001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.regionserver; 020 021import java.util.Collections; 022import java.util.Set; 023import java.util.concurrent.ConcurrentHashMap; 024import java.util.concurrent.TimeUnit; 025 026import org.apache.hadoop.hbase.metrics.BaseSourceImpl; 027import org.apache.hadoop.metrics2.MetricsCollector; 028import org.apache.hadoop.metrics2.MetricsRecordBuilder; 029import org.apache.hadoop.metrics2.impl.JmxCacheBuster; 030import org.apache.hadoop.metrics2.lib.MetricsExecutorImpl; 031import org.apache.yetus.audience.InterfaceAudience; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035@InterfaceAudience.Private 036public class MetricsRegionAggregateSourceImpl extends BaseSourceImpl 037 implements MetricsRegionAggregateSource { 038 039 private static final Logger LOG = LoggerFactory.getLogger(MetricsRegionAggregateSourceImpl.class); 040 041 private final MetricsExecutorImpl executor = new MetricsExecutorImpl(); 042 043 private final Set<MetricsRegionSource> regionSources = 044 Collections.newSetFromMap(new ConcurrentHashMap<MetricsRegionSource, Boolean>()); 045 046 public MetricsRegionAggregateSourceImpl() { 047 this(METRICS_NAME, METRICS_DESCRIPTION, METRICS_CONTEXT, METRICS_JMX_CONTEXT); 048 } 049 050 051 public MetricsRegionAggregateSourceImpl(String metricsName, 052 String metricsDescription, 053 String metricsContext, 054 String metricsJmxContext) { 055 super(metricsName, metricsDescription, metricsContext, metricsJmxContext); 056 057 // Every few mins clean the JMX cache. 058 executor.getExecutor().scheduleWithFixedDelay(new Runnable() { 059 public void run() { 060 JmxCacheBuster.clearJmxCache(); 061 } 062 }, 5, 5, TimeUnit.MINUTES); 063 } 064 065 @Override 066 public void register(MetricsRegionSource source) { 067 regionSources.add(source); 068 clearCache(); 069 } 070 071 @Override 072 public void deregister(MetricsRegionSource toRemove) { 073 try { 074 regionSources.remove(toRemove); 075 } catch (Exception e) { 076 // Ignored. If this errors out it means that someone is double 077 // closing the region source and the region is already nulled out. 078 LOG.info( 079 "Error trying to remove " + toRemove + " from " + this.getClass().getSimpleName(), 080 e); 081 } 082 clearCache(); 083 } 084 085 private synchronized void clearCache() { 086 JmxCacheBuster.clearJmxCache(); 087 } 088 089 /** 090 * Yes this is a get function that doesn't return anything. Thanks Hadoop for breaking all 091 * expectations of java programmers. Instead of returning anything Hadoop metrics expects 092 * getMetrics to push the metrics into the collector. 093 * 094 * @param collector the collector 095 * @param all get all the metrics regardless of when they last changed. 096 */ 097 @Override 098 public void getMetrics(MetricsCollector collector, boolean all) { 099 MetricsRecordBuilder mrb = collector.addRecord(metricsName); 100 101 if (regionSources != null) { 102 for (MetricsRegionSource regionMetricSource : regionSources) { 103 if (regionMetricSource instanceof MetricsRegionSourceImpl) { 104 ((MetricsRegionSourceImpl) regionMetricSource).snapshot(mrb, all); 105 } 106 } 107 metricsRegistry.snapshot(mrb, all); 108 } 109 } 110}