001/* 002 * Copyright (C) 2020-present 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 java.util.Collection; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.Map; 023import java.util.Set; 024import java.util.concurrent.ConcurrentHashMap; 025 026/** 027 * MatchedRulesCache is a cache for bean name to configured rule mapping (See 028 * JmxCollector.Receiver). The cache also retains unmatched entries (a bean name not matching a rule 029 * pattern) to avoid matching against the same pattern in later bean collections. 030 */ 031public class MatchedRulesCache { 032 private final Map<JmxCollector.Rule, Map<String, MatchedRule>> cachedRules; 033 034 public MatchedRulesCache(Collection<JmxCollector.Rule> rules) { 035 this.cachedRules = new HashMap<>(rules.size()); 036 for (JmxCollector.Rule rule : rules) { 037 this.cachedRules.put(rule, new ConcurrentHashMap<>()); 038 } 039 } 040 041 public void put( 042 final JmxCollector.Rule rule, final String cacheKey, final MatchedRule matchedRule) { 043 Map<String, MatchedRule> cachedRulesForRule = cachedRules.get(rule); 044 cachedRulesForRule.put(cacheKey, matchedRule); 045 } 046 047 public MatchedRule get(final JmxCollector.Rule rule, final String cacheKey) { 048 return cachedRules.get(rule).get(cacheKey); 049 } 050 051 // Remove stale rules (in the cache but not collected in the last run of the collector) 052 public void evictStaleEntries(final StalenessTracker stalenessTracker) { 053 for (Map.Entry<JmxCollector.Rule, Map<String, MatchedRule>> entry : 054 cachedRules.entrySet()) { 055 JmxCollector.Rule rule = entry.getKey(); 056 Map<String, MatchedRule> cachedRulesForRule = entry.getValue(); 057 058 for (String cacheKey : cachedRulesForRule.keySet()) { 059 if (!stalenessTracker.contains(rule, cacheKey)) { 060 cachedRulesForRule.remove(cacheKey); 061 } 062 } 063 } 064 } 065 066 public static class StalenessTracker { 067 private final Map<JmxCollector.Rule, Set<String>> lastCachedEntries = new HashMap<>(); 068 069 public void add(final JmxCollector.Rule rule, final String cacheKey) { 070 Set<String> lastCachedEntriesForRule = 071 lastCachedEntries.computeIfAbsent(rule, k -> new HashSet<>()); 072 lastCachedEntriesForRule.add(cacheKey); 073 } 074 075 public boolean contains(final JmxCollector.Rule rule, final String cacheKey) { 076 Set<String> lastCachedEntriesForRule = lastCachedEntries.get(rule); 077 return (lastCachedEntriesForRule != null) 078 && lastCachedEntriesForRule.contains(cacheKey); 079 } 080 081 public long cachedCount() { 082 long count = 0; 083 for (Set<String> cacheKeys : lastCachedEntries.values()) { 084 count += cacheKeys.size(); 085 } 086 return count; 087 } 088 } 089}