| /** |
| * Copyright 2010 The Apache Software Foundation |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.hadoop.hbase.regionserver.metrics; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.hbase.io.hfile.HFile; |
| import org.apache.hadoop.hbase.metrics.HBaseInfo; |
| import org.apache.hadoop.hbase.metrics.MetricsRate; |
| import org.apache.hadoop.hbase.metrics.PersistentMetricsTimeVaryingRate; |
| import org.apache.hadoop.hbase.regionserver.wal.HLog; |
| import org.apache.hadoop.hbase.util.Pair; |
| import org.apache.hadoop.hbase.util.Strings; |
| import org.apache.hadoop.metrics.ContextFactory; |
| import org.apache.hadoop.metrics.MetricsContext; |
| import org.apache.hadoop.metrics.MetricsRecord; |
| import org.apache.hadoop.metrics.MetricsUtil; |
| import org.apache.hadoop.metrics.Updater; |
| import org.apache.hadoop.metrics.jvm.JvmMetrics; |
| import org.apache.hadoop.metrics.util.MetricsIntValue; |
| import org.apache.hadoop.metrics.util.MetricsLongValue; |
| import org.apache.hadoop.metrics.util.MetricsRegistry; |
| import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate; |
| |
| import java.io.IOException; |
| import java.lang.management.ManagementFactory; |
| import java.lang.management.MemoryUsage; |
| import java.util.List; |
| |
| /** |
| * This class is for maintaining the various regionserver statistics |
| * and publishing them through the metrics interfaces. |
| * <p> |
| * This class has a number of metrics variables that are publicly accessible; |
| * these variables (objects) have methods to update their values. |
| */ |
| public class RegionServerMetrics implements Updater { |
| @SuppressWarnings({"FieldCanBeLocal"}) |
| private final Log LOG = LogFactory.getLog(this.getClass()); |
| private final MetricsRecord metricsRecord; |
| private long lastUpdate = System.currentTimeMillis(); |
| private long lastExtUpdate = System.currentTimeMillis(); |
| private long extendedPeriod = 0; |
| private static final int MB = 1024*1024; |
| private MetricsRegistry registry = new MetricsRegistry(); |
| private final RegionServerStatistics statistics; |
| |
| public final MetricsTimeVaryingRate atomicIncrementTime = |
| new MetricsTimeVaryingRate("atomicIncrementTime", registry); |
| |
| /** |
| * Count of regions carried by this regionserver |
| */ |
| public final MetricsIntValue regions = |
| new MetricsIntValue("regions", registry); |
| |
| /** |
| * Block cache size. |
| */ |
| public final MetricsLongValue blockCacheSize = new MetricsLongValue("blockCacheSize", registry); |
| |
| /** |
| * Block cache free size. |
| */ |
| public final MetricsLongValue blockCacheFree = new MetricsLongValue("blockCacheFree", registry); |
| |
| /** |
| * Block cache item count. |
| */ |
| public final MetricsLongValue blockCacheCount = new MetricsLongValue("blockCacheCount", registry); |
| |
| /** |
| * Block cache hit count. |
| */ |
| public final MetricsLongValue blockCacheHitCount = new MetricsLongValue("blockCacheHitCount", registry); |
| |
| /** |
| * Block cache miss count. |
| */ |
| public final MetricsLongValue blockCacheMissCount = new MetricsLongValue("blockCacheMissCount", registry); |
| |
| /** |
| * Block cache evict count. |
| */ |
| public final MetricsLongValue blockCacheEvictedCount = new MetricsLongValue("blockCacheEvictedCount", registry); |
| |
| /** |
| * Block hit ratio. |
| */ |
| public final MetricsIntValue blockCacheHitRatio = new MetricsIntValue("blockCacheHitRatio", registry); |
| |
| /** |
| * Block hit caching ratio. This only includes the requests to the block |
| * cache where caching was turned on. See HBASE-2253. |
| */ |
| public final MetricsIntValue blockCacheHitCachingRatio = new MetricsIntValue("blockCacheHitCachingRatio", registry); |
| |
| /* |
| * Count of requests to the regionservers since last call to metrics update |
| */ |
| private final MetricsRate requests = new MetricsRate("requests", registry); |
| |
| /** |
| * Count of stores open on the regionserver. |
| */ |
| public final MetricsIntValue stores = new MetricsIntValue("stores", registry); |
| |
| /** |
| * Count of storefiles open on the regionserver. |
| */ |
| public final MetricsIntValue storefiles = new MetricsIntValue("storefiles", registry); |
| |
| /** |
| * Sum of all the storefile index sizes in this regionserver in MB |
| */ |
| public final MetricsIntValue storefileIndexSizeMB = |
| new MetricsIntValue("storefileIndexSizeMB", registry); |
| |
| /** |
| * Sum of all the memstore sizes in this regionserver in MB |
| */ |
| public final MetricsIntValue memstoreSizeMB = |
| new MetricsIntValue("memstoreSizeMB", registry); |
| |
| /** |
| * Size of the compaction queue. |
| */ |
| public final MetricsIntValue compactionQueueSize = |
| new MetricsIntValue("compactionQueueSize", registry); |
| |
| /** |
| * filesystem read latency |
| */ |
| public final MetricsTimeVaryingRate fsReadLatency = |
| new MetricsTimeVaryingRate("fsReadLatency", registry); |
| |
| /** |
| * filesystem write latency |
| */ |
| public final MetricsTimeVaryingRate fsWriteLatency = |
| new MetricsTimeVaryingRate("fsWriteLatency", registry); |
| |
| /** |
| * filesystem sync latency |
| */ |
| public final MetricsTimeVaryingRate fsSyncLatency = |
| new MetricsTimeVaryingRate("fsSyncLatency", registry); |
| |
| /** |
| * time each scheduled compaction takes |
| */ |
| protected final PersistentMetricsTimeVaryingRate compactionTime = |
| new PersistentMetricsTimeVaryingRate("compactionTime", registry); |
| |
| protected final PersistentMetricsTimeVaryingRate compactionSize = |
| new PersistentMetricsTimeVaryingRate("compactionSize", registry); |
| |
| /** |
| * time each scheduled flush takes |
| */ |
| protected final PersistentMetricsTimeVaryingRate flushTime = |
| new PersistentMetricsTimeVaryingRate("flushTime", registry); |
| |
| protected final PersistentMetricsTimeVaryingRate flushSize = |
| new PersistentMetricsTimeVaryingRate("flushSize", registry); |
| |
| public RegionServerMetrics() { |
| MetricsContext context = MetricsUtil.getContext("hbase"); |
| metricsRecord = MetricsUtil.createRecord(context, "regionserver"); |
| String name = Thread.currentThread().getName(); |
| metricsRecord.setTag("RegionServer", name); |
| context.registerUpdater(this); |
| // Add jvmmetrics. |
| JvmMetrics.init("RegionServer", name); |
| // Add Hbase Info metrics |
| HBaseInfo.init(); |
| |
| // export for JMX |
| statistics = new RegionServerStatistics(this.registry, name); |
| |
| // get custom attributes |
| try { |
| Object m = ContextFactory.getFactory().getAttribute("hbase.extendedperiod"); |
| if (m instanceof String) { |
| this.extendedPeriod = Long.parseLong((String) m)*1000; |
| } |
| } catch (IOException ioe) { |
| LOG.info("Couldn't load ContextFactory for Metrics config info"); |
| } |
| |
| LOG.info("Initialized"); |
| } |
| |
| public void shutdown() { |
| if (statistics != null) |
| statistics.shutdown(); |
| } |
| |
| /** |
| * Since this object is a registered updater, this method will be called |
| * periodically, e.g. every 5 seconds. |
| * @param caller the metrics context that this responsible for calling us |
| */ |
| public void doUpdates(MetricsContext caller) { |
| synchronized (this) { |
| this.lastUpdate = System.currentTimeMillis(); |
| |
| // has the extended period for long-living stats elapsed? |
| if (this.extendedPeriod > 0 && |
| this.lastUpdate - this.lastExtUpdate >= this.extendedPeriod) { |
| this.lastExtUpdate = this.lastUpdate; |
| this.compactionTime.resetMinMaxAvg(); |
| this.compactionSize.resetMinMaxAvg(); |
| this.flushTime.resetMinMaxAvg(); |
| this.flushSize.resetMinMaxAvg(); |
| this.resetAllMinMax(); |
| } |
| |
| this.stores.pushMetric(this.metricsRecord); |
| this.storefiles.pushMetric(this.metricsRecord); |
| this.storefileIndexSizeMB.pushMetric(this.metricsRecord); |
| this.memstoreSizeMB.pushMetric(this.metricsRecord); |
| this.regions.pushMetric(this.metricsRecord); |
| this.requests.pushMetric(this.metricsRecord); |
| this.compactionQueueSize.pushMetric(this.metricsRecord); |
| this.blockCacheSize.pushMetric(this.metricsRecord); |
| this.blockCacheFree.pushMetric(this.metricsRecord); |
| this.blockCacheCount.pushMetric(this.metricsRecord); |
| this.blockCacheHitCount.pushMetric(this.metricsRecord); |
| this.blockCacheMissCount.pushMetric(this.metricsRecord); |
| this.blockCacheEvictedCount.pushMetric(this.metricsRecord); |
| this.blockCacheHitRatio.pushMetric(this.metricsRecord); |
| this.blockCacheHitCachingRatio.pushMetric(this.metricsRecord); |
| |
| // Mix in HFile and HLog metrics |
| // Be careful. Here is code for MTVR from up in hadoop: |
| // public synchronized void inc(final int numOps, final long time) { |
| // currentData.numOperations += numOps; |
| // currentData.time += time; |
| // long timePerOps = time/numOps; |
| // minMax.update(timePerOps); |
| // } |
| // Means you can't pass a numOps of zero or get a ArithmeticException / by zero. |
| int ops = (int)HFile.getReadOps(); |
| if (ops != 0) this.fsReadLatency.inc(ops, HFile.getReadTime()); |
| ops = (int)HFile.getWriteOps(); |
| if (ops != 0) this.fsWriteLatency.inc(ops, HFile.getWriteTime()); |
| // mix in HLog metrics |
| ops = (int)HLog.getWriteOps(); |
| if (ops != 0) this.fsWriteLatency.inc(ops, HLog.getWriteTime()); |
| ops = (int)HLog.getSyncOps(); |
| if (ops != 0) this.fsSyncLatency.inc(ops, HLog.getSyncTime()); |
| |
| // push the result |
| this.fsReadLatency.pushMetric(this.metricsRecord); |
| this.fsWriteLatency.pushMetric(this.metricsRecord); |
| this.fsSyncLatency.pushMetric(this.metricsRecord); |
| this.compactionTime.pushMetric(this.metricsRecord); |
| this.compactionSize.pushMetric(this.metricsRecord); |
| this.flushTime.pushMetric(this.metricsRecord); |
| this.flushSize.pushMetric(this.metricsRecord); |
| } |
| this.metricsRecord.update(); |
| } |
| |
| public void resetAllMinMax() { |
| this.atomicIncrementTime.resetMinMax(); |
| this.fsReadLatency.resetMinMax(); |
| this.fsWriteLatency.resetMinMax(); |
| this.fsSyncLatency.resetMinMax(); |
| } |
| |
| /** |
| * @return Count of requests. |
| */ |
| public float getRequests() { |
| return this.requests.getPreviousIntervalValue(); |
| } |
| |
| /** |
| * @param compact history in <time, size> |
| */ |
| public synchronized void addCompaction(final Pair<Long,Long> compact) { |
| this.compactionTime.inc(compact.getFirst()); |
| this.compactionSize.inc(compact.getSecond()); |
| } |
| |
| /** |
| * @param flushes history in <time, size> |
| */ |
| public synchronized void addFlush(final List<Pair<Long,Long>> flushes) { |
| for (Pair<Long,Long> f : flushes) { |
| this.flushTime.inc(f.getFirst()); |
| this.flushSize.inc(f.getSecond()); |
| } |
| } |
| |
| /** |
| * @param inc How much to add to requests. |
| */ |
| public void incrementRequests(final int inc) { |
| this.requests.inc(inc); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| int seconds = (int)((System.currentTimeMillis() - this.lastUpdate)/1000); |
| if (seconds == 0) { |
| seconds = 1; |
| } |
| sb = Strings.appendKeyValue(sb, "request", |
| Float.valueOf(this.requests.getPreviousIntervalValue())); |
| sb = Strings.appendKeyValue(sb, "regions", |
| Integer.valueOf(this.regions.get())); |
| sb = Strings.appendKeyValue(sb, "stores", |
| Integer.valueOf(this.stores.get())); |
| sb = Strings.appendKeyValue(sb, "storefiles", |
| Integer.valueOf(this.storefiles.get())); |
| sb = Strings.appendKeyValue(sb, "storefileIndexSize", |
| Integer.valueOf(this.storefileIndexSizeMB.get())); |
| sb = Strings.appendKeyValue(sb, "memstoreSize", |
| Integer.valueOf(this.memstoreSizeMB.get())); |
| sb = Strings.appendKeyValue(sb, "compactionQueueSize", |
| Integer.valueOf(this.compactionQueueSize.get())); |
| // Duplicate from jvmmetrics because metrics are private there so |
| // inaccessible. |
| MemoryUsage memory = |
| ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); |
| sb = Strings.appendKeyValue(sb, "usedHeap", |
| Long.valueOf(memory.getUsed()/MB)); |
| sb = Strings.appendKeyValue(sb, "maxHeap", |
| Long.valueOf(memory.getMax()/MB)); |
| sb = Strings.appendKeyValue(sb, this.blockCacheSize.getName(), |
| Long.valueOf(this.blockCacheSize.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheFree.getName(), |
| Long.valueOf(this.blockCacheFree.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheCount.getName(), |
| Long.valueOf(this.blockCacheCount.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheHitCount.getName(), |
| Long.valueOf(this.blockCacheHitCount.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheMissCount.getName(), |
| Long.valueOf(this.blockCacheMissCount.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheEvictedCount.getName(), |
| Long.valueOf(this.blockCacheEvictedCount.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheHitRatio.getName(), |
| Long.valueOf(this.blockCacheHitRatio.get())); |
| sb = Strings.appendKeyValue(sb, this.blockCacheHitCachingRatio.getName(), |
| Long.valueOf(this.blockCacheHitCachingRatio.get())); |
| return sb.toString(); |
| } |
| } |