Skip to content

[MyPerf4J-94] Support V3 JVM GC Metrics #109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cn.myperf4j.base.metric;

/**
* Created by LinShunkang on 2024/02/08
*/
public class JvmGcMetricsV3 extends Metrics {

private static final long serialVersionUID = -233095689152915892L;

private final String gcName;

private final long gcCount;

private final long gcTime;

private final double avgGcTime;

public JvmGcMetricsV3(String gcName, long gcCount, long gcTime) {
this.gcName = gcName;
this.gcCount = gcCount;
this.gcTime = gcTime;
this.avgGcTime = gcCount > 0L ? ((double) gcTime) / gcCount : 0D;
}

public String getGcName() {
return gcName;
}

public long getGcCount() {
return gcCount;
}

public long getGcTime() {
return gcTime;
}

public double getAvgGcTime() {
return avgGcTime;
}

@Override
public String toString() {
return "JvmGcMetricsV3{" +
"gcName='" + gcName + '\'' +
", gcCount=" + gcCount +
", gcTime=" + gcTime +
", avgGcTime=" + avgGcTime +
"} " + super.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static JvmGcMetrics collectGcMetrics() {
zGcPausesTime += gcMxBean.getCollectionTime();
zGcPausesCount += gcMxBean.getCollectionCount();
} else {
Logger.warn("Unknown GC: " + gcName);
Logger.debug("Unknown GC: " + gcName);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package cn.myperf4j.base.metric.collector;

import cn.myperf4j.base.metric.JvmGcMetricsV3;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Created by LinShunkang on 2024/02/08
* <p>
* -XX:+UseParallelGC -XX:+UseParallelOldGC
* -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
* -XX:+UseSerialGC
* -XX:+UseG1GC
* -XX:+UseZGC [-XX:+ZGenerational]
*/
public final class JvmGcV3Collector {

private static final Map<String, GcInfo> lastGcInfoMap = new ConcurrentHashMap<>(16);

private JvmGcV3Collector() {
//empty
}

public static List<JvmGcMetricsV3> collectGcMetrics() {
final List<GarbageCollectorMXBean> gcMXBeanList = ManagementFactory.getGarbageCollectorMXBeans();
final List<JvmGcMetricsV3> result = new ArrayList<>(gcMXBeanList.size());
for (int i = 0, size = gcMXBeanList.size(); i < size; i++) {
final GarbageCollectorMXBean gcMxBean = gcMXBeanList.get(i);
final String gcName = gcMxBean.getName();
final GcInfo curGcInfo = new GcInfo(gcMxBean);
final GcInfo lastGcInfo = lastGcInfoMap.put(gcName, curGcInfo);
if (lastGcInfo != null) {
result.add(generateGcMetrics(curGcInfo, lastGcInfo));
}
}
return result;
}

private static JvmGcMetricsV3 generateGcMetrics(GcInfo cur, GcInfo last) {
return new JvmGcMetricsV3(cur.gcName, cur.gcCount - last.gcCount, cur.gcTime - last.gcTime);
}

private static final class GcInfo {

private final String gcName;

private final long gcTime;

private final long gcCount;

GcInfo(GarbageCollectorMXBean gcMxBean) {
this.gcName = gcMxBean.getName();
this.gcTime = gcMxBean.getCollectionTime();
this.gcCount = gcMxBean.getCollectionCount();
}

@Override
public String toString() {
return "GcInfo{" +
"gcName='" + gcName + '\'' +
", gcTime=" + gcTime +
", gcCount=" + gcCount +
'}';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cn.myperf4j.base.metric.exporter;

import cn.myperf4j.base.metric.JvmGcMetricsV3;

/**
* Created by LinShunkang on 2024/02/08
*/
public interface JvmGcMetricsV3Exporter extends MetricsExporter<JvmGcMetricsV3> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmCompilationMetricsExporter;
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmFileDescMetricsExporter;
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmGcMetricsExporter;
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmMemoryMetricsExporter;
import cn.myperf4j.base.metric.exporter.discard.DiscardJvmThreadMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmBufferPoolMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmClassMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmCompilationMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmFileDescMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmGcMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmMemoryMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpJvmThreadMetricsExporter;
import cn.myperf4j.base.metric.exporter.http.influxdb.InfluxHttpMethodMetricsExporter;
Expand All @@ -20,6 +22,7 @@
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmCompilationMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmFileDescMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmGcMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmMemoryMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogJvmThreadMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.influxdb.InfluxLogMethodMetricsExporter;
Expand All @@ -28,6 +31,7 @@
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmCompilationMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmFileDescMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmGcMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmMemoryMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogJvmThreadMetricsExporter;
import cn.myperf4j.base.metric.exporter.log.standard.StdLogMethodMetricsExporter;
Expand Down Expand Up @@ -71,6 +75,20 @@ public static JvmGcMetricsExporter getGcMetricsExporter(String exporter) {
}
}

public static JvmGcMetricsV3Exporter getGcMetricsV3Exporter(String exporter) {
switch (exporter) {
case EXPORTER_LOG_STANDARD:
case EXPORTER_LOG_STDOUT:
return new StdLogJvmGcMetricsV3Exporter();
case EXPORTER_LOG_INFLUX_DB:
return new InfluxLogJvmGcMetricsV3Exporter();
case EXPORTER_HTTP_INFLUX_DB:
return new InfluxHttpJvmGcMetricsV3Exporter();
default:
return new DiscardJvmGcMetricsV3Exporter();
}
}

public static JvmMemoryMetricsExporter getMemoryMetricsExporter(String exporter) {
switch (exporter) {
case EXPORTER_LOG_STANDARD:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cn.myperf4j.base.metric.exporter.discard;

import cn.myperf4j.base.metric.JvmGcMetricsV3;
import cn.myperf4j.base.metric.exporter.JvmGcMetricsV3Exporter;

/**
* Created by LinShunkang on 2024/02/08
*/
public class DiscardJvmGcMetricsV3Exporter implements JvmGcMetricsV3Exporter {

@Override
public void beforeProcess(long processId, long startMillis, long stopMillis) {
//empty
}

@Override
public void process(JvmGcMetricsV3 metrics, long processId, long startMillis, long stopMillis) {
//empty
}

@Override
public void afterProcess(long processId, long startMillis, long stopMillis) {
//empty
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cn.myperf4j.base.metric.exporter.http.influxdb;

import cn.myperf4j.base.influxdb.InfluxDbClient;
import cn.myperf4j.base.influxdb.InfluxDbClientFactory;
import cn.myperf4j.base.metric.JvmGcMetricsV3;
import cn.myperf4j.base.metric.exporter.JvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.formatter.JvmGcMetricsV3Formatter;
import cn.myperf4j.base.metric.formatter.influxdb.InfluxJvmGcMetricsV3Formatter;
import cn.myperf4j.base.util.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* Created by LinShunkang on 2024/02/08
*/
public class InfluxHttpJvmGcMetricsV3Exporter implements JvmGcMetricsV3Exporter {

private static final JvmGcMetricsV3Formatter METRICS_FORMATTER = new InfluxJvmGcMetricsV3Formatter();

private static final InfluxDbClient CLIENT = InfluxDbClientFactory.getClient();

private final ConcurrentMap<Long, List<JvmGcMetricsV3>> metricsMap = new ConcurrentHashMap<>(8);

@Override
public void beforeProcess(long processId, long startMillis, long stopMillis) {
metricsMap.put(processId, new ArrayList<JvmGcMetricsV3>(1));
}

@Override
public void process(JvmGcMetricsV3 metrics, long processId, long startMillis, long stopMillis) {
final List<JvmGcMetricsV3> metricsList = metricsMap.get(processId);
if (metricsList != null) {
metricsList.add(metrics);
} else {
Logger.error("InfluxHttpJvmGcMetricsV3Exporter.process(" + processId + ", " + startMillis + ", "
+ stopMillis + "): metricsList is null!!!");
}
}

@Override
public void afterProcess(long processId, long startMillis, long stopMillis) {
final List<JvmGcMetricsV3> metricsList = metricsMap.remove(processId);
if (metricsList != null) {
CLIENT.writeMetricsAsync(METRICS_FORMATTER.format(metricsList, startMillis, stopMillis));
} else {
Logger.error("InfluxHttpJvmGcMetricsV3Exporter.afterProcess(" + processId + ", " + startMillis + ", "
+ stopMillis + "): metricsList is null!!!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cn.myperf4j.base.metric.exporter.log;

import cn.myperf4j.base.config.ProfilingConfig;
import cn.myperf4j.base.log.ILogger;
import cn.myperf4j.base.log.LoggerFactory;
import cn.myperf4j.base.metric.exporter.JvmGcMetricsV3Exporter;

/**
* Created by LinShunkang on 2024/02/08
*/
public abstract class AbstractLogJvmGcMetricsV3Exporter implements JvmGcMetricsV3Exporter {

protected ILogger logger = LoggerFactory.getLogger(ProfilingConfig.metricsConfig().gcMetricsFile());

@Override
public void beforeProcess(long processId, long startMillis, long stopMillis) {
//empty
}

@Override
public void afterProcess(long processId, long startMillis, long stopMillis) {
logger.flushLog();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cn.myperf4j.base.metric.exporter.log.influxdb;

import cn.myperf4j.base.metric.JvmGcMetricsV3;
import cn.myperf4j.base.metric.exporter.log.AbstractLogJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.formatter.JvmGcMetricsV3Formatter;
import cn.myperf4j.base.metric.formatter.influxdb.InfluxJvmGcMetricsV3Formatter;

import java.util.Collections;

/**
* Created by LinShunkang on 2024/02/08
*/
public class InfluxLogJvmGcMetricsV3Exporter extends AbstractLogJvmGcMetricsV3Exporter {

private static final JvmGcMetricsV3Formatter METRICS_FORMATTER = new InfluxJvmGcMetricsV3Formatter();

@Override
public void process(JvmGcMetricsV3 metrics, long processId, long startMillis, long stopMillis) {
logger.log(METRICS_FORMATTER.format(Collections.singletonList(metrics), startMillis, stopMillis));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cn.myperf4j.base.metric.exporter.log.standard;

import cn.myperf4j.base.metric.JvmGcMetricsV3;
import cn.myperf4j.base.metric.exporter.log.AbstractLogJvmGcMetricsV3Exporter;
import cn.myperf4j.base.metric.formatter.JvmGcMetricsV3Formatter;
import cn.myperf4j.base.metric.formatter.standard.StdJvmGcMetricsV3Formatter;
import cn.myperf4j.base.util.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* Created by LinShunkang on 2024/02/08
*/
public class StdLogJvmGcMetricsV3Exporter extends AbstractLogJvmGcMetricsV3Exporter {

private static final JvmGcMetricsV3Formatter METRICS_FORMATTER = new StdJvmGcMetricsV3Formatter();

private final ConcurrentMap<Long, List<JvmGcMetricsV3>> metricsMap = new ConcurrentHashMap<>(8);

@Override
public void beforeProcess(long processId, long startMillis, long stopMillis) {
metricsMap.put(processId, new ArrayList<JvmGcMetricsV3>(1));
}

@Override
public void process(JvmGcMetricsV3 metrics, long processId, long startMillis, long stopMillis) {
final List<JvmGcMetricsV3> metricsList = metricsMap.get(processId);
if (metricsList != null) {
metricsList.add(metrics);
} else {
Logger.error("StdLogJvmGcMetricsV3Exporter.process(" + processId + ", " + startMillis + ", "
+ stopMillis + "): metricsList is null!!!");
}
}

@Override
public void afterProcess(long processId, long startMillis, long stopMillis) {
final List<JvmGcMetricsV3> metricsList = metricsMap.remove(processId);
if (metricsList != null) {
logger.logAndFlush(METRICS_FORMATTER.format(metricsList, startMillis, stopMillis));
} else {
Logger.error("StdLogJvmGcMetricsV3Exporter.afterProcess(" + processId + ", " + startMillis + ", "
+ stopMillis + "): metricsList is null!!!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cn.myperf4j.base.metric.formatter;

import cn.myperf4j.base.metric.JvmGcMetricsV3;

/**
* Created by LinShunkang on 2024/02/08
*/
public interface JvmGcMetricsV3Formatter extends MetricsFormatter<JvmGcMetricsV3> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public String format(List<JvmBufferPoolMetrics> metricsList, long startMillis, l
for (int i = 0, size = metricsList.size(); i < size; ++i) {
appendLineProtocol(metricsList.get(i), startNanos, sb);
}
return sb.substring(0, sb.length() - 1);
return sb.substring(0, Math.max(0, sb.length() - 1));
} finally {
sb.setLength(0);
}
Expand Down
Loading