/** * 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.metrics.jvm; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; 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 static java.lang.Thread.State.*; import java.lang.management.GarbageCollectorMXBean; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Singleton class which reports Java Virtual Machine metrics to the metrics API. * Any application can create an instance of this class in order to emit * Java VM metrics. * @deprecated in favor of <code>org.apache.hadoop.metrics2</code> usage. */ @Deprecated @InterfaceAudience.Private @InterfaceStability.Evolving public class JvmMetrics implements Updater { private static final float M = 1024*1024; private static JvmMetrics theInstance = null; private static Log log = LogFactory.getLog(JvmMetrics.class); private MetricsRecord metrics; // garbage collection counters private long gcCount = 0; private long gcTimeMillis = 0; // logging event counters private long fatalCount = 0; private long errorCount = 0; private long warnCount = 0; private long infoCount = 0; public synchronized static JvmMetrics init(String processName, String sessionId) { return init(processName, sessionId, "metrics"); } public synchronized static JvmMetrics init(String processName, String sessionId, String recordName) { if (theInstance != null) { log.info("Cannot initialize JVM Metrics with processName=" + processName + ", sessionId=" + sessionId + " - already initialized"); } else { log.info("Initializing JVM Metrics with processName=" + processName + ", sessionId=" + sessionId); theInstance = new JvmMetrics(processName, sessionId, recordName); } return theInstance; } /** Creates a new instance of JvmMetrics */ private JvmMetrics(String processName, String sessionId, String recordName) { MetricsContext context = MetricsUtil.getContext("jvm"); metrics = MetricsUtil.createRecord(context, recordName); metrics.setTag("processName", processName); metrics.setTag("sessionId", sessionId); context.registerUpdater(this); } /** * This will be called periodically (with the period being configuration * dependent). */ public void doUpdates(MetricsContext context) { doMemoryUpdates(); doGarbageCollectionUpdates(); doThreadUpdates(); doEventCountUpdates(); metrics.update(); } private void doMemoryUpdates() { MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); MemoryUsage memNonHeap = memoryMXBean.getNonHeapMemoryUsage(); MemoryUsage memHeap = memoryMXBean.getHeapMemoryUsage(); Runtime runtime = Runtime.getRuntime(); metrics.setMetric("memNonHeapUsedM", memNonHeap.getUsed()/M); metrics.setMetric("memNonHeapCommittedM", memNonHeap.getCommitted()/M); metrics.setMetric("memHeapUsedM", memHeap.getUsed()/M); metrics.setMetric("memHeapCommittedM", memHeap.getCommitted()/M); metrics.setMetric("maxMemoryM", runtime.maxMemory()/M); } private void doGarbageCollectionUpdates() { List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); long count = 0; long timeMillis = 0; for (GarbageCollectorMXBean gcBean : gcBeans) { count += gcBean.getCollectionCount(); timeMillis += gcBean.getCollectionTime(); } metrics.incrMetric("gcCount", (int)(count - gcCount)); metrics.incrMetric("gcTimeMillis", (int)(timeMillis - gcTimeMillis)); gcCount = count; gcTimeMillis = timeMillis; } private void doThreadUpdates() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long threadIds[] = threadMXBean.getAllThreadIds(); ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds, 0); int threadsNew = 0; int threadsRunnable = 0; int threadsBlocked = 0; int threadsWaiting = 0; int threadsTimedWaiting = 0; int threadsTerminated = 0; for (ThreadInfo threadInfo : threadInfos) { // threadInfo is null if the thread is not alive or doesn't exist if (threadInfo == null) continue; Thread.State state = threadInfo.getThreadState(); if (state == NEW) { threadsNew++; } else if (state == RUNNABLE) { threadsRunnable++; } else if (state == BLOCKED) { threadsBlocked++; } else if (state == WAITING) { threadsWaiting++; } else if (state == TIMED_WAITING) { threadsTimedWaiting++; } else if (state == TERMINATED) { threadsTerminated++; } } metrics.setMetric("threadsNew", threadsNew); metrics.setMetric("threadsRunnable", threadsRunnable); metrics.setMetric("threadsBlocked", threadsBlocked); metrics.setMetric("threadsWaiting", threadsWaiting); metrics.setMetric("threadsTimedWaiting", threadsTimedWaiting); metrics.setMetric("threadsTerminated", threadsTerminated); } private void doEventCountUpdates() { long newFatal = EventCounter.getFatal(); long newError = EventCounter.getError(); long newWarn = EventCounter.getWarn(); long newInfo = EventCounter.getInfo(); metrics.incrMetric("logFatal", (int)(newFatal - fatalCount)); metrics.incrMetric("logError", (int)(newError - errorCount)); metrics.incrMetric("logWarn", (int)(newWarn - warnCount)); metrics.incrMetric("logInfo", (int)(newInfo - infoCount)); fatalCount = newFatal; errorCount = newError; warnCount = newWarn; infoCount = newInfo; } }