
com.didiglobal.knowframework.system.metrcis.service.linux.LinuxProcessMetricsServiceImpl Maven / Gradle / Ivy
package com.didiglobal.knowframework.system.metrcis.service.linux;
import com.didiglobal.knowframework.system.metrcis.annotation.PeriodMethod;
import com.didiglobal.knowframework.system.metrcis.bean.PeriodStatistics;
import com.didiglobal.knowframework.system.metrcis.service.ProcessMetricsService;
import com.didiglobal.knowframework.system.metrcis.util.MathUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.List;
/**
* 获取进程级指标
* 包括按需获取指标数据和一次性获取所有指标数据
* @author william.
* @Date 2021/11/3
*/
public class LinuxProcessMetricsServiceImpl extends LinuxMetricsService implements ProcessMetricsService {
private static final Logger LOGGER = LoggerFactory.getLogger(LinuxProcessMetricsServiceImpl.class);
/**
* 当前agent进程id
*/
private final Long PID;
private LinuxCpuTime lastLinuxCpuTimeProcessCpuUtil;
private LinuxCpuTime lastLinuxCpuTimeProcessCpuUtilTotalPercent;
private LinuxNetFlow lastLinuxNetFlowSend;
private LinuxNetFlow lastLinuxNetFlowReceive;
private LinuxIORate lastLinuxIORateReadRate;
private LinuxIORate lastLinuxIORateReadBytesRate;
private LinuxIORate lastLinuxIORateWriteRate;
private LinuxIORate lastLinuxIORateWriteBytesRate;
/**
* agent宿主机cpu核(逻辑核)
*/
private final int CPU_NUM;
/**************************** 待计算字段 ****************************/
private PeriodStatistics procCpuUtil = new PeriodStatistics();
private PeriodStatistics procNetworkReceiveBytesPs = new PeriodStatistics();
private PeriodStatistics procNetworkSendBytesPs = new PeriodStatistics();
private PeriodStatistics procCpuUtilTotalPercent = new PeriodStatistics();
private PeriodStatistics procCpuSys = new PeriodStatistics();
private PeriodStatistics procCpuUser = new PeriodStatistics();
private PeriodStatistics procCpuSwitchesPS = new PeriodStatistics();
private PeriodStatistics procCpuVoluntarySwitchesPS = new PeriodStatistics();
private PeriodStatistics procCpuNonVoluntarySwitchesPS = new PeriodStatistics();
private PeriodStatistics procIOReadRate = new PeriodStatistics();
private PeriodStatistics procIOReadBytesRate = new PeriodStatistics();
private PeriodStatistics procIOWriteRate = new PeriodStatistics();
private PeriodStatistics procIOWriteBytesRate = new PeriodStatistics();
private PeriodStatistics procIOReadWriteRate = new PeriodStatistics();
private PeriodStatistics procIOReadWriteBytesRate = new PeriodStatistics();
private PeriodStatistics procIOAwaitTimePercent = new PeriodStatistics();
private static LinuxProcessMetricsServiceImpl instance;
private Long yGcCountCurrent = 0l;
private Long yGcTimeCurrent = 0l;
private Long fGcCountCurrent = 0l;
private Long fGcTimeCurrent = 0l;
private Long yGcCountPre = 0l;
private Long yGcTimePre = 0l;
private Long fGcCountPre = 0l;
private Long fGcTimePre = 0l;
public static synchronized LinuxProcessMetricsServiceImpl getInstance() {
if(null == instance) {
instance = new LinuxProcessMetricsServiceImpl();
}
return instance;
}
private LinuxProcessMetricsServiceImpl() {
PID = initializePid();
CPU_NUM = Runtime.getRuntime().availableProcessors();
try {
lastLinuxCpuTimeProcessCpuUtil = new LinuxCpuTime(getProcessPid(), CPU_NUM);// 记录上次的cpu耗时
lastLinuxCpuTimeProcessCpuUtilTotalPercent = new LinuxCpuTime(getProcessPid(), CPU_NUM);
} catch (Exception e) {
LOGGER.error("class=LinuxProcessMetricsServiceImpl||method=LinuxProcessMetricsServiceImpl()||msg=CpuTime init failed",
e);
}
try {
lastLinuxNetFlowSend = new LinuxNetFlow(getProcessPid());// 记录上次的收发字节数
lastLinuxNetFlowReceive = new LinuxNetFlow(getProcessPid());
} catch (Exception e) {
LOGGER.error("class=LinuxProcessMetricsServiceImpl||method=LinuxProcessMetricsServiceImpl()||msg=NetFlow init failed",
e);
}
try {
lastLinuxIORateReadBytesRate = new LinuxIORate(getProcessPid());// 记录上次IO速率
lastLinuxIORateWriteRate = new LinuxIORate(getProcessPid());// 记录上次IO速率
lastLinuxIORateWriteBytesRate = new LinuxIORate(getProcessPid());// 记录上次IO速率
lastLinuxIORateReadRate = new LinuxIORate(getProcessPid());// 记录上次IO速率;
} catch (Exception e) {
LOGGER.error("class=LinuxProcessMetricsServiceImpl||method=LinuxProcessMetricsServiceImpl()||msg=processIORate init failed",
e);
}
}
@Override
public Long getProcessStartupTime() {
try {
return ManagementFactory.getRuntimeMXBean().getStartTime();
} catch (Exception ex) {
LOGGER.error("class=LinuxProcessMetricsServiceImpl||method=getProcessStartupTime()||msg=failed to get process startup time", ex);
return 0L;
}
}
@Override
public Long getProcUptime() {
return System.currentTimeMillis() - getProcessStartupTime();
}
@Override
public Long getProcessPid() {
return PID;
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuUtil() {
procCpuUtil.add(getCurrentProcCpuUtil());
}
@Override
public Double getProcCpuUtil() {
return getCurrentProcCpuUtil();
}
@Override
public Double getCurrentProcCpuUtil() {
try {
LinuxCpuTime curLinuxCpuTime = new LinuxCpuTime(getProcessPid(), CPU_NUM);
float cpuUsage = curLinuxCpuTime.getUsage(lastLinuxCpuTimeProcessCpuUtil);
lastLinuxCpuTimeProcessCpuUtil = curLinuxCpuTime;
return MathUtil.divideWith2Digit(Float.valueOf(cpuUsage).doubleValue(), 1.0d);
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getCurrentProcessCpuUsage||msg=current process's cpu usage get failed",
e);
return 0d;
}
}
@Override
public PeriodStatistics getProcCpuUtilTotalPercent() {
if(procCpuUtilTotalPercent.isEmpty()) {
calcProcCpuUtilTotalPercent();
}
return procCpuUtilTotalPercent.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuUtilTotalPercent() {
procCpuUtilTotalPercent.add(getProcCpuUtilTotalPercentOnly());
}
private Double getProcCpuUtilTotalPercentOnly() {
try {
LinuxCpuTime curLinuxCpuTime = new LinuxCpuTime(getProcessPid(), CPU_NUM);
float cpuUsage = curLinuxCpuTime.getUsage(lastLinuxCpuTimeProcessCpuUtilTotalPercent);
lastLinuxCpuTimeProcessCpuUtilTotalPercent = curLinuxCpuTime;
return MathUtil.divideWith2Digit(Float.valueOf(cpuUsage).doubleValue(), CPU_NUM);
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getCurrentProcessCpuUsage||msg=current process's cpu usage get failed",
e);
return 0d;
}
}
@Override
public Double getProcCpuSys() {
return getProcCpuSysOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuSys() {
procCpuSys.add(getProcCpuSysOnly());
}
private Double getProcCpuSysOnly() {
try {
List lines = getOutputByCmd("pidstat -p %d 1 1 | awk 'NR==4'", "当前进程系统态cpu使用率", PID);
String[] columns = lines.get(0).split("\\s+");
if(columns.length == 9) {
return Double.parseDouble(columns[4]);
} else if(columns.length == 10) {
return Double.parseDouble(columns[5]);
}
return 0.0d;
} catch (Exception ex) {
LOGGER.error("class=LinuxProcMetricsService||method=getProcCpuSysOnly()||msg="+ex.getMessage());
return 0.0d;
}
}
@Override
public Double getProcCpuUser() {
return getProcCpuUserOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuUser() {
procCpuUser.add(getProcCpuUserOnly());
}
private Double getProcCpuUserOnly() {
try {
List lines = getOutputByCmd("pidstat -p %d 1 1 | awk 'NR==4'", "当前进程用户态cpu使用率", PID);
String[] columns = lines.get(0).split("\\s+");
if(columns.length == 9) {
return Double.parseDouble(columns[3]);
} else if(columns.length == 10) {
return Double.parseDouble(columns[4]);
}
return 0.0d;
} catch (Exception ex) {
LOGGER.error("class=LinuxProcMetricsService||method=getProcCpuUserOnly||msg="+ex.getMessage());
return 0.0d;
}
}
@Override
public Double getProcCpuSwitchesPS() {
return getProcCpuSwitchesPSOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuSwitchesPS() {
procCpuSwitchesPS.add(getProcCpuSwitchesPSOnly());
}
private Double getProcCpuSwitchesPSOnly() {
return getProcCpuVoluntarySwitchesPSOnly() + getProcCpuNonVoluntarySwitchesPSOnly();
}
@Override
public Double getProcCpuVoluntarySwitchesPS() {
return getProcCpuVoluntarySwitchesPSOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuVoluntarySwitchesPS() {
procCpuVoluntarySwitchesPS.add(getProcCpuVoluntarySwitchesPSOnly());
}
private Double getProcCpuVoluntarySwitchesPSOnly() {
List lines = getOutputByCmd("pidstat -w -p %d 1 1 | awk 'NR==4{print $4}'", "进程CPU每秒上下文自愿切换次数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Double.parseDouble(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcCpuVoluntarySwitchesPSOnly||msg=data is null");
return 0d;
}
}
@Override
public Double getProcCpuNonVoluntarySwitchesPS() {
return getProcCpuNonVoluntarySwitchesPSOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcCpuNonVoluntarySwitchesPS() {
procCpuNonVoluntarySwitchesPS.add(getProcCpuNonVoluntarySwitchesPSOnly());
}
private Double getProcCpuNonVoluntarySwitchesPSOnly() {
List lines = getOutputByCmd("pidstat -w -p %d 1 1 | awk 'NR==4{print $5}'", "进程CPU每秒上下文非自愿切换次数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Double.parseDouble(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcCpuNonVoluntarySwitchesPSOnly||msg=data is null");
return 0d;
}
}
@Override
public Long getProcMemUsed() {
return getJvmProcHeapMemoryUsed() + getJvmProcNonHeapMemoryUsed();
}
@Override
public Double getProcMemUtil() {
long memTotal = getSystemMemTotal();
if (memTotal == 0) {
LOGGER.warn("SystemMemoryTotal is zero");
return 0.0d;
}
return MathUtil.divideWith2Digit(getProcMemUsed() * 100, memTotal);
}
@Override
public Long getProcMemData() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmData' | awk '{print $2}'", "当前进程data内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemData()||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemDirty() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'RssAnon' | awk '{print $2}'", "当前进程dirty内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemDirty||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemLib() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmLib' | awk '{print $2}'", "当前进程lib内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemLib||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemRss() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmRSS' | awk '{print $2}'", "当前进程常驻内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemRss||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemShared() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'RssShmem' | awk '{print $2}'", "当前进程共享内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemShared||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemSwap() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmSwap' | awk '{print $2}'", "当前进程交换空间大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemSwap||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemText() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmExe' | awk '{print $2}'", "当前进程Text内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemText||msg=data is null");
return 0L;
}
}
@Override
public Long getProcMemVms() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmSize' | awk '{print $2}'", "当前进程虚拟内存大小", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return 1024 * Long.parseLong(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcMemVms||msg=data is null");
return 0L;
}
}
@Override
public Long getJvmProcHeapMemoryUsed() {
try {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
return memoryMXBean.getHeapMemoryUsage().getUsed();
} catch (Exception ex) {
LOGGER.error("获取系统资源项[当前进程堆内内存使用量]失败", ex);
return 0L;
}
}
@Override
public Long getJvmProcNonHeapMemoryUsed() {
try {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
return memoryMXBean.getNonHeapMemoryUsage().getUsed();
} catch (Exception ex) {
LOGGER.error("获取系统资源项[当前进程堆外内存使用量]失败", ex);
return 0L;
}
}
@Override
public Long getJvmProcHeapSizeXmx() {
try {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
return memoryMXBean.getHeapMemoryUsage().getMax();
} catch (Exception ex) {
LOGGER.error("获取系统资源项[当前进程最大可用堆内存]失败", ex);
return 0l;
}
}
@Override
public Long getJvmProcMemUsedPeak() {
List lines = getOutputByCmd("cat /proc/%d/status | grep 'VmHWM' | awk '{print $2}'", "当前jvm进程启动以来内存使用量峰值", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Long.parseLong(lines.get(0)) * 1024;
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcMemUsedPeak||msg=data is null");
return 0L;
}
}
@Override
public Double getJvmProcHeapMemUsedPercent() {
return MathUtil.divideWith2Digit(getJvmProcHeapMemoryUsed() * 100, getJvmProcHeapSizeXmx());
}
@Override
public PeriodStatistics getProcIOReadRate() {
if(procIOReadRate.isEmpty()) {
calcProcIOReadRate();
}
return procIOReadRate.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOReadRate() {
procIOReadRate.add(getProcIOReadRateOnly());
}
private Double getProcIOReadRateOnly() {
try {
LinuxIORate curLinuxIORate = new LinuxIORate(PID);
double ioReadTimesRate = curLinuxIORate.getIOReadTimesRate(lastLinuxIORateReadRate);
this.lastLinuxIORateReadRate = curLinuxIORate;
return ioReadTimesRate;
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getProcIOReadRateOnly||msg=failed to get process IO read rate",
e);
}
return 0.0d;
}
@Override
public Double getProcIOReadBytesRate() {
return getProcIOReadBytesRateOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOReadBytesRate() {
procIOReadBytesRate.add(getProcIOReadBytesRateOnly());
}
private Double getProcIOReadBytesRateOnly() {
try {
LinuxIORate curLinuxIORate = new LinuxIORate(PID);
double ioReadBytesRate = curLinuxIORate.getIOReadBytesRate(lastLinuxIORateReadBytesRate);
this.lastLinuxIORateReadBytesRate = curLinuxIORate;
return ioReadBytesRate;
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getProcIOReadBytesRateOnly||msg=failed to get process IO read bytes rate",
e);
}
return 0d;
}
@Override
public PeriodStatistics getProcIOWriteRate() {
if(procIOWriteRate.isEmpty()) {
calcProcIOWriteRate();
}
return procIOWriteRate.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOWriteRate() {
procIOWriteRate.add(getProcIOWriteRateOnly());
}
private Double getProcIOWriteRateOnly() {
try {
LinuxIORate curLinuxIORate = new LinuxIORate(PID);
double ioWriteTimesRate = curLinuxIORate.getIOWriteTimesRate(lastLinuxIORateWriteRate);
this.lastLinuxIORateWriteRate = curLinuxIORate;
return ioWriteTimesRate;
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getProcIOWriteRateOnly||msg=failed to get process IO write rate",
e);
}
return 0d;
}
@Override
public Double getProcIOWriteBytesRate() {
return getProcIOWriteBytesRateOnly();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOWriteBytesRate() {
procIOWriteBytesRate.add(getProcIOWriteBytesRateOnly());
}
private Double getProcIOWriteBytesRateOnly() {
try {
LinuxIORate curLinuxIORate = new LinuxIORate(PID);
double ioWriteBytesRate = curLinuxIORate.getIOWriteBytesRate(lastLinuxIORateWriteBytesRate);
this.lastLinuxIORateWriteBytesRate = curLinuxIORate;
return ioWriteBytesRate;
} catch (Exception e) {
LOGGER.error("class=LinuxOSResourceService||method=getProcIOWriteBytesRateOnly||msg=failed to get process IO write bytes rate",
e);
}
return 0d;
}
@Override
public PeriodStatistics getProcIOReadWriteRate() {
if(procIOReadWriteRate.isEmpty()) {
calcProcIOReadWriteRate();
}
return procIOReadWriteRate.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOReadWriteRate() {
procIOReadWriteRate.add(getProcIOReadWriteRateOnly());
}
private Double getProcIOReadWriteRateOnly() {
return getProcIOReadRateOnly() + getProcIOWriteRateOnly();
}
@Override
public PeriodStatistics getProcIOReadWriteBytesRate() {
if(procIOReadWriteBytesRate.isEmpty()) {
calcProcIOReadWriteBytesRate();
}
return procIOReadWriteBytesRate.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOReadWriteBytesRate() {
procIOReadWriteBytesRate.add(getProcIOReadWriteBytesRateOnly());
}
private Double getProcIOReadWriteBytesRateOnly() {
return getProcIOReadBytesRateOnly() + getProcIOWriteBytesRateOnly();
}
@Override
public PeriodStatistics getProcIOAwaitTimePercent() {
if(procIOAwaitTimePercent.isEmpty()) {
calcProcIOAwaitTimePercent();
}
return procIOAwaitTimePercent.snapshot();
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcIOAwaitTimePercent() {
procIOAwaitTimePercent.add(getProcIOAwaitTimePercentOnly());
}
private Double getProcIOAwaitTimePercentOnly() {
List lines = getOutputByCmd("iotop -P -b -n 1 | grep %d | awk 'NR==1{print $10}'",
"当前进程io读写等待时间占总时间百分比", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Double.parseDouble(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcIOAwaitTimePercent||msg=data is null");
return 0d;
}
}
@Override
public Long getJvmProcYoungGcCount() {
yGcCountCurrent = getJvmProcYoungGcCountOnly();
Long yGcCount = yGcCountCurrent - yGcCountPre;
yGcCountPre = yGcCountCurrent;
return yGcCount;
}
private Long getJvmProcYoungGcCountOnly() {
long gcCounts = 0L;
for (GarbageCollectorMXBean garbageCollector : ManagementFactory
.getGarbageCollectorMXBeans()) {
String name = garbageCollector.getName();
if (StringUtils.isNotBlank(name) && !name.contains("MarkSweep")) {
gcCounts += garbageCollector.getCollectionCount();
}
}
return gcCounts;
}
@Override
public Long getJvmProcFullGcCount() {
fGcCountCurrent = getJvmProcFullGcCountOnly();
Long fGcCount = fGcCountCurrent - fGcCountPre;
fGcCountPre = fGcCountCurrent;
return fGcCount;
}
private Long getJvmProcFullGcCountOnly() {
long gcCounts = 0L;
for (GarbageCollectorMXBean garbageCollector : ManagementFactory
.getGarbageCollectorMXBeans()) {
String name = garbageCollector.getName();
if (StringUtils.isNotBlank(name) && name.contains("MarkSweep")) {
gcCounts += garbageCollector.getCollectionCount();
}
}
return gcCounts;
}
@Override
public Long getJvmProcYoungGcTime() {
yGcTimeCurrent = getJvmProcYoungGcTimeOnly();
Long yGcTime = yGcTimeCurrent - yGcTimePre;
yGcTimePre = yGcTimeCurrent;
return yGcTime;
}
private Long getJvmProcYoungGcTimeOnly() {
long gcTime = 0L;
for (GarbageCollectorMXBean garbageCollector : ManagementFactory
.getGarbageCollectorMXBeans()) {
String name = garbageCollector.getName();
if (StringUtils.isNotBlank(name) && !name.contains("MarkSweep")) {
gcTime += garbageCollector.getCollectionTime();
}
}
return gcTime;
}
@Override
public Long getJvmProcFullGcTime() {
fGcTimeCurrent = getJvmProcFullGcTimeOnly();
Long fGcTime = fGcTimeCurrent - fGcTimePre;
fGcTimePre = fGcTimeCurrent;
return fGcTime;
}
private Long getJvmProcFullGcTimeOnly() {
long gcTime = 0L;
for (GarbageCollectorMXBean garbageCollector : ManagementFactory
.getGarbageCollectorMXBeans()) {
String name = garbageCollector.getName();
if (StringUtils.isNotBlank(name) && name.contains("MarkSweep")) {
gcTime += garbageCollector.getCollectionTime();
}
}
return gcTime;
}
@Override
public Double getJvmProcS0C() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程S0C", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[0]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcS0C||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcS0C||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcS1C() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程S1C", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[1]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcS1C||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcS1C||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcS0U() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程S0U", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[2]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcS0U||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcS0U||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcS1U() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程S1U", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[3]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcS1U||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcS1U||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcEC() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程EC", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[4]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcEC||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcEC||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcEU() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程EU", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[5]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcEU||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcEU||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcOC() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程OC", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[6]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcOC||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcOC||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcOU() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程OU", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[7]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcOU||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcOU||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcMC() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程MC", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[8]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcMC||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcMC||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcMU() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程MU", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[9]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcMU||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcMU||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcCCSC() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程CCSC", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[10]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcCCSC||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcCCSC||msg=data is null");
return 0d;
}
}
@Override
public Double getJvmProcCCSU() {
List lines = getOutputByCmd("jstat -gc %d",
"当前jvm进程CCSU", PID);
if (!lines.isEmpty() && 2 == lines.size() && StringUtils.isNotBlank(lines.get(1))) {
String[] properties = lines.get(1).split("\\s+");
if(12 <= properties.length) {
return Double.parseDouble(properties[11]) * 1024;
} else {
LOGGER.error(
String.format("class=LinuxProcMetricsService||method=getJvmProcCCSU||msg=data is invalid, data is %s", lines.get(1))
);
return 0d;
}
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getJvmProcCCSU||msg=data is null");
return 0d;
}
}
@Override
public Integer getJvmProcThreadNum() {
try {
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
return mxBean.getThreadCount();
} catch (Exception ex) {
LOGGER.error("获取系统资源项[当前jvm进程线程使用数]失败", ex);
return 0;
}
}
@Override
public Integer getJvmProcThreadNumPeak() {
try {
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
return mxBean.getPeakThreadCount();
} catch (Exception ex) {
LOGGER.error("获取系统资源项[jvm进程启动以来线程数峰值]失败", ex);
return 0;
}
}
@Override
public Integer getProcOpenFdCount() {
List lines = getOutputByCmd("ls /proc/%d/fd | wc -l", "jvm进程当前fd使用数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcOpenFdCount()||msg=data is null");
return 0;
}
}
@Override
public List getProcPortListen() {
List result = new ArrayList<>();
List output = getOutputByCmd("netstat -nltp | grep %d | awk '{print $4}' | awk -F: '{print $NF}'",
"当前Jvm进程监听端口", PID);
if (!output.isEmpty()) {
for (String s : output) {
result.add(Integer.parseInt(s));
}
}
return result;
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcNetworkReceiveBytesPs() {
try {
LinuxNetFlow curLinuxNetFlow = new LinuxNetFlow(getProcessPid());
double processReceiveBytesPs = curLinuxNetFlow.getProcessReceiveBytesPs(lastLinuxNetFlowReceive);
lastLinuxNetFlowReceive = curLinuxNetFlow;
procNetworkReceiveBytesPs.add(processReceiveBytesPs);
} catch (Exception e) {
LOGGER.error(
String.format(
"class=LinuxProcMetricsService||method=calcProcNetworkReceiveBytesPs||msg=%s",
e.getMessage()
),
e
);
procNetworkReceiveBytesPs.add(0d);
}
}
@Override
public Double getProcNetworkReceiveBytesPs() {
try {
LinuxNetFlow curLinuxNetFlow = new LinuxNetFlow(getProcessPid());
double processReceiveBytesPs = curLinuxNetFlow.getProcessReceiveBytesPs(lastLinuxNetFlowReceive);
lastLinuxNetFlowReceive = curLinuxNetFlow;
return processReceiveBytesPs;
} catch (Exception e) {
LOGGER.error(
String.format(
"class=LinuxProcMetricsService||method=calcProcNetworkReceiveBytesPs||msg=%s",
e.getMessage()
),
e
);
return 0d;
}
}
@PeriodMethod(periodMs = 5 * 1000)
private void calcProcNetworkSendBytesPs() {
try {
LinuxNetFlow curLinuxNetFlow = new LinuxNetFlow(getProcessPid());
double processTransmitBytesPs = curLinuxNetFlow.getProcessTransmitBytesPs(lastLinuxNetFlowSend);
lastLinuxNetFlowSend = curLinuxNetFlow;
procNetworkSendBytesPs.add(processTransmitBytesPs);
} catch (Exception e) {
LOGGER.error(
String.format(
"class=LinuxProcMetricsService||method=calcProcNetworkSendBytesPs||msg=%s",
e.getMessage()
),
e
);
procNetworkSendBytesPs.add(0d);
}
}
@Override
public Double getProcNetworkSendBytesPs() {
try {
LinuxNetFlow curLinuxNetFlow = new LinuxNetFlow(getProcessPid());
double processTransmitBytesPs = curLinuxNetFlow.getProcessTransmitBytesPs(lastLinuxNetFlowSend);
lastLinuxNetFlowSend = curLinuxNetFlow;
return processTransmitBytesPs;
} catch (Exception e) {
LOGGER.error(
String.format(
"class=LinuxProcMetricsService||method=calcProcNetworkSendBytesPs||msg=%s",
e.getMessage()
),
e
);
return 0d;
}
}
@Override
public PeriodStatistics getProcNetworkConnRate() {
return PeriodStatistics.defaultValue();
}
@Override
public Integer getProcNetworkTcpConnectionNum() {
List lines = getOutputByCmd("netstat -antp | grep -c %d", "当前Jvm进程当前tcp连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpConnectionNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpListeningNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'LISTEN'", "当前Jvm进程当前处于 listening 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpListeningNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpEstablishedNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'ESTABLISHED'", "当前Jvm进程当前处于 ESTABLISHED 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpEstablishedNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpSynSentNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'SYN_SENT'", "当前Jvm进程当前处于 SYN_SENT 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpSynSentNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpSynRecvNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'SYN_RCVD'", "当前Jvm进程当前处于 SYN_RCVD 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpSynRecvNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpFinWait1Num() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'FIN_WAIT1'", "当前Jvm进程当前处于 FIN_WAIT1 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpFinWait1Num||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpFinWait2Num() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'FIN_WAIT2'", "当前Jvm进程当前处于 FIN_WAIT2 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpFinWait2Num||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpTimeWaitNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'TIME_WAIT'", "当前Jvm进程当前处于 time wait 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpTimeWaitNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpClosedNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'CLOSED'", "当前Jvm进程当前处于 CLOSED 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpClosedNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpCloseWaitNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'CLOSE_WAIT'", "当前Jvm进程当前处于 close wait 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpCloseWaitNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpClosingNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'CLOSING'", "当前Jvm进程当前处于 CLOSING 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpClosingNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpLastAckNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'LAST_ACK'", "当前Jvm进程当前处于 LAST_ACK 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpLastAckNum||msg=data is null");
return 0;
}
}
@Override
public Integer getProcNetworkTcpNoneNum() {
List lines = getOutputByCmd("netstat -antp | grep %d | grep -c 'NONE'", "当前Jvm进程当前处于 NONE 状态 tcp 连接数", PID);
if (!lines.isEmpty() && StringUtils.isNotBlank(lines.get(0))) {
return Integer.parseInt(lines.get(0));
} else {
LOGGER.error("class=LinuxProcMetricsService||method=getProcNetworkTcpNoneNum||msg=data is null");
return 0;
}
}
/**
* @return 返回当前 agent 进程 id
*/
private long initializePid() {
final String name = ManagementFactory.getRuntimeMXBean().getName();
try {
return Long.parseLong(name.split("@")[0]);
} catch (final NumberFormatException e) {
LOGGER.warn(String.format("failed parsing PID from [{}]", name), e);
return -1;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy