gala-gopher/refactor-modify-jvmprobe-to-support-pod.patch
xietangxin 71cf797faf sync bugfix patch from openeuler/gala-gopher
(cherry picked from commit 4ea8a981b29acd853dd2d279d658055e0e6e79a1)
2023-04-10 10:53:07 +08:00

1192 lines
43 KiB
Diff

From 5b8ecf7c24ca91a37b2073d4ee1a462f7aab5760 Mon Sep 17 00:00:00 2001
From: dowzyx <zhaoyuxing2@huawei.com>
Date: Thu, 9 Mar 2023 20:30:06 +0800
Subject: [PATCH 16/30] refactor: modify jvmprobe to support pod
---
src/probes/extends/java.probe/build.sh | 100 +++---
src/probes/extends/java.probe/install.sh | 5 +-
.../jvm.probe/config/META-INF/MANIFEST.MF | 1 -
.../java.probe/jvm.probe/jvm_probe.meta | 231 ++++++++++---
.../java.probe/jvm.probe/src/JvmProbe.java | 305 +++++++++++++-----
.../extends/java.probe/jvm.probe/src/Vm.java | 173 ----------
.../jvm.probe/src/agent/JvmProbeAgent.java | 188 +++++++++++
.../src/agent/config/META-INF/MANIFEST.MF | 6 +
8 files changed, 657 insertions(+), 352 deletions(-)
delete mode 100644 src/probes/extends/java.probe/jvm.probe/src/Vm.java
create mode 100644 src/probes/extends/java.probe/jvm.probe/src/agent/JvmProbeAgent.java
create mode 100644 src/probes/extends/java.probe/jvm.probe/src/agent/config/META-INF/MANIFEST.MF
diff --git a/src/probes/extends/java.probe/build.sh b/src/probes/extends/java.probe/build.sh
index 0ea7782..3c6f4e0 100755
--- a/src/probes/extends/java.probe/build.sh
+++ b/src/probes/extends/java.probe/build.sh
@@ -4,95 +4,79 @@ PRJ_DIR=$(dirname $(readlink -f "$0"))
BUILD_FILES=${PRJ_DIR}/jvm.probe
cd ${BUILD_FILES}
-function find_jars()
+function find_cmd_jar()
{
- if [ -z $JAVA_HOME ];
- then
- # find jdk
- clink_path=$(echo $(ls -lrt $javac_link) | awk -F " " '{print $NF}' )
- link_path=$(echo $(ls -lrt $clink_path) | awk -F " " '{print $NF}' )
- jdk_path=$(dirname $(dirname $link_path))
- dir=$jdk_path
- else
- dir=$JAVA_HOME
- fi
-
- #tools.jar
- if [ -e $dir/lib/tools.jar ];
- then
- mkdir -p lib
- cp $dir/lib/tools.jar lib/
- else
- echo "Error: tools.jar not found"
- return 1
- fi
-
- #management.jar
- if [ -e $dir/jre/lib/management-agent.jar ];
+ if [ -z $(which jar 2>/dev/null) ];
then
- cp $dir/jre/lib/management-agent.jar lib/
- else
- echo "Error: management-agent.jar not found"
+ echo "Error: jar command not found"
return 1
- fi
-
- return 0
+ else
+ return 0
+ fi
}
-function make_probe_jar()
+function make_probe_agent_jar()
{
- mkdir -p tmp
- cd tmp
- javac -cp ../lib/tools.jar ../src/*.java -d ./
+ mkdir -p tmp
+ cd tmp
+ javac ../src/agent/JvmProbeAgent.java -d ./
+ cd ..
+ jar cfm JvmProbeAgent.jar src/agent/config/META-INF/MANIFEST.MF -C tmp/ .
- if [ -z $(which jar 2>/dev/null) ];
- then
- echo "Error: jar command not found"
- return 1
- else
- jar xf ../lib/tools.jar #>/dev/null 2>&1
- cp ../lib/management-agent.jar ./
- cd ..
- jar cfm JvmProbe.jar config/META-INF/MANIFEST.MF -C tmp/ . #2>/dev/null
- fi
+ rm -rf tmp 2>/dev/null
+ return 0
+}
+
+function make_probe_jar()
+{
+ mkdir -p tmp
+ cd tmp/
+ javac ../src/JvmProbe.java -d .
+ cd ..
+ jar cfm JvmProbe.jar config/META-INF/MANIFEST.MF -C tmp/ .
- rm -rf tmp 2>/dev/null
-
- return 0
+ rm -rf tmp 2>/dev/null
+ return 0
}
function compile_clean()
{
- rm -rf lib 2>/dev/null
- rm -rf tmp 2>/dev/null
+ rm -rf tmp 2>/dev/null
}
if [ "$1" == "-c" -o "$1" == "--clean" ];
then
compile_clean
+ rm -f *.jar 2>/dev/null
exit
fi
java_link=$(which java 2>/dev/null)
javac_link=$(which javac 2>/dev/null)
-
-if [ -z $java_link ] || [ -z $javac_link ];
+
+if [ -z $java_link ] || [ -z $javac_link ];
then
echo "Error: java and javac : command not found"
exit 1
-else
- find_jars
+else
+ find_cmd_jar
if [ $? -eq 1 ];
then
- exit 1
- fi
-
+ exit 1
+ fi
+
+ make_probe_agent_jar
+ if [ $? -eq 1 ];
+ then
+ exit 1
+ fi
+
make_probe_jar
if [ $? -eq 1 ];
then
- exit 1
+ exit 1
fi
-
+
compile_clean
exit
fi
diff --git a/src/probes/extends/java.probe/install.sh b/src/probes/extends/java.probe/install.sh
index ee653b5..4111fb3 100755
--- a/src/probes/extends/java.probe/install.sh
+++ b/src/probes/extends/java.probe/install.sh
@@ -2,6 +2,7 @@
PROGRAM=$0
PRJ_DIR=$(dirname $(readlink -f "$0"))
INSTALL_FILES="jvm.probe/JvmProbe.jar"
+INSTALL_FILES+=" jvm.probe/JvmProbeAgent.jar"
while getopts ":b:c:" opt
do
@@ -15,6 +16,8 @@ done
cd ${PRJ_DIR}
if [ ${INSTALL_PATH} ]; then
mkdir -p ${INSTALL_PATH}
- \cp ${INSTALL_FILES} ${INSTALL_PATH}
+ for file in ${INSTALL_FILES}; do
+ cp ${file} ${INSTALL_PATH}
+ done
fi
diff --git a/src/probes/extends/java.probe/jvm.probe/config/META-INF/MANIFEST.MF b/src/probes/extends/java.probe/jvm.probe/config/META-INF/MANIFEST.MF
index 9f2a9af..fd73d72 100644
--- a/src/probes/extends/java.probe/jvm.probe/config/META-INF/MANIFEST.MF
+++ b/src/probes/extends/java.probe/jvm.probe/config/META-INF/MANIFEST.MF
@@ -1,5 +1,4 @@
Manifest-Version: 1.0
-Class-Path: management-agent.jar
Created-By: 1.8.0_333 (Oracle Corporation)
Main-Class: JvmProbe
diff --git a/src/probes/extends/java.probe/jvm.probe/jvm_probe.meta b/src/probes/extends/java.probe/jvm.probe/jvm_probe.meta
index bcce601..bb9d01a 100755
--- a/src/probes/extends/java.probe/jvm.probe/jvm_probe.meta
+++ b/src/probes/extends/java.probe/jvm.probe/jvm_probe.meta
@@ -3,100 +3,259 @@ version = "1.0.0"
measurements:
(
{
- table_name: "jvm",
+ table_name: "jvm_info",
entity_name: "jvm",
fields:
(
{
- description: "ID of current java process ",
+ description: "ID of current java process.",
type: "key",
name: "tgid",
},
{
- description: "pkg_name-java_main_class",
+ description: "JVM runtime Environment.",
type: "label",
- name: "pkg_name_main_class",
+ name: "runtime",
},
{
- description: "JVM specification version ",
+ description: "....",
type: "label",
- name: "jvm_version",
+ name: "vendor",
},
{
- description: "JVM implementation name ",
+ description: "....",
type: "label",
- name: "jvm_type",
+ name: "version",
},
{
- description: "Garbage collectors` average usage",
+ description: "a fixed num 1 as metric",
type: "gauge",
- name: "gc_activity_util",
+ name: "info",
+ }
+ )
+ },
+ {
+ table_name: "jvm_process",
+ entity_name: "jvm",
+ fields:
+ (
+ {
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
},
{
- description: "Garbage collector collection counts",
+ description: "Start time of the process since unix epoch in seconds.",
type: "gauge",
- name: "gc_total_count",
+ name: "process_start_time_seconds",
},
{
- description: "Total garbage collector collection time",
+ description: "Total user and system CPU time spent in seconds.",
type: "gauge",
- name: "gc_total_seconds",
+ name: "process_cpu_seconds_total",
},
+ )
+ },
+ {
+ table_name: "jvm_class",
+ entity_name: "jvm",
+ fields:
+ (
{
- description: "Process start time in seconds",
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
+ },
+ {
+ description: "Start time of the process since unix epoch in seconds.",
type: "gauge",
- name: "process_start_time_seconds",
+ name: "classes_currently_loaded",
},
{
- description: "Process run time in seconds",
+ description: "Total user and system CPU time spent in seconds.",
type: "gauge",
- name: "process_run_time_seconds",
+ name: "classes_loaded_total",
+ },
+ )
+ },
+ {
+ table_name: "jvm_thread",
+ entity_name: "jvm",
+ fields:
+ (
+ {
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
},
{
- description: "The number of threads in the current process",
+ description: "Current thread count of a JVM.",
type: "gauge",
name: "threads_current",
},
{
- description: "The peak number of threads of the java process",
+ description: "Daemon thread count of a JVM.",
+ type: "gauge",
+ name: "threads_daemon",
+ },
+ {
+ description: "Peak thread count of a JVM.",
type: "gauge",
name: "threads_peak",
},
{
- description: "Deadlocked JVM thread number",
+ description: "Started thread count of a JVM.",
+ type: "gauge",
+ name: "threads_started_total",
+ },
+ {
+ description: "Cycles of JVM-threads that are in deadlock waiting to acquire object monitors or ownable synchronizers.",
type: "gauge",
name: "threads_deadlocked",
},
+ )
+ },
+ {
+ table_name: "jvm_mem",
+ entity_name: "jvm",
+ fields:
+ (
+ {
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
+ },
+ {
+ description: "type of JVM memory type: heap or noheap.",
+ type: "key",
+ name: "area",
+ },
{
- description: "Used bytes of JVM _Heap memory area",
+ description: "Used bytes of a given JVM memory area.",
type: "gauge",
- name: "heap_memory_bytes_used",
+ name: "memory_bytes_used",
},
{
- description: "JVM _Heap occupation",
+ description: "Committed (bytes) of a given JVM memory area.",
type: "gauge",
- name: "heap_occuped_percent",
+ name: "memory_bytes_committed",
},
{
- description: "Used bytes of JVM _NonHeap memory area",
+ description: "Max (bytes) of a given JVM memory area.",
type: "gauge",
- name: "nonheap_memory_bytes_used",
+ name: "memory_bytes_max",
},
{
- description: "JVM _NonHeap occupation",
+ description: "Initial bytes of a given JVM memory area.",
type: "gauge",
- name: "nonheap_occuped_percent",
+ name: "memory_bytes_init",
},
+ )
+ },
+ {
+ table_name: "jvm_mem_pool",
+ entity_name: "jvm",
+ fields:
+ (
{
- description: "The total capacity of the JVM buffer pools",
- type: "gauge",
- name: "buffer_pool_total_size",
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
},
{
- description: "the memory that the JVM uses for buffer pools",
- type: "gauge",
- name: "buffer_pool_used_bytes",
- }
+ description: "....",
+ type: "key",
+ name: "pool",
+ },
+ {
+ description: "Used bytes of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_bytes_used",
+ },
+ {
+ description: "Committed bytes of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_bytes_committed",
+ },
+ {
+ description: "Max bytes of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_bytes_max",
+ },
+ {
+ description: "Used bytes after last collection of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_collection_used_bytes",
+ },
+ {
+ description: "Committed after last collection bytes of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_collection_committed_bytes",
+ },
+ {
+ description: "Max bytes after last collection of a given JVM memory pool.",
+ type: "gauge",
+ name: "memory_pool_collection_max_bytes",
+ },
+ )
+ },
+ {
+ table_name: "jvm_buf_pool",
+ entity_name: "jvm",
+ fields:
+ (
+ {
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
+ },
+ {
+ description: "....",
+ type: "label",
+ name: "pool",
+ },
+ {
+ description: "Used bytes of a given JVM buffer pool.",
+ type: "gauge",
+ name: "buffer_pool_used_bytes",
+ },
+ {
+ description: "Used buffers of a given JVM buffer pool.",
+ type: "gauge",
+ name: "buffer_pool_used_buffers",
+ },
+ {
+ description: "Bytes capacity of a given JVM buffer pool.",
+ type: "gauge",
+ name: "buffer_pool_capacity_bytes",
+ },
+ )
+ },
+ {
+ table_name: "jvm_gc",
+ entity_name: "jvm",
+ fields:
+ (
+ {
+ description: "ID of current java process.",
+ type: "key",
+ name: "tgid",
+ },
+ {
+ description: "....",
+ type: "label",
+ name: "gc",
+ },
+ {
+ description: "Collection count of a given JVM garbage collector.",
+ type: "gauge",
+ name: "gc_collection_seconds_count",
+ },
+ {
+ description: "Time spent in a given JVM garbage collector in seconds.",
+ type: "gauge",
+ name: "gc_collection_seconds_sum",
+ },
)
}
)
diff --git a/src/probes/extends/java.probe/jvm.probe/src/JvmProbe.java b/src/probes/extends/java.probe/jvm.probe/src/JvmProbe.java
index 9c67f17..81d64ba 100644
--- a/src/probes/extends/java.probe/jvm.probe/src/JvmProbe.java
+++ b/src/probes/extends/java.probe/jvm.probe/src/JvmProbe.java
@@ -1,83 +1,222 @@
-import com.sun.tools.attach.*;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
-import java.util.List;
-import java.util.HashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-public class JvmProbe {
-
- public static List<VirtualMachineDescriptor> virtualMachineDescriptors;
- public static ExecutorService executorService;
- public static int time = 5;
- public static String agentPath;
- final static String agent = "management-agent.jar";
-
- public static void main(String[] args) {
- ArgsParse(args);
- try {
- agentPath = getTemporaryRes(agent);
- } catch (IOException e) {
- System.out.println(e.getMessage());
- System.exit(1);
- }
-
- while (true) {
- try {
- probe();
- TimeUnit.SECONDS.sleep(time);
- } catch (InterruptedException e) {
- System.out.println(e.getMessage());
- }
- }
- }
-
- public static void ArgsParse(String[] args) {
- int argsLen = args.length;
- HashMap<String,String> argsMap = new HashMap<>();
- for (int i = 0; i < argsLen / 2; i++) {
- argsMap.put(args[i], args[i + 1]);
- }
- //set
- if (argsMap.containsKey("-t")) {
- time = Integer.parseInt(argsMap.get("-t"));
- }
- }
-
- public static void probe() {
- virtualMachineDescriptors = VirtualMachine.list();
- if (executorService == null) {
- executorService = Executors.newFixedThreadPool(5);
- }
-
- for (VirtualMachineDescriptor virtualMachineDescriptor : virtualMachineDescriptors) {
- executorService.submit(() -> {
- try {
- Vm vm = new Vm(virtualMachineDescriptor, agentPath);
- vm.getData();
- } catch (IOException | AgentLoadException | AttachNotSupportedException | AgentInitializationException e) {
- System.out.println(e.getMessage());
- }
- });
- }
- }
-
- public static String getTemporaryRes(String resource) throws IOException {
- //read embedded resource from this JAR
- InputStream inputStream = JvmProbe.class.getResourceAsStream(resource);
- if(inputStream == null){
- throw new IOException("Resource not found in the JAR");
- }
- // create a temporary file
- File temporaryFile = File.createTempFile("resource", null);
- temporaryFile.deleteOnExit();
- // Copy the resource data into the temporary file
- Files.copy(inputStream, temporaryFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- return temporaryFile.getAbsolutePath();
- }
-}
+import java.io.IOException;
+import java.io.File;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+import java.lang.Process;
+import java.lang.ProcessBuilder;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.FileInputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+
+public class JvmProbe {
+
+ private static String PROC_COMM_CMD = "/usr/bin/cat /proc/%d/comm 2> /dev/null";
+ private static String PROC_STATUS_CMD =
+ "/usr/bin/cat /proc/%s/status 2> /dev/null | grep -w NStgid | awk -F ' ' '{print $NF}'";
+ private static String BPFTOOL_DUMP_PROCMAP_CMD =
+ "bpftool map dump pinned /sys/fs/bpf/probe/proc_map 2> /dev/null | grep key | awk -F ' ' '{print $5$4$3$2}'";
+ // jvm_attach <pid> <nspid> load instrument false "/tmp/JvmProbeAgent.jar=<pid>,<nspid>"
+ private static String ATTACH_CMD = "%s %s %s load instrument false \"%s=%s,%s\"";
+ private final static String ATTACH_BIN_PATH = "/opt/gala-gopher/extend_probes/jvm_attach";
+ private final static String HOST_JAR_DIR = "/opt/gala-gopher/extend_probes";
+ private final static String NS_TMP_DIR = "/tmp";
+ private final static String AGENT_JAR_NAME = "JvmProbeAgent.jar";
+ private static final String METRIC_FILE_NAME = "jvm-metrics.txt";
+ private static int period = 5;
+
+ private static class ProcessInfo {
+ String pid;
+ String nspid;
+ }
+
+ private static void argsParse(String[] args) {
+ int argsLen = args.length;
+ HashMap<String,String> argsMap = new HashMap<>();
+ for (int i = 0; i < argsLen / 2; i++) {
+ argsMap.put(args[i], args[i + 1]);
+ }
+ //set
+ if (argsMap.containsKey("-t")) {
+ period = Integer.parseInt(argsMap.get("-t"));
+ }
+ }
+
+ private static Boolean detactProcIsJava(int procId) throws IOException {
+ List<String> commandList = new ArrayList<>();
+ commandList.add("sh");
+ commandList.add("-c");
+ commandList.add(String.format(PROC_COMM_CMD, procId));
+
+ ProcessBuilder pb = new ProcessBuilder(commandList);
+ Process process = pb.start();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ if (line.equals("java")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static List<Integer> checkProcessToAttach() throws IOException, InterruptedException {
+ List<Integer> pidList = new ArrayList<>();
+ List<String> commandList = new ArrayList<>();
+ commandList.add("sh");
+ commandList.add("-c");
+ commandList.add(BPFTOOL_DUMP_PROCMAP_CMD);
+
+ ProcessBuilder pb = new ProcessBuilder(commandList);
+ Process process = pb.start();
+ int ret = process.waitFor();
+ if (ret != 0) {
+ System.out.println("Process exited with code: " + ret + " cmd: " + commandList);
+ return pidList; // empty list
+ }
+ BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ int decimal = Integer.decode(String.format("0x%s", line));
+ if (detactProcIsJava(decimal)) {
+ pidList.add(decimal);
+ }
+ }
+
+ return pidList;
+ }
+
+ private static ProcessInfo setEffectiveId(String pid) throws IOException {
+ ProcessInfo attachInfo = new ProcessInfo();
+ List<String> commandList = new ArrayList<>();
+ commandList.add("sh");
+ commandList.add("-c");
+ commandList.add(String.format(PROC_STATUS_CMD, pid));
+
+ ProcessBuilder pb = new ProcessBuilder(commandList);
+ Process process = pb.start();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ attachInfo.nspid = line;
+ }
+
+ attachInfo.pid = pid;
+ return attachInfo;
+ }
+
+ private static void setJarFileToTmp(String Pid) throws IOException {
+ File nsAgentPath = new File(String.format("/proc/%s/root%s/%s", Pid, NS_TMP_DIR, AGENT_JAR_NAME));
+ File hostAgentJarPath = new File(String.format("%s/%s", HOST_JAR_DIR, AGENT_JAR_NAME));
+
+ Files.copy(hostAgentJarPath.toPath(), nsAgentPath.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ private static Boolean getNsJarPath(ProcessInfo attachInfo) {
+ if (attachInfo.nspid.equals(attachInfo.pid)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static void delTmpFile(File file) {
+ if (file.delete() != true) {
+ System.out.println("delete file failed.\n");
+ }
+ }
+
+ private static int doAttach(ProcessInfo attachInfo) throws IOException, InterruptedException {
+ int ret = -1;
+ List<String> commandList = new ArrayList<>();
+ if (attachInfo.pid == null || attachInfo.nspid == null) {
+ System.out.println("attach failed becase null pid or nspid");
+ return -1;
+ }
+ String nsJarPath;
+ if (getNsJarPath(attachInfo)) {
+ nsJarPath = String.format("/proc/%s/root%s/%s", attachInfo.pid, NS_TMP_DIR, AGENT_JAR_NAME);
+ } else {
+ nsJarPath = String.format("%s/%s", NS_TMP_DIR, AGENT_JAR_NAME);
+ }
+
+ commandList.add("sh");
+ commandList.add("-c");
+ commandList.add(String.format(ATTACH_CMD,
+ ATTACH_BIN_PATH, attachInfo.pid, attachInfo.nspid, nsJarPath, attachInfo.pid, attachInfo.nspid));
+
+ ProcessBuilder pb = new ProcessBuilder(commandList);
+ Process process = pb.start();
+ ret = process.waitFor();
+ if (ret != 0) {
+ System.out.println("Program attach exited with code: " + ret + " command: " + commandList);
+ }
+
+ return ret;
+ }
+
+ private static int readMetricFile(ProcessInfo attachInfo) throws IOException {
+ File jvmMetricFile = new File(String.format("/proc/%s/root/tmp/%s", attachInfo.pid, METRIC_FILE_NAME));
+ if (!jvmMetricFile.exists()) {
+ System.out.printf("Proc[%s] has no jvm metric file in /tmp path.\n", attachInfo.pid);
+ return 0;
+ }
+
+ InputStreamReader streamReader = new InputStreamReader(new FileInputStream(jvmMetricFile));
+ BufferedReader br = new BufferedReader(streamReader);
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+
+ // del metric file after read
+ if (jvmMetricFile.delete() != true) {
+ System.out.println("delete jvm metric file failed.\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ private static void probe() throws IOException, InterruptedException {
+ List<Integer> jvmProcList = checkProcessToAttach();
+ System.out.println(jvmProcList);
+
+ for (int i = 0; i < jvmProcList.size(); i++) {
+ ProcessInfo attachInfo = setEffectiveId(jvmProcList.get(i).toString());
+ try {
+ setJarFileToTmp(attachInfo.pid);
+ } catch (IOException e) {
+ System.out.println("copy host_jar to ns_tmp failed, err: %s" + e.getMessage());
+ continue;
+ }
+ doAttach(attachInfo);
+ readMetricFile(attachInfo);
+ }
+ }
+
+ public static void main(String[] args) {
+ argsParse(args);
+ while (true) {
+ try {
+ probe();
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ } catch (InterruptedException e) {
+ System.out.println(e.getMessage());
+ }
+ // sleep
+ try {
+ TimeUnit.SECONDS.sleep(period);
+ } catch (InterruptedException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+ }
+
+}
diff --git a/src/probes/extends/java.probe/jvm.probe/src/Vm.java b/src/probes/extends/java.probe/jvm.probe/src/Vm.java
deleted file mode 100644
index 61d111d..0000000
--- a/src/probes/extends/java.probe/jvm.probe/src/Vm.java
+++ /dev/null
@@ -1,173 +0,0 @@
-import com.sun.tools.attach.*;
-import javax.management.MBeanServerConnection;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-import java.io.IOException;
-import java.lang.management.*;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-
-public class Vm {
- public VirtualMachineDescriptor virtualMachineDescriptor;
- public MBeanServerConnection mBeanServerConnection;
- public JMXConnector connector;
- public final String canonicalPath;
- public StringBuilder res;
-
- final String localConnectorAddress = "com.sun.management.jmxremote.localConnectorAddress";
-
- public Vm(VirtualMachineDescriptor virtualMachineDescriptor,String canonicalPath) throws AgentLoadException, IOException, AttachNotSupportedException, AgentInitializationException {
- this.virtualMachineDescriptor = virtualMachineDescriptor;
- this.canonicalPath = canonicalPath;
- getTargetVmConnection(virtualMachineDescriptor.id());
- res = new StringBuilder();
- }
-
- private void getTargetVmConnection(String vmId) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
-
- VirtualMachine virtualMachine = VirtualMachine.attach(vmId);
- virtualMachine.loadAgent(canonicalPath);
-
- String connectorAddress = (String) virtualMachine.getAgentProperties().get(localConnectorAddress);
- virtualMachine.detach();
- this.connector = JMXConnectorFactory.connect(new JMXServiceURL(connectorAddress));
- this.mBeanServerConnection = connector.getMBeanServerConnection();
- }
-
- public void getData() {
- try {
- getInfo(this.mBeanServerConnection);
- } catch (IOException e) {
- System.out.println(e.getMessage());
- } finally {
- try {
- connector.close();
- } catch (IOException e) {
- System.out.println(e.getMessage());
- }
- }
- }
-
- private void getInfo(MBeanServerConnection connection) throws IOException {
- RuntimeMXBean runtimeMXBean = ManagementFactory.newPlatformMXBeanProxy(
- connection, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
- com.sun.management.OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(connection,
- ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, com.sun.management.OperatingSystemMXBean.class);
- List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getPlatformMXBeans(
- connection,GarbageCollectorMXBean.class);
- ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(
- connection, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
- MemoryMXBean memoryMXBean = ManagementFactory.newPlatformMXBeanProxy(
- connection, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
- List<BufferPoolMXBean> pools = ManagementFactory.getPlatformMXBeans(
- connection,BufferPoolMXBean.class);
- // tid % mainclass
- String jvmPid = virtualMachineDescriptor.id();
- String[] split = virtualMachineDescriptor.displayName().split(" ");
- String pkgNameMainClass = split[0];
- res.append(String.format("|jvm|%s|%s|", jvmPid, pkgNameMainClass));
-
- // vesion % type
- String jvmVersion = runtimeMXBean.getSpecVersion();
- String jvmType = runtimeMXBean.getVmName();
- res.append(String.format("%s|%s|", jvmVersion, jvmType));
-
- // gc
- double gcDetail = getGarbageCollectionUsage(runtimeMXBean, operatingSystemMXBean, garbageCollectorMXBeans);
- long gc_counts = getTotalGarbageCollectionCount(garbageCollectorMXBeans);
- long gc_time_ms = getTotalGarbageCollectionTime(garbageCollectorMXBeans);
- res.append(String.format("%.2f|%d|%d|", gcDetail, gc_counts, gc_time_ms));
- // process & thread
- Long processStartTimeSeconds = runtimeMXBean.getStartTime();
- Long processCpuSecondsTotal = runtimeMXBean.getUptime();
-
- int threadsCurrent = threadMXBean.getThreadCount();
- int threadsPeak = threadMXBean.getPeakThreadCount();
- int threadsDeadlocked = 0;
- if(threadMXBean.findDeadlockedThreads() != null) {
- threadsDeadlocked = threadMXBean.findDeadlockedThreads().length;
- }
-
- res.append(String.format("%d|%d|%d|%d|%d|", processStartTimeSeconds, processCpuSecondsTotal, threadsCurrent, threadsPeak, threadsDeadlocked));
-
- // heap
- double heap_occupied = 100.0 * Double.valueOf(memoryMXBean.getHeapMemoryUsage().getCommitted()) / memoryMXBean.getHeapMemoryUsage().getMax();
- long heap_used = memoryMXBean.getHeapMemoryUsage().getUsed();
- res.append(String.format("%d|%.2f|", heap_used, heap_occupied));
-
- // noheap
- long noheap_used = memoryMXBean.getNonHeapMemoryUsage().getUsed();
- double noheap_occupied = memoryMXBean.getNonHeapMemoryUsage().getMax();
- if(noheap_occupied > 0) {
- noheap_occupied = 100.0 * Double.valueOf(memoryMXBean.getNonHeapMemoryUsage().getCommitted()) / noheap_occupied;
- res.append(String.format("%d|%.2f|", noheap_used, noheap_occupied));
- }
- else {
- res.append(String.format("%d|%.0f|", noheap_used,noheap_occupied));
- }
- // bufferpool
- long bf_capacity = getTotalBufferPoolsCapacity(pools);
- long bf_used = getTotalBufferPoolsUsed(pools);
- res.append(String.format("%d|%d|\n", bf_capacity, bf_used));
- System.out.printf(res.toString());
- }
-
- private long getTotalGarbageCollectionCount(List<GarbageCollectorMXBean> garbageCollectorMXBeans) {
- long gc_count=0;
- for(GarbageCollectorMXBean gc :garbageCollectorMXBeans) {
- gc_count +=gc.getCollectionCount();
- }
- return gc_count;
- }
-
- private long getTotalGarbageCollectionTime(List<GarbageCollectorMXBean> gcmList) {
- long total_ms=0;
- for(GarbageCollectorMXBean gc :gcmList) {
- total_ms += gc.getCollectionTime();
- }
- return total_ms;
- }
-
- private double getGarbageCollectionUsage(RuntimeMXBean runtime, com.sun.management.OperatingSystemMXBean os, List<GarbageCollectorMXBean> gcmList) {
- // the uptime of the Java virtual machine
- long prevUpTime = runtime.getUptime();
- // the approximate accumulated collection elapsed time
- long prevProcessGcTime = getTotalGarbageCollectionTime(gcmList);
- // the number of processors available to the Java virtual machine
- int processorCount = os.getAvailableProcessors();
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- System.out.println(e.getMessage());
- System.exit(1);
- }
-
- long upTime = runtime.getUptime();
- long processGcTime = getTotalGarbageCollectionTime(gcmList);
- long upTimeDiff = upTime - prevUpTime;
- long processGcTimeDiff = processGcTime - prevProcessGcTime;
-
- double gcDetail = (processGcTimeDiff * 100.0 / processorCount / upTimeDiff);
- return gcDetail;
- }
-
- private long getTotalBufferPoolsCapacity(List<BufferPoolMXBean> bufferpools) {
- long total_bytes = 0;
- for (BufferPoolMXBean bpool : bufferpools) {
- total_bytes += bpool.getTotalCapacity();
- }
- return total_bytes;
- }
-
- private long getTotalBufferPoolsUsed(List<BufferPoolMXBean> bufferpools) {
- long total_bytes = 0;
- for (BufferPoolMXBean bpool : bufferpools) {
- total_bytes += bpool.getMemoryUsed();
- }
- return total_bytes;
- }
-
-}
-
diff --git a/src/probes/extends/java.probe/jvm.probe/src/agent/JvmProbeAgent.java b/src/probes/extends/java.probe/jvm.probe/src/agent/JvmProbeAgent.java
new file mode 100644
index 0000000..488c73c
--- /dev/null
+++ b/src/probes/extends/java.probe/jvm.probe/src/agent/JvmProbeAgent.java
@@ -0,0 +1,188 @@
+package agent;
+
+import java.util.List;
+import java.io.IOException;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.lang.management.ManagementFactory;
+import com.sun.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.BufferPoolMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+
+public class JvmProbeAgent {
+
+ private static final int MSEC_PER_SEC = 1000;
+ private static final int NSEC_PER_SEC = 1000000;
+ private static final String METRIC_FILE_NAME = "jvm-metrics.txt";
+ private static String pid;
+ private static String nspid;
+
+ private static String getMetricFilePath() {
+ String filePath = String.format("/proc/%s/root/tmp/%s", nspid, METRIC_FILE_NAME);
+ return filePath;
+ }
+
+ private static void writeMetricRecords(String record) {
+ try {
+ File file = new File(getMetricFilePath());
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
+ BufferedWriter bw = new BufferedWriter(fw);
+ bw.write(record);
+ bw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void getJmxInfo() throws IOException {
+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
+ ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+ ClassLoadingMXBean clBean = ManagementFactory.getClassLoadingMXBean();
+ MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
+ MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
+ MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
+ List<MemoryPoolMXBean> memPoolBeans = ManagementFactory.getMemoryPoolMXBeans();
+ List<BufferPoolMXBean> bufPoolBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
+ List<GarbageCollectorMXBean> garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans();
+
+ infoCollector(runtimeBean);
+ processCollector(runtimeBean, osBean);
+ classCollector(clBean);
+ threadCollector(threadBean);
+ memoryAreaCollector(heapUsage, "heap");
+ memoryAreaCollector(nonHeapUsage, "nonheap");
+ memoryPoolCollector(memPoolBeans);
+ bufferPoolCollector(bufPoolBeans);
+ gcCollector(garbageCollectors);
+ }
+
+ private static void infoCollector(RuntimeMXBean runtimeBean) {
+ String jvmName = runtimeBean.getVmName();
+ String jvmVersion = runtimeBean.getVmVersion(); // 原始的为getSpecVersion();
+ String jvmVender = runtimeBean.getVmVendor();
+
+ writeMetricRecords(String.format("|jvm_info|%s|%s|%s|%s|%d|\n", pid, jvmName, jvmVender, jvmVersion, 1));
+ }
+
+ private static void processCollector(RuntimeMXBean runtimeBean, OperatingSystemMXBean osBean) {
+ long processStartTime = runtimeBean.getStartTime(); // ms
+ try {
+ Long processCpuTime = callLongGetter(osBean.getClass().getMethod("getProcessCpuTime"), osBean); // ns
+ writeMetricRecords(String.format("|jvm_process|%s|%d|%d|\n", pid, processStartTime, processCpuTime));
+ } catch (Exception e) {
+ //System.out.println("error");
+ }
+ }
+
+ private static Long callLongGetter(Method method, Object obj) throws InvocationTargetException {
+ try {
+ return (Long) method.invoke(obj);
+ } catch (IllegalAccessException e) {
+ // Expected, the declaring class or interface might not be public.
+ }
+
+ for (Class<?> clazz : method.getDeclaringClass().getInterfaces()) {
+ try {
+ Method interfaceMethod = clazz.getMethod(method.getName(), method.getParameterTypes());
+ Long result = callLongGetter(interfaceMethod, obj);
+ if (result != null) {
+ return result;
+ }
+ } catch (NoSuchMethodException e) {
+ // Expected, class might implement multiple, unrelated interfaces.
+ }
+ }
+ return null;
+ }
+
+ // thread
+ private static void threadCollector(ThreadMXBean threadBean) {
+ int currentThreadCnt = threadBean.getThreadCount();
+ int daemonThreadCnt = threadBean.getDaemonThreadCount();
+ int peakThreadCnt = threadBean.getPeakThreadCount();
+ long startThreadCnt = threadBean.getTotalStartedThreadCount();
+ long cycleThreadDeadlocked = 0;
+ long[] deadlocks = threadBean.findDeadlockedThreads();
+ if (deadlocks != null && deadlocks.length > 0) {
+ cycleThreadDeadlocked = deadlocks.length;
+ }
+ writeMetricRecords(String.format("|jvm_thread|%s|%d|%d|%d|%d|%d|\n",
+ pid, currentThreadCnt, daemonThreadCnt, peakThreadCnt, startThreadCnt, cycleThreadDeadlocked));
+ }
+
+ private static void classCollector(ClassLoadingMXBean clBean) {
+ int currentClassCnt = clBean.getLoadedClassCount();
+ long totalClassCnt = clBean.getTotalLoadedClassCount();
+ writeMetricRecords(String.format("|jvm_class|%s|%d|%d|\n", pid, currentClassCnt, totalClassCnt));
+ }
+
+ // memory
+ private static void memoryAreaCollector(MemoryUsage memUsage, String area) {
+ long memUsed = memUsage.getUsed();
+ long memCommitted = memUsage.getCommitted();
+ long memMax = memUsage.getMax();
+ long memInit = memUsage.getInit();
+ writeMetricRecords(String.format("|jvm_mem|%s|%s|%d|%d|%d|%d|\n", pid, area, memUsed, memCommitted, memMax, memInit));
+ }
+
+ // memory_pool
+ private static void memoryPoolCollector(List<MemoryPoolMXBean> poolBeans) {
+ for (final MemoryPoolMXBean pool : poolBeans) {
+ MemoryUsage poolUsage = pool.getUsage();
+ if (poolUsage != null) {
+ writeMetricRecords(String.format("|jvm_mem_pool|%s|%s|%d|%d|%d|",
+ pid, pool.getName(), poolUsage.getUsed(), poolUsage.getCommitted(), poolUsage.getMax()));
+ }
+ MemoryUsage colPoolUsage = pool.getCollectionUsage();
+ if (colPoolUsage != null) {
+ writeMetricRecords(String.format("%d|%d|%d|",
+ colPoolUsage.getUsed(), colPoolUsage.getCommitted(), colPoolUsage.getMax()));
+ } else {
+ writeMetricRecords(String.format("-1|-1|-1|"));
+ }
+ writeMetricRecords(String.format("\n"));
+ }
+ }
+
+ // buffer_pool
+ private static void bufferPoolCollector(List<BufferPoolMXBean> bufferPools) {
+ for (BufferPoolMXBean pool : bufferPools) {
+ writeMetricRecords(String.format("|jvm_buf_pool|%s|%s|%d|%d|%d|\n",
+ pid, pool.getName(), pool.getMemoryUsed(), pool.getCount(), pool.getTotalCapacity()));
+ }
+ }
+
+ // gc
+ private static void gcCollector(List<GarbageCollectorMXBean> garbageCollectors) {
+ for (GarbageCollectorMXBean gc : garbageCollectors) {
+ writeMetricRecords(String.format("|jvm_gc|%s|%s|%d|%d|\n",
+ pid, gc.getName(), gc.getCollectionCount(), gc.getCollectionTime())); // ms
+ }
+ }
+
+
+ public static void agentmain(String agentArgs) {
+ String[] argStr = agentArgs.split("[,]");
+ pid = argStr[0];
+ nspid = argStr[1];
+ try {
+ getJmxInfo();
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+}
diff --git a/src/probes/extends/java.probe/jvm.probe/src/agent/config/META-INF/MANIFEST.MF b/src/probes/extends/java.probe/jvm.probe/src/agent/config/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..2d6f14f
--- /dev/null
+++ b/src/probes/extends/java.probe/jvm.probe/src/agent/config/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Created-By: 1.8.0_272 (Oracle Corporation)
+Agent-Class: agent.JvmProbeAgent
+Can-Retransform-Classes: true
+Can-Redefine-Classes: true
+
--
2.33.0