001/* 002 * Copyright (C) 2015-2023 The Prometheus jmx_exporter Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package io.prometheus.jmx; 018 019import io.prometheus.jmx.logger.Logger; 020import io.prometheus.jmx.logger.LoggerFactory; 021import java.util.Collections; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.concurrent.ConcurrentHashMap; 027import java.util.logging.Level; 028import javax.management.MalformedObjectNameException; 029import javax.management.ObjectName; 030 031/** Class to implement filtering of an MBean's attributes based on the attribute's name */ 032@SuppressWarnings("unchecked") 033public class ObjectNameAttributeFilter { 034 035 private static final Logger LOGGER = LoggerFactory.getLogger(ObjectNameAttributeFilter.class); 036 037 /** Configuration constant to define a mapping of ObjectNames to attribute names */ 038 public static final String EXCLUDE_OBJECT_NAME_ATTRIBUTES = "excludeObjectNameAttributes"; 039 040 /** Configuration constant to enable auto ObjectName attributes filtering */ 041 public static final String AUTO_EXCLUDE_OBJECT_NAME_ATTRIBUTES = 042 "autoExcludeObjectNameAttributes"; 043 044 private final Map<ObjectName, Set<String>> excludeObjectNameAttributesMap; 045 046 private boolean autoExcludeObjectNameAttributes; 047 048 /** Constructor */ 049 private ObjectNameAttributeFilter() { 050 excludeObjectNameAttributesMap = new ConcurrentHashMap<>(); 051 } 052 053 /** 054 * Method to initialize the ObjectNameAttributeFilter 055 * 056 * @param yamlConfig yamlConfig 057 * @return an ObjectNameAttributeFilter 058 * @throws MalformedObjectNameException MalformedObjectNameException 059 */ 060 private ObjectNameAttributeFilter initialize(Map<String, Object> yamlConfig) 061 throws MalformedObjectNameException { 062 if (yamlConfig.containsKey(EXCLUDE_OBJECT_NAME_ATTRIBUTES)) { 063 Map<Object, Object> objectNameAttributeMap = 064 (Map<Object, Object>) yamlConfig.get(EXCLUDE_OBJECT_NAME_ATTRIBUTES); 065 066 for (Map.Entry<Object, Object> entry : objectNameAttributeMap.entrySet()) { 067 ObjectName objectName = new ObjectName((String) entry.getKey()); 068 069 List<String> attributeNames = (List<String>) entry.getValue(); 070 071 Set<String> attributeNameSet = 072 excludeObjectNameAttributesMap.computeIfAbsent( 073 objectName, o -> Collections.synchronizedSet(new HashSet<>())); 074 075 attributeNameSet.addAll(attributeNames); 076 for (String attribueName : attributeNames) { 077 attributeNameSet.add(attribueName); 078 } 079 080 excludeObjectNameAttributesMap.put(objectName, attributeNameSet); 081 } 082 } 083 084 if (yamlConfig.containsKey(AUTO_EXCLUDE_OBJECT_NAME_ATTRIBUTES)) { 085 autoExcludeObjectNameAttributes = 086 (Boolean) yamlConfig.get(AUTO_EXCLUDE_OBJECT_NAME_ATTRIBUTES); 087 } else { 088 autoExcludeObjectNameAttributes = true; 089 } 090 091 LOGGER.log(Level.FINE, "dynamicExclusion [%b]", autoExcludeObjectNameAttributes); 092 093 return this; 094 } 095 096 /** 097 * Method to add an attribute name to the filter if dynamic exclusion is enabled 098 * 099 * @param objectName the ObjectName 100 * @param attributeName the attribute name 101 */ 102 public void add(ObjectName objectName, String attributeName) { 103 if (autoExcludeObjectNameAttributes) { 104 Set<String> attribteNameSet = 105 excludeObjectNameAttributesMap.computeIfAbsent( 106 objectName, o -> Collections.synchronizedSet(new HashSet<>())); 107 108 LOGGER.log( 109 Level.FINE, 110 "auto adding exclusion of object name [%s] attribute name [%s]", 111 objectName.getCanonicalName(), 112 attributeName); 113 114 attribteNameSet.add(attributeName); 115 } 116 } 117 118 /** 119 * Method to check if an attribute should be excluded 120 * 121 * @param objectName the ObjectName 122 * @param attributeName the attribute name 123 * @return true if it should be excluded, false otherwise 124 */ 125 public boolean exclude(ObjectName objectName, String attributeName) { 126 boolean result = false; 127 128 if (excludeObjectNameAttributesMap.size() > 0) { 129 Set<String> attributeNameSet = excludeObjectNameAttributesMap.get(objectName); 130 if (attributeNameSet != null) { 131 result = attributeNameSet.contains(attributeName); 132 } 133 } 134 135 return result; 136 } 137 138 /** 139 * Method to create an ObjectNameAttributeFilter 140 * 141 * @param yamlConfig yamlConfig 142 * @return an ObjectNameAttributeFilter 143 */ 144 public static ObjectNameAttributeFilter create(Map<String, Object> yamlConfig) { 145 try { 146 return new ObjectNameAttributeFilter().initialize(yamlConfig); 147 } catch (MalformedObjectNameException e) { 148 throw new RuntimeException( 149 "Invalid configuration format for excludeObjectNameAttributes", e); 150 } 151 } 152}