From 1cc99267287ca3a78331d84b81ac6495115b8b25 Mon Sep 17 00:00:00 2001 From: bimalc Date: Wed, 17 Mar 2021 19:19:47 -0700 Subject: [PATCH 1/2] Attach the agent to a running process, hotswap --- README.md | 39 +++++++++++++++++++++++++ pom.xml | 9 ++++++ src/main/java/net/test/AgentLoader.java | 26 +++++++++++++++++ src/main/java/net/test/TraceAgent.java | 5 ++++ 4 files changed, 79 insertions(+) create mode 100644 src/main/java/net/test/AgentLoader.java diff --git a/README.md b/README.md index dbc6ec3..28e63ee 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,31 @@ methodWithArgs TraceAgent (trace_retval): `public int net.test.TestClass2nd.methodWithArgs(java.lang.String,int) returns with 12 ``` +## Attaching Agent to running java process (hotswap) + +The agent can be attached to already running java process. + +To start trace on a running process one can use: + +``` +$ java -cp /lib/tools.jar:target/trace-agent-1.0-SNAPSHOT.jar net.test.AgentLoader target/trace-agent-1.0-SNAPSHOT.jar + +The above command attaches to the running java process and installs the actions. The instrumentaion messages will start showing in the processes logs/stdout as per the configuration. + +For example when attaching to a Spark executor using its pid: +... +21/03/17 13:30:52 INFO yarn.Client: Application report for application_1614936955492_0466 (state: ACCEPTED) +TraceAgent is initializing +TraceAgent tries to install actions: [{actionId='trace_args', classMatcher='REGEXP(org\.apache\.spark\.sql\.execution\.SparkStratgies.*)'}, ...] +TraceAgent installed actions successfully +... +21/03/17 14:18:33 INFO yarn.Client: Application report for application_1614936955492_0470 (state: RUNNING) +21/03/17 14:18:34 INFO util.Utils: Using initial executors = 0, max of spark.dynamicAllocation.initialExecutors, spark.dynamicAllocation.minExecutors and spark.executor.instances +TraceAgent (timing): `public final void org.apache.spark.SparkContext$$anonfun$23.apply(org.apache.spark.ExecutorAllocationManager)` took 22 ms +TraceAgent (timing): `public final void org.apache.spark.SparkContext$$anonfun$24.apply(org.apache.spark.ContextCleaner)` took 2 ms +.... + +``` ## The config format @@ -230,6 +255,20 @@ In this case all the rules are used from both the internal and external action f In distributed environment when external action file is used you should take care on each node the action file is really can be accessed using the path. Otherwise the error is logged but the application continues: "TraceAgent does not find the external action file: ". +#### Redirect output to log4j logger. + +By adding this argument we can instruct the agent to add the file to log4j logger instead of stdout. + +``` +java -javaagent:target/trace-agent-1.0-SNAPSHOT.jar="use_log4j:true" -jar ../testartifact/target/testartifact-1.0-SNAPSHOT.jar + +21/03/15 16:57:47 INFO TraceAgent: TraceAgent (trace_args_with_method_call): public java.lang.Object org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(org.apache.spark.sql.SparkSession,org.apache.spark.sql.execution.QueryExecution,scala.Function0) parameter instance with index 1 method call "getAllTokens" returns with +21/03/15 16:57:47 INFO TraceAgent: TraceAgent (trace_args): `public java.lang.String org.apache.spark.sql.execution.SQLExecution$.EXECUTION_ID_KEY() called with [] +``` + +The default is to write to the stdout. + + # The counter action This action can be used to count the number of of method calls. It has one parameter `count_frequency` which specifies after how many calls there will be a printout. diff --git a/pom.xml b/pom.xml index 7662074..092ada7 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,8 @@ 1.8 1.8 net.test.TraceAgent + 1.8 + 1.8.0 @@ -29,6 +31,13 @@ byte-buddy 1.10.10 + + com.sun + tools + ${sun.tools.version} + system + ${java.home}/../lib/tools.jar + diff --git a/src/main/java/net/test/AgentLoader.java b/src/main/java/net/test/AgentLoader.java new file mode 100644 index 0000000..a7e20c9 --- /dev/null +++ b/src/main/java/net/test/AgentLoader.java @@ -0,0 +1,26 @@ +package net.test; + +import com.sun.tools.attach.VirtualMachine; + +import java.io.File; +import java.util.Optional; + +/** Agent Loader to attach to a PID. */ +public class AgentLoader { + + public static void main(String[] args) { + File agentFile = new File(args[0]); + + System.out.println(agentFile.getAbsolutePath()); + try { + String pid = args[1]; + System.out.println("Attaching to target JVM with PID: " + pid); + VirtualMachine jvm = VirtualMachine.attach(pid); + jvm.loadAgent(agentFile.getAbsolutePath()); + jvm.detach(); + System.out.println("Succefully attached to target JVM and loaded Java agent"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/net/test/TraceAgent.java b/src/main/java/net/test/TraceAgent.java index d361366..008f0d2 100644 --- a/src/main/java/net/test/TraceAgent.java +++ b/src/main/java/net/test/TraceAgent.java @@ -79,6 +79,7 @@ private void installActions(List actions) { final Object interceptor = action.getActionInterceptor(traceAgentArgs); if (interceptor != null) { new AgentBuilder.Default() + .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager()) .type(action.getClassMatcher()) .transform( (builder, type, classLoader, module) -> @@ -117,4 +118,8 @@ public static void premain(String arguments, Instrumentation instrumentation) { TraceAgent traceAgent = new TraceAgent(traceAgentArgs, instrumentation); traceAgent.install(); } + + public static void agentmain(String arguments, Instrumentation instrumentation) { + premain(arguments, instrumentation); + } } From 53224e53283c84801acd94da4e99bfa64494ca00 Mon Sep 17 00:00:00 2001 From: bimalc Date: Wed, 17 Mar 2021 19:22:37 -0700 Subject: [PATCH 2/2] Fix in README --- README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/README.md b/README.md index 28e63ee..30a8631 100644 --- a/README.md +++ b/README.md @@ -255,19 +255,6 @@ In this case all the rules are used from both the internal and external action f In distributed environment when external action file is used you should take care on each node the action file is really can be accessed using the path. Otherwise the error is logged but the application continues: "TraceAgent does not find the external action file: ". -#### Redirect output to log4j logger. - -By adding this argument we can instruct the agent to add the file to log4j logger instead of stdout. - -``` -java -javaagent:target/trace-agent-1.0-SNAPSHOT.jar="use_log4j:true" -jar ../testartifact/target/testartifact-1.0-SNAPSHOT.jar - -21/03/15 16:57:47 INFO TraceAgent: TraceAgent (trace_args_with_method_call): public java.lang.Object org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(org.apache.spark.sql.SparkSession,org.apache.spark.sql.execution.QueryExecution,scala.Function0) parameter instance with index 1 method call "getAllTokens" returns with -21/03/15 16:57:47 INFO TraceAgent: TraceAgent (trace_args): `public java.lang.String org.apache.spark.sql.execution.SQLExecution$.EXECUTION_ID_KEY() called with [] -``` - -The default is to write to the stdout. - # The counter action