diff --git common/src/java/org/apache/hadoop/hive/common/JvmMetrics.java common/src/java/org/apache/hadoop/hive/common/JvmMetrics.java new file mode 100644 index 0000000..64f2819 --- /dev/null +++ common/src/java/org/apache/hadoop/hive/common/JvmMetrics.java @@ -0,0 +1,187 @@ +/** + * 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.hive.common; + +import static org.apache.hadoop.hive.common.JvmMetricsInfo.*; + +import org.apache.hadoop.log.metrics.EventCounter; +import org.apache.hadoop.metrics2.MetricsCollector; +import org.apache.hadoop.metrics2.MetricsInfo; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.metrics2.MetricsSource; +import org.apache.hadoop.metrics2.MetricsSystem; +import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.apache.hadoop.metrics2.lib.Interns; + +import java.lang.management.GarbageCollectorMXBean; +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 java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import static org.apache.hadoop.metrics2.impl.MsInfo.ProcessName; +import static org.apache.hadoop.metrics2.impl.MsInfo.SessionId; + +/** + * JVM and logging related metrics. Ported from Hadoop JvmMetrics. + * Mostly used by various servers as a part of the metrics they export. + */ +public class JvmMetrics implements MetricsSource { + enum Singleton { + INSTANCE; + + JvmMetrics impl; + + synchronized JvmMetrics init(String processName, String sessionId) { + if (impl == null) { + impl = create(processName, sessionId, DefaultMetricsSystem.instance()); + } + return impl; + } + } + + static final float M = 1024*1024; + + final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + final List gcBeans = + ManagementFactory.getGarbageCollectorMXBeans(); + final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + final String processName, sessionId; + private JvmPauseMonitor pauseMonitor = null; + final ConcurrentHashMap gcInfoCache = + new ConcurrentHashMap(); + + JvmMetrics(String processName, String sessionId) { + this.processName = processName; + this.sessionId = sessionId; + } + + public void setPauseMonitor(final JvmPauseMonitor pauseMonitor) { + this.pauseMonitor = pauseMonitor; + } + + public static JvmMetrics create(String processName, String sessionId, MetricsSystem ms) { + return ms.register(JvmMetrics.name(), JvmMetrics.description(), + new JvmMetrics(processName, sessionId)); + } + + public static JvmMetrics initSingleton(String processName, String sessionId) { + return Singleton.INSTANCE.init(processName, sessionId); + } + + @Override + public void getMetrics(MetricsCollector collector, boolean all) { + MetricsRecordBuilder rb = collector.addRecord(JvmMetrics) + .setContext("jvm").tag(ProcessName, processName) + .tag(SessionId, sessionId); + getMemoryUsage(rb); + getGcUsage(rb); + getThreadUsage(rb); + getEventCounters(rb); + } + + private void getMemoryUsage(MetricsRecordBuilder rb) { + MemoryUsage memNonHeap = memoryMXBean.getNonHeapMemoryUsage(); + MemoryUsage memHeap = memoryMXBean.getHeapMemoryUsage(); + Runtime runtime = Runtime.getRuntime(); + rb.addGauge(MemNonHeapUsedM, memNonHeap.getUsed() / M) + .addGauge(MemNonHeapCommittedM, memNonHeap.getCommitted() / M) + .addGauge(MemNonHeapMaxM, memNonHeap.getMax() / M) + .addGauge(MemHeapUsedM, memHeap.getUsed() / M) + .addGauge(MemHeapCommittedM, memHeap.getCommitted() / M) + .addGauge(MemHeapMaxM, memHeap.getMax() / M) + .addGauge(MemMaxM, runtime.maxMemory() / M); + } + + private void getGcUsage(MetricsRecordBuilder rb) { + long count = 0; + long timeMillis = 0; + for (GarbageCollectorMXBean gcBean : gcBeans) { + long c = gcBean.getCollectionCount(); + long t = gcBean.getCollectionTime(); + MetricsInfo[] gcInfo = getGcInfo(gcBean.getName()); + rb.addCounter(gcInfo[0], c).addCounter(gcInfo[1], t); + count += c; + timeMillis += t; + } + rb.addCounter(GcCount, count) + .addCounter(GcTimeMillis, timeMillis); + + if (pauseMonitor != null) { + rb.addCounter(GcNumWarnThresholdExceeded, + pauseMonitor.getNumGcWarnThreadholdExceeded()); + rb.addCounter(GcNumInfoThresholdExceeded, + pauseMonitor.getNumGcInfoThresholdExceeded()); + rb.addCounter(GcTotalExtraSleepTime, + pauseMonitor.getTotalGcExtraSleepTime()); + } + } + + private MetricsInfo[] getGcInfo(String gcName) { + MetricsInfo[] gcInfo = gcInfoCache.get(gcName); + if (gcInfo == null) { + gcInfo = new MetricsInfo[2]; + gcInfo[0] = Interns.info("GcCount" + gcName, "GC Count for " + gcName); + gcInfo[1] = Interns + .info("GcTimeMillis" + gcName, "GC Time for " + gcName); + MetricsInfo[] previousGcInfo = gcInfoCache.putIfAbsent(gcName, gcInfo); + if (previousGcInfo != null) { + return previousGcInfo; + } + } + return gcInfo; + } + + private void getThreadUsage(MetricsRecordBuilder rb) { + int threadsNew = 0; + int threadsRunnable = 0; + int threadsBlocked = 0; + int threadsWaiting = 0; + int threadsTimedWaiting = 0; + int threadsTerminated = 0; + long threadIds[] = threadMXBean.getAllThreadIds(); + for (ThreadInfo threadInfo : threadMXBean.getThreadInfo(threadIds, 0)) { + if (threadInfo == null) continue; // race protection + switch (threadInfo.getThreadState()) { + case NEW: threadsNew++; break; + case RUNNABLE: threadsRunnable++; break; + case BLOCKED: threadsBlocked++; break; + case WAITING: threadsWaiting++; break; + case TIMED_WAITING: threadsTimedWaiting++; break; + case TERMINATED: threadsTerminated++; break; + } + } + rb.addGauge(ThreadsNew, threadsNew) + .addGauge(ThreadsRunnable, threadsRunnable) + .addGauge(ThreadsBlocked, threadsBlocked) + .addGauge(ThreadsWaiting, threadsWaiting) + .addGauge(ThreadsTimedWaiting, threadsTimedWaiting) + .addGauge(ThreadsTerminated, threadsTerminated); + } + + private void getEventCounters(MetricsRecordBuilder rb) { + rb.addCounter(LogFatal, EventCounter.getFatal()) + .addCounter(LogError, EventCounter.getError()) + .addCounter(LogWarn, EventCounter.getWarn()) + .addCounter(LogInfo, EventCounter.getInfo()); + } +} diff --git common/src/java/org/apache/hadoop/hive/common/JvmMetricsInfo.java common/src/java/org/apache/hadoop/hive/common/JvmMetricsInfo.java new file mode 100644 index 0000000..3ab73c5 --- /dev/null +++ common/src/java/org/apache/hadoop/hive/common/JvmMetricsInfo.java @@ -0,0 +1,65 @@ +/* + * 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.hive.common; + +import com.google.common.base.Objects; + +import org.apache.hadoop.metrics2.MetricsInfo; + +/** + * JVM and logging related metrics info instances. Ported from Hadoop JvmMetricsInfo. + */ +public enum JvmMetricsInfo implements MetricsInfo { + JvmMetrics("JVM related metrics etc."), // record info + // metrics + MemNonHeapUsedM("Non-heap memory used in MB"), + MemNonHeapCommittedM("Non-heap memory committed in MB"), + MemNonHeapMaxM("Non-heap memory max in MB"), + MemHeapUsedM("Heap memory used in MB"), + MemHeapCommittedM("Heap memory committed in MB"), + MemHeapMaxM("Heap memory max in MB"), + MemMaxM("Max memory size in MB"), + GcCount("Total GC count"), + GcTimeMillis("Total GC time in milliseconds"), + ThreadsNew("Number of new threads"), + ThreadsRunnable("Number of runnable threads"), + ThreadsBlocked("Number of blocked threads"), + ThreadsWaiting("Number of waiting threads"), + ThreadsTimedWaiting("Number of timed waiting threads"), + ThreadsTerminated("Number of terminated threads"), + LogFatal("Total number of fatal log events"), + LogError("Total number of error log events"), + LogWarn("Total number of warning log events"), + LogInfo("Total number of info log events"), + GcNumWarnThresholdExceeded("Number of times that the GC warn threshold is exceeded"), + GcNumInfoThresholdExceeded("Number of times that the GC info threshold is exceeded"), + GcTotalExtraSleepTime("Total GC extra sleep time in milliseconds"); + + private final String desc; + + JvmMetricsInfo(String desc) { this.desc = desc; } + + @Override public String description() { return desc; } + + @Override public String toString() { + return Objects.toStringHelper(this) + .add("name", name()).add("description", desc) + .toString(); + } +} diff --git llap-server/src/java/org/apache/hadoop/hive/llap/daemon/impl/LlapDaemon.java llap-server/src/java/org/apache/hadoop/hive/llap/daemon/impl/LlapDaemon.java index 95bc675..30f9ad4 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/daemon/impl/LlapDaemon.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/daemon/impl/LlapDaemon.java @@ -256,8 +256,7 @@ public LlapDaemon(Configuration daemonConf, int numExecutors, long executorMemor this.metrics.setCacheMemoryPerInstance(ioMemoryBytes); this.metrics.setJvmMaxMemory(maxJvmMemory); this.metrics.setWaitQueueSize(waitQueueSize); - // TODO: Has to be reverted in HIVE-15644 - //this.metrics.getJvmMetrics().setPauseMonitor(pauseMonitor); + this.metrics.getJvmMetrics().setPauseMonitor(pauseMonitor); this.llapDaemonInfoBean = MBeans.register("LlapDaemon", "LlapDaemonInfo", this); LOG.info("Started LlapMetricsSystem with displayName: " + displayName + " sessionId: " + sessionId); diff --git llap-server/src/java/org/apache/hadoop/hive/llap/metrics/LlapDaemonExecutorMetrics.java llap-server/src/java/org/apache/hadoop/hive/llap/metrics/LlapDaemonExecutorMetrics.java index 7a0ecc9..435b4de 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/metrics/LlapDaemonExecutorMetrics.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/metrics/LlapDaemonExecutorMetrics.java @@ -58,6 +58,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.google.common.collect.Maps; +import org.apache.hadoop.hive.common.JvmMetrics; import org.apache.hadoop.hive.llap.daemon.impl.ContainerRunnerImpl; import org.apache.hadoop.metrics2.MetricsCollector; import org.apache.hadoop.metrics2.MetricsInfo; @@ -71,7 +72,6 @@ import org.apache.hadoop.metrics2.lib.MutableGaugeInt; import org.apache.hadoop.metrics2.lib.MutableGaugeLong; import org.apache.hadoop.metrics2.lib.MutableQuantiles; -import org.apache.hadoop.metrics2.source.JvmMetrics; /** * Metrics about the llap daemon executors. diff --git llap-tez/src/java/org/apache/hadoop/hive/llap/tezplugins/metrics/LlapTaskSchedulerMetrics.java llap-tez/src/java/org/apache/hadoop/hive/llap/tezplugins/metrics/LlapTaskSchedulerMetrics.java index 04fd815..478f949 100644 --- llap-tez/src/java/org/apache/hadoop/hive/llap/tezplugins/metrics/LlapTaskSchedulerMetrics.java +++ llap-tez/src/java/org/apache/hadoop/hive/llap/tezplugins/metrics/LlapTaskSchedulerMetrics.java @@ -31,6 +31,7 @@ import static org.apache.hadoop.metrics2.impl.MsInfo.ProcessName; import static org.apache.hadoop.metrics2.impl.MsInfo.SessionId; +import org.apache.hadoop.hive.common.JvmMetrics; import org.apache.hadoop.hive.llap.metrics.LlapMetricsSystem; import org.apache.hadoop.hive.llap.metrics.MetricsUtils; import org.apache.hadoop.metrics2.MetricsCollector; @@ -43,7 +44,6 @@ import org.apache.hadoop.metrics2.lib.MutableCounterInt; import org.apache.hadoop.metrics2.lib.MutableGaugeInt; import org.apache.hadoop.metrics2.lib.MutableGaugeLong; -import org.apache.hadoop.metrics2.source.JvmMetrics; /** * Metrics about the llap task scheduler.