| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed 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 com.google.gerrit.metrics.proc; |
| |
| import com.google.common.base.Strings; |
| import com.google.common.base.Supplier; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.gerrit.common.Version; |
| import com.google.gerrit.metrics.CallbackMetric; |
| import com.google.gerrit.metrics.CallbackMetric0; |
| import com.google.gerrit.metrics.CallbackMetric1; |
| import com.google.gerrit.metrics.Description; |
| import com.google.gerrit.metrics.Description.Units; |
| import com.google.gerrit.metrics.Field; |
| import com.google.gerrit.metrics.MetricMaker; |
| import java.lang.management.GarbageCollectorMXBean; |
| import java.lang.management.ManagementFactory; |
| import java.lang.management.MemoryMXBean; |
| import java.lang.management.MemoryUsage; |
| import java.lang.management.ThreadMXBean; |
| import java.util.concurrent.TimeUnit; |
| |
| public class ProcMetricModule extends MetricModule { |
| @Override |
| protected void configure(MetricMaker metrics) { |
| buildLabel(metrics); |
| procUptime(metrics); |
| procCpuUsage(metrics); |
| procJvmGc(metrics); |
| procJvmMemory(metrics); |
| procJvmThread(metrics); |
| } |
| |
| private void buildLabel(MetricMaker metrics) { |
| metrics.newConstantMetric( |
| "build/label", |
| Strings.nullToEmpty(Version.getVersion()), |
| new Description("Version of Gerrit server software")); |
| } |
| |
| private void procUptime(MetricMaker metrics) { |
| metrics.newConstantMetric( |
| "proc/birth_timestamp", |
| Long.valueOf(TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis())), |
| new Description("Time at which the process started").setUnit(Units.MICROSECONDS)); |
| |
| metrics.newCallbackMetric( |
| "proc/uptime", |
| Long.class, |
| new Description("Uptime of this process").setUnit(Units.MILLISECONDS), |
| new Supplier<Long>() { |
| @Override |
| public Long get() { |
| return ManagementFactory.getRuntimeMXBean().getUptime(); |
| } |
| }); |
| } |
| |
| private void procCpuUsage(MetricMaker metrics) { |
| final OperatingSystemMXBeanProvider provider = OperatingSystemMXBeanProvider.Factory.create(); |
| |
| if (provider == null) { |
| return; |
| } |
| |
| if (provider.getProcessCpuTime() != -1) { |
| metrics.newCallbackMetric( |
| "proc/cpu/usage", |
| Double.class, |
| new Description("CPU time used by the process").setCumulative().setUnit(Units.SECONDS), |
| new Supplier<Double>() { |
| @Override |
| public Double get() { |
| return provider.getProcessCpuTime() / 1e9; |
| } |
| }); |
| } |
| |
| if (provider.getOpenFileDescriptorCount() != -1) { |
| metrics.newCallbackMetric( |
| "proc/num_open_fds", |
| Long.class, |
| new Description("Number of open file descriptors").setGauge().setUnit("fds"), |
| new Supplier<Long>() { |
| @Override |
| public Long get() { |
| return provider.getOpenFileDescriptorCount(); |
| } |
| }); |
| } |
| } |
| |
| private void procJvmMemory(MetricMaker metrics) { |
| final CallbackMetric0<Long> heapCommitted = |
| metrics.newCallbackMetric( |
| "proc/jvm/memory/heap_committed", |
| Long.class, |
| new Description("Amount of memory guaranteed for user objects.") |
| .setGauge() |
| .setUnit(Units.BYTES)); |
| |
| final CallbackMetric0<Long> heapUsed = |
| metrics.newCallbackMetric( |
| "proc/jvm/memory/heap_used", |
| Long.class, |
| new Description("Amount of memory holding user objects.") |
| .setGauge() |
| .setUnit(Units.BYTES)); |
| |
| final CallbackMetric0<Long> nonHeapCommitted = |
| metrics.newCallbackMetric( |
| "proc/jvm/memory/non_heap_committed", |
| Long.class, |
| new Description("Amount of memory guaranteed for classes, etc.") |
| .setGauge() |
| .setUnit(Units.BYTES)); |
| |
| final CallbackMetric0<Long> nonHeapUsed = |
| metrics.newCallbackMetric( |
| "proc/jvm/memory/non_heap_used", |
| Long.class, |
| new Description("Amount of memory holding classes, etc.") |
| .setGauge() |
| .setUnit(Units.BYTES)); |
| |
| final CallbackMetric0<Integer> objectPendingFinalizationCount = |
| metrics.newCallbackMetric( |
| "proc/jvm/memory/object_pending_finalization_count", |
| Integer.class, |
| new Description("Approximate number of objects needing finalization.") |
| .setGauge() |
| .setUnit("objects")); |
| |
| final MemoryMXBean memory = ManagementFactory.getMemoryMXBean(); |
| metrics.newTrigger( |
| ImmutableSet.<CallbackMetric<?>>of( |
| heapCommitted, heapUsed, nonHeapCommitted, nonHeapUsed, objectPendingFinalizationCount), |
| new Runnable() { |
| @Override |
| public void run() { |
| try { |
| MemoryUsage stats = memory.getHeapMemoryUsage(); |
| heapCommitted.set(stats.getCommitted()); |
| heapUsed.set(stats.getUsed()); |
| } catch (IllegalArgumentException e) { |
| // MXBean may throw due to a bug in Java 7; ignore. |
| } |
| |
| MemoryUsage stats = memory.getNonHeapMemoryUsage(); |
| nonHeapCommitted.set(stats.getCommitted()); |
| nonHeapUsed.set(stats.getUsed()); |
| |
| objectPendingFinalizationCount.set(memory.getObjectPendingFinalizationCount()); |
| } |
| }); |
| } |
| |
| private void procJvmGc(MetricMaker metrics) { |
| final CallbackMetric1<String, Long> gcCount = |
| metrics.newCallbackMetric( |
| "proc/jvm/gc/count", |
| Long.class, |
| new Description("Number of GCs").setCumulative(), |
| Field.ofString("gc_name", "The name of the garbage collector")); |
| |
| final CallbackMetric1<String, Long> gcTime = |
| metrics.newCallbackMetric( |
| "proc/jvm/gc/time", |
| Long.class, |
| new Description("Approximate accumulated GC elapsed time") |
| .setCumulative() |
| .setUnit(Units.MILLISECONDS), |
| Field.ofString("gc_name", "The name of the garbage collector")); |
| |
| metrics.newTrigger( |
| gcCount, |
| gcTime, |
| new Runnable() { |
| @Override |
| public void run() { |
| for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) { |
| long count = gc.getCollectionCount(); |
| if (count != -1) { |
| gcCount.set(gc.getName(), count); |
| } |
| long time = gc.getCollectionTime(); |
| if (time != -1) { |
| gcTime.set(gc.getName(), time); |
| } |
| } |
| } |
| }); |
| } |
| |
| private void procJvmThread(MetricMaker metrics) { |
| final ThreadMXBean thread = ManagementFactory.getThreadMXBean(); |
| metrics.newCallbackMetric( |
| "proc/jvm/thread/num_live", |
| Integer.class, |
| new Description("Current live thread count").setGauge().setUnit("threads"), |
| new Supplier<Integer>() { |
| @Override |
| public Integer get() { |
| return thread.getThreadCount(); |
| } |
| }); |
| } |
| } |