1192 lines
43 KiB
Diff
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
|
|
|