1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.metrics.impl;
19
20 import com.google.common.base.Optional;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Map.Entry;
28 import java.util.concurrent.TimeUnit;
29 import java.util.concurrent.atomic.AtomicBoolean;
30 import org.apache.commons.lang.reflect.FieldUtils;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.hbase.metrics.MetricRegistries;
34 import org.apache.hadoop.hbase.metrics.MetricRegistry;
35 import org.apache.hadoop.hbase.metrics.MetricRegistryInfo;
36 import org.apache.hadoop.metrics2.MetricsCollector;
37 import org.apache.hadoop.metrics2.MetricsExecutor;
38 import org.apache.hadoop.metrics2.MetricsSource;
39 import org.apache.hadoop.metrics2.MetricsSystem;
40 import org.apache.hadoop.metrics2.impl.JmxCacheBuster;
41 import org.apache.hadoop.metrics2.impl.MetricsSystemImpl;
42 import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
43 import org.apache.hadoop.metrics2.lib.DefaultMetricsSystemHelper;
44 import org.apache.hadoop.metrics2.lib.MetricsExecutorImpl;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public class GlobalMetricRegistriesAdapter {
69
70 private static final Log LOG = LogFactory.getLog(GlobalMetricRegistriesAdapter.class);
71
72 private class MetricsSourceAdapter implements MetricsSource {
73 private final MetricRegistry registry;
74 MetricsSourceAdapter(MetricRegistry registry) {
75 this.registry = registry;
76 }
77
78 @Override
79 public void getMetrics(MetricsCollector collector, boolean all) {
80 metricsAdapter.snapshotAllMetrics(registry, collector);
81 }
82 }
83
84 private final MetricsExecutor executor;
85 private final AtomicBoolean stopped;
86 private final DefaultMetricsSystemHelper helper;
87 private final HBaseMetrics2HadoopMetricsAdapter metricsAdapter;
88 private final HashMap<MetricRegistryInfo, MetricsSourceAdapter> registeredSources;
89
90 private GlobalMetricRegistriesAdapter() {
91 this.executor = new MetricsExecutorImpl();
92 this.stopped = new AtomicBoolean(false);
93 this.metricsAdapter = new HBaseMetrics2HadoopMetricsAdapter();
94 this.registeredSources = new HashMap<>();
95 this.helper = new DefaultMetricsSystemHelper();
96 executor.getExecutor().scheduleAtFixedRate(new Runnable(){
97 @Override
98 public void run() {
99 doRun();
100
101 }}, 10, 10, TimeUnit.SECONDS);
102 }
103
104
105
106
107
108 public static GlobalMetricRegistriesAdapter init() {
109 return new GlobalMetricRegistriesAdapter();
110 }
111
112 public void stop() {
113 stopped.set(true);
114 }
115
116 private void doRun() {
117 if (stopped.get()) {
118 executor.stop();
119 return;
120 }
121 if (LOG.isTraceEnabled()) {
122 LOG.trace("doRun called: " + registeredSources);
123 }
124
125 Collection<MetricRegistry> registries = MetricRegistries.global().getMetricRegistries();
126 for (MetricRegistry registry : registries) {
127 MetricRegistryInfo info = registry.getMetricRegistryInfo();
128
129 if (info.isExistingSource()) {
130
131
132
133
134
135
136 continue;
137 }
138
139 if (!registeredSources.containsKey(info)) {
140 if (LOG.isDebugEnabled()) {
141 LOG.debug("Registering adapter for the MetricRegistry: " + info.getMetricsJmxContext());
142 }
143
144 MetricsSourceAdapter adapter = new MetricsSourceAdapter(registry);
145 LOG.info("Registering " + info.getMetricsJmxContext() + " " + info.getMetricsDescription());
146 DefaultMetricsSystem.instance().register(info.getMetricsJmxContext(),
147 info.getMetricsDescription(), adapter);
148 registeredSources.put(info, adapter);
149
150
151 }
152 }
153
154 boolean removed = false;
155
156 for (Iterator<Entry<MetricRegistryInfo, MetricsSourceAdapter>> it =
157 registeredSources.entrySet().iterator(); it.hasNext();) {
158 Entry<MetricRegistryInfo, MetricsSourceAdapter> entry = it.next();
159 MetricRegistryInfo info = entry.getKey();
160 Optional<MetricRegistry> found = MetricRegistries.global().get(info);
161 if (!found.isPresent()) {
162 if (LOG.isDebugEnabled()) {
163 LOG.debug("Removing adapter for the MetricRegistry: " + info.getMetricsJmxContext());
164 }
165 synchronized(DefaultMetricsSystem.instance()) {
166 unregisterSource(info);
167 helper.removeSourceName(info.getMetricsJmxContext());
168 helper.removeObjectName(info.getMetricsJmxContext());
169 it.remove();
170 removed = true;
171 }
172 }
173 }
174 if (removed) {
175 JmxCacheBuster.clearJmxCache();
176 }
177 }
178
179
180
181
182
183 protected void unregisterSource(MetricRegistryInfo info) {
184
185 MetricsSystem metricsSystem = DefaultMetricsSystem.instance();
186 if (metricsSystem instanceof MetricsSystemImpl) {
187 try {
188
189
190 @SuppressWarnings("unchecked")
191 Map<String, Object> sources =
192 (Map<String, Object>) FieldUtils.readField(metricsSystem, "sources", true);
193 String sourceName = info.getMetricsJmxContext();
194 if (sources.containsKey(sourceName)) {
195 Object sourceAdapter = sources.get(sourceName);
196 Method method = null;
197 try {
198 method = sourceAdapter.getClass().getDeclaredMethod("stop");
199 } catch (NoSuchMethodException e) {
200 LOG.info("Stop method not found on MetricsSourceAdapter");
201 } catch (SecurityException e) {
202 LOG.info("Don't have access to call stop method not found on MetricsSourceAdapter", e);
203 }
204 if (method != null) {
205 method.setAccessible(true);
206 try {
207 method.invoke(sourceAdapter);
208 } catch (IllegalArgumentException | InvocationTargetException e) {
209 LOG.warn("Couldn't invoke stop on metrics source adapter: " + sourceName);
210 e.printStackTrace();
211 }
212 }
213 sources.remove(sourceName);
214
215 }
216 @SuppressWarnings("unchecked")
217 Map<String, MetricsSource> allSources =
218 (Map<String, MetricsSource>) FieldUtils.readField(metricsSystem, "allSources", true);
219 if (allSources.containsKey(sourceName)) {
220 allSources.remove(sourceName);
221 }
222 } catch (IllegalAccessException e) {
223 LOG.warn("Error unregistering metric source " + info.getMetricsJmxContext());
224 }
225 }
226 }
227 }