blob: 0ffb02aa47fe12e297fc8ff0bc2f95f941bc176e [file] [log] [blame]
/*
* 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.ignite.internal.metrics.sources;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.HashMap;
import java.util.function.Supplier;
import org.apache.ignite.internal.metrics.LongGauge;
import org.apache.ignite.internal.metrics.Metric;
import org.apache.ignite.internal.metrics.MetricSet;
import org.apache.ignite.internal.metrics.MetricSource;
import org.jetbrains.annotations.Nullable;
/**
* Metric source, which provides JVM metrics like memory usage, gc stats etc.
*/
public class JvmMetricSource implements MetricSource {
/** Source name. */
private static final String SOURCE_NAME = "jvm";
/** Timeout for memory usage stats cache. */
private static final long MEMORY_USAGE_CACHE_TIMEOUT = 1000;
/** JVM standard MXBean to provide information about memory usage. */
private final MemoryMXBean memoryMxBean;
/** True, if source is enabled, false otherwise. */
private boolean enabled;
/**
* Constructor.
*
* @param memoryMxBean MXBean implementation to receive memory info.
*/
JvmMetricSource(MemoryMXBean memoryMxBean) {
this.memoryMxBean = memoryMxBean;
}
/**
* Constructs new metric source with standard MemoryMXBean as metric provider.
*/
public JvmMetricSource() {
memoryMxBean = ManagementFactory.getMemoryMXBean();
}
/** {@inheritDoc} */
@Override
public String name() {
return SOURCE_NAME;
}
/** {@inheritDoc} */
@Override
public synchronized @Nullable MetricSet enable() {
var metrics = new HashMap<String, Metric>();
CachedMemoryUsage heapMemoryUsage = new CachedMemoryUsage(memoryMxBean::getHeapMemoryUsage, MEMORY_USAGE_CACHE_TIMEOUT);
metrics.put("memory.heap.Init",
new LongGauge(
"memory.heap.Init",
"Initial amount of heap memory",
() -> heapMemoryUsage.get().getInit()
));
metrics.put("memory.heap.Used",
new LongGauge("memory.heap.Used",
"Current used amount of heap memory",
() -> heapMemoryUsage.get().getUsed()
));
metrics.put("memory.heap.Committed",
new LongGauge("memory.heap.Committed",
"Committed amount of heap memory",
() -> heapMemoryUsage.get().getCommitted()
));
metrics.put("memory.heap.Max",
new LongGauge("memory.heap.Max",
"Maximum amount of heap memory",
() -> heapMemoryUsage.get().getMax()
));
CachedMemoryUsage nonHeapMemoryUsage = new CachedMemoryUsage(memoryMxBean::getNonHeapMemoryUsage, MEMORY_USAGE_CACHE_TIMEOUT);
metrics.put("memory.non-heap.Init",
new LongGauge("memory.non-heap.Init",
"Initial amount of non-heap memory",
() -> nonHeapMemoryUsage.get().getInit()
));
metrics.put("memory.non-heap.Used",
new LongGauge("memory.non-heap.Used",
"Used amount of non-heap memory",
() -> nonHeapMemoryUsage.get().getUsed()
));
metrics.put("memory.non-heap.Committed",
new LongGauge("memory.non-heap.Committed",
"Committed amount of non-heap memory",
() -> nonHeapMemoryUsage.get().getCommitted()
));
metrics.put("memory.non-heap.Max",
new LongGauge("memory.non-heap.Max",
"Maximum amount of non-heap memory",
() -> nonHeapMemoryUsage.get().getMax()
));
enabled = true;
return new MetricSet(SOURCE_NAME, metrics);
}
/** {@inheritDoc} */
@Override
public synchronized void disable() {
enabled = false;
}
/** {@inheritDoc} */
@Override
public synchronized boolean enabled() {
return enabled;
}
/**
* Simple wrapper for memoization memory usage stats.
*/
private static class CachedMemoryUsage {
/** Source of memory usage stats. */
private final Supplier<MemoryUsage> source;
/** Timeout of cache in ms. */
private final long timeout;
/** Last update time in ms. */
private volatile long lastUpdateTime;
/** Last received from source value. */
private volatile MemoryUsage currentVal;
/**
* Constructor.
*
* @param source Source of memory usage data.
* @param timeout Cache timeout in millis.
*/
private CachedMemoryUsage(Supplier<MemoryUsage> source, long timeout) {
this.source = source;
this.timeout = timeout;
update();
}
/**
* Returns current cached value.
*
* @return Current cached value.
*/
private MemoryUsage get() {
if ((System.currentTimeMillis() - lastUpdateTime) > timeout) {
update();
}
return currentVal;
}
/**
* Update cache value and last update time.
*/
private synchronized void update() {
currentVal = source.get();
lastUpdateTime = System.currentTimeMillis();
}
}
}