You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/12/08 02:04:32 UTC
[skywalking] branch master updated: Change the operation name of
quartz-scheduler plugin (#5934)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new fbf49b2 Change the operation name of quartz-scheduler plugin (#5934)
fbf49b2 is described below
commit fbf49b2cc61a42305b0a44a3518e6058154f47f7
Author: hailin0 <ha...@foxmail.com>
AuthorDate: Tue Dec 8 10:04:14 2020 +0800
Change the operation name of quartz-scheduler plugin (#5934)
---
CHANGES.md | 1 +
....java => JobExecuteStateMethodInterceptor.java} | 51 +++++-----------------
.../quartz/JobRunShellMethodInterceptor.java | 6 ++-
.../JobRunShellInterceptorInstrumentation.java | 32 +++++++++++---
docs/en/setup/service-agent/java-agent/README.md | 2 +-
.../config/expectedData.yaml | 32 ++++++++++++--
.../testcase/quartzscheduler/job/ExceptionJob.java | 32 ++++++++++++++
.../testcase/quartzscheduler/job/QuartzConfig.java | 21 ++++++++-
8 files changed, 126 insertions(+), 51 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 228bf47..1d2ce2a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,7 @@ Release Notes.
* Chore: adapt `create_source_release.sh` to make it runnable on Linux.
#### Java Agent
+* The operation name of quartz-scheduler plugin, has been changed as the `quartz-scheduler/${className}` format.
* Fix jdk-http and okhttp-3.x plugin did not overwrite the old trace header.
#### OAP-Backend
diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobExecuteStateMethodInterceptor.java
similarity index 51%
copy from apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java
copy to apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobExecuteStateMethodInterceptor.java
index 465a7fe..e42c45a 100644
--- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java
+++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobExecuteStateMethodInterceptor.java
@@ -19,65 +19,38 @@
package org.apache.skywalking.apm.plugin.quartz;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag;
-import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-import org.quartz.JobDataMap;
-import org.quartz.JobDetail;
+import org.quartz.JobExecutionException;
+import org.quartz.core.JobRunShell;
import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Map;
/**
- * Intercept method of {@link org.quartz.core.JobRunShell#run()}.
- * record the quartz job local span.
+ * Intercept method of {@link JobRunShell#notifyJobListenersComplete(org.quartz.JobExecutionContext, org.quartz.JobExecutionException)}.
+ * record the quartz job execute exception.
*/
-public class JobRunShellMethodInterceptor implements InstanceMethodsAroundInterceptor {
-
- private static final AbstractTag JOB_GROUP = Tags.ofKey("jobGroup");
- private static final AbstractTag JOB_DATA_MAP = Tags.ofKey("jobDataMap");
-
- private static final String EMPTY_JOB_DATA_MAP_STRING = Collections.emptyMap().toString();
+public class JobExecuteStateMethodInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
- JobDetail jobDetail = (JobDetail) objInst.getSkyWalkingDynamicField();
-
- String jobName = jobDetail.getKey().getName();
- String jobGroup = jobDetail.getKey().getGroup();
- String operationName = ComponentsDefine.QUARTZ_SCHEDULER.getName() + "/" + jobName;
-
- AbstractSpan span = ContextManager.createLocalSpan(operationName);
- span.setComponent(ComponentsDefine.QUARTZ_SCHEDULER);
- Tags.LOGIC_ENDPOINT.set(span, Tags.VAL_LOCAL_SPAN_AS_LOGIC_ENDPOINT);
- span.tag(JOB_GROUP, jobGroup == null ? "" : jobGroup);
- span.tag(JOB_DATA_MAP, getJobDataMapString(jobDetail));
+ if (ContextManager.isActive()) {
+ JobExecutionException exception = (JobExecutionException) allArguments[1];
+ if (exception != null) {
+ AbstractSpan span = ContextManager.activeSpan();
+ span.log(exception);
+ }
+ }
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
- ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
- ContextManager.activeSpan().log(t);
- }
-
- private static String getJobDataMapString(JobDetail jobDetail) {
- JobDataMap jobDataMap = jobDetail.getJobDataMap();
- if (jobDataMap != null) {
- Map wrappedMap = jobDataMap.getWrappedMap();
- if (wrappedMap != null) {
- return wrappedMap.toString();
- }
- }
- return EMPTY_JOB_DATA_MAP_STRING;
}
}
diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java
index 465a7fe..213c93c 100644
--- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java
+++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/JobRunShellMethodInterceptor.java
@@ -40,6 +40,7 @@ import java.util.Map;
public class JobRunShellMethodInterceptor implements InstanceMethodsAroundInterceptor {
private static final AbstractTag JOB_GROUP = Tags.ofKey("jobGroup");
+ private static final AbstractTag JOB_NAME = Tags.ofKey("jobName");
private static final AbstractTag JOB_DATA_MAP = Tags.ofKey("jobDataMap");
private static final String EMPTY_JOB_DATA_MAP_STRING = Collections.emptyMap().toString();
@@ -48,14 +49,15 @@ public class JobRunShellMethodInterceptor implements InstanceMethodsAroundInterc
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
JobDetail jobDetail = (JobDetail) objInst.getSkyWalkingDynamicField();
- String jobName = jobDetail.getKey().getName();
String jobGroup = jobDetail.getKey().getGroup();
- String operationName = ComponentsDefine.QUARTZ_SCHEDULER.getName() + "/" + jobName;
+ String jobName = jobDetail.getKey().getName();
+ String operationName = ComponentsDefine.QUARTZ_SCHEDULER.getName() + "/" + jobDetail.getJobClass().getName();
AbstractSpan span = ContextManager.createLocalSpan(operationName);
span.setComponent(ComponentsDefine.QUARTZ_SCHEDULER);
Tags.LOGIC_ENDPOINT.set(span, Tags.VAL_LOCAL_SPAN_AS_LOGIC_ENDPOINT);
span.tag(JOB_GROUP, jobGroup == null ? "" : jobGroup);
+ span.tag(JOB_NAME, jobName == null ? "" : jobName);
span.tag(JOB_DATA_MAP, getJobDataMapString(jobDetail));
}
diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/define/JobRunShellInterceptorInstrumentation.java b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/define/JobRunShellInterceptorInstrumentation.java
index 6cfad92..6a098df 100644
--- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/define/JobRunShellInterceptorInstrumentation.java
+++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/quartz/define/JobRunShellInterceptorInstrumentation.java
@@ -26,22 +26,25 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInst
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+import static net.bytebuddy.matcher.ElementMatchers.isPublic;
+import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
- * Enhance {@link org.quartz.core.JobRunShell} instance and intercept {@link org.quartz.core.JobRunShell#run()} method,
- * this method is a unified entrance of execute schedule job.
+ * Enhance {@link org.quartz.core.JobRunShell} instance and intercept {@link org.quartz.core.JobRunShell#run()},{@link org.quartz.core.JobRunShell#notifyJobListenersComplete(org.quartz.JobExecutionContext, org.quartz.JobExecutionException)} methods,
+ * this class is a unified entrance of execute schedule job.
*
* @see org.apache.skywalking.apm.plugin.quartz.JobRunShellConstructorInterceptor
* @see org.apache.skywalking.apm.plugin.quartz.JobRunShellMethodInterceptor
+ * @see org.apache.skywalking.apm.plugin.quartz.JobExecuteStateMethodInterceptor
*/
public class JobRunShellInterceptorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
public static final String CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.quartz.JobRunShellConstructorInterceptor";
- public static final String METHOD_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.quartz.JobRunShellMethodInterceptor";
+ public static final String JOB_EXECUTE_METHOD_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.quartz.JobRunShellMethodInterceptor";
+ public static final String JOB_EXECUTE_STATE_METHOD_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.quartz.JobExecuteStateMethodInterceptor";
public static final String ENHANC_CLASS = "org.quartz.core.JobRunShell";
@Override
@@ -81,7 +84,26 @@ public class JobRunShellInterceptorInstrumentation extends ClassInstanceMethodsE
@Override
public String getMethodsInterceptor() {
- return METHOD_INTERCEPTOR_CLASS;
+ return JOB_EXECUTE_METHOD_INTERCEPTOR_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription> getMethodsMatcher() {
+ return named("notifyJobListenersComplete")
+ .and(isPrivate())
+ .and(takesArguments(2))
+ .and(takesArgument(1, named("org.quartz.JobExecutionException")));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return JOB_EXECUTE_STATE_METHOD_INTERCEPTOR_CLASS;
}
@Override
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index 144fee3..db886c5 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -192,7 +192,7 @@ The following logic endpoints are added automatically by plugins.
1. Spring's ScheduledMethodRunnable jobs are logic endpoints. The name format is `SpringScheduled`/`${className}`/`${methodName}`.
1. Apache ShardingSphere ElasticJob's jobs are logic endpoints. The name format is `ElasticJob`/`${jobName}`.
1. XXLJob's jobs are logic endpoints. The name formats include `xxl-job`/`MethodJob`/`${className}`.`${methodName}`, `xxl-job`/`ScriptJob`/`${GlueType}`/`id`/`${jobId}`, and `xxl-job`/`SimpleJob`/`${className}`.
-1. Quartz(optional plugin)'s jobs are logic endpoints. the name format is `quartz-scheduler`/`${jobName}`.
+1. Quartz(optional plugin)'s jobs are logic endpoints. the name format is `quartz-scheduler`/`${className}`.
User could use the SkyWalking's application toolkits to add the tag into the local span to label the span as a logic endpoint in the analysis stage.
The tag is, key=`x-le` and value = `{"logic-span":true}`.
diff --git a/test/plugin/scenarios/quartz-scheduler-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/config/expectedData.yaml
index ae649d7..7deb74c 100644
--- a/test/plugin/scenarios/quartz-scheduler-2.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/config/expectedData.yaml
@@ -35,7 +35,7 @@ segmentItems:
- {key: url, value: 'http://localhost:8080/quartz-scheduler-2.x-scenario/case/call'}
- {key: http.method, value: GET}
refs:
- - {parentEndpoint: quartz-scheduler/DemoJob, networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null}
+ - {parentEndpoint: quartz-scheduler/org.apache.skywalking.apm.testcase.quartzscheduler.job.DemoJob, networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null}
- segmentId: not null
spans:
- operationName: /quartz-scheduler-2.x-scenario/case/call
@@ -53,7 +53,7 @@ segmentItems:
tags:
- {key: http.method, value: GET}
- {key: url, value: 'http://localhost:8080/quartz-scheduler-2.x-scenario/case/call'}
- - operationName: quartz-scheduler/DemoJob
+ - operationName: quartz-scheduler/org.apache.skywalking.apm.testcase.quartzscheduler.job.DemoJob
operationId: 0
parentSpanId: -1
spanId: 0
@@ -68,4 +68,30 @@ segmentItems:
tags:
- {key: x-le, value: '{"logic-span":true}'}
- {key: jobGroup, value: 'DemoJobGroup'}
- - {key: jobDataMap, value: '{param1=test}'}
\ No newline at end of file
+ - {key: jobName, value: 'DemoJob'}
+ - {key: jobDataMap, value: '{param1=test}'}
+ - segmentId: not null
+ spans:
+ - operationName: quartz-scheduler/org.apache.skywalking.apm.testcase.quartzscheduler.job.ExceptionJob
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Unknown
+ startTime: not null
+ endTime: not null
+ componentId: 97
+ isError: true
+ spanType: Local
+ peer: ''
+ skipAnalysis: false
+ tags:
+ - {key: x-le, value: '{"logic-span":true}'}
+ - {key: jobGroup, value: 'ExceptionJobGroup'}
+ - {key: jobName, value: 'ExceptionJob'}
+ - {key: jobDataMap, value: '{param1=test}'}
+ logs:
+ - logEvent:
+ - {key: event, value: error}
+ - {key: error.kind, value: org.quartz.JobExecutionException}
+ - {key: message, value: not null}
+ - {key: stack, value: not null}
\ No newline at end of file
diff --git a/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/ExceptionJob.java b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/ExceptionJob.java
new file mode 100644
index 0000000..6cb29c3
--- /dev/null
+++ b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/ExceptionJob.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.quartzscheduler.job;
+
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+
+@Slf4j
+public class ExceptionJob implements Job {
+
+ @Override
+ public void execute(JobExecutionContext jobExecutionContext) {
+ throw new RuntimeException("execute job exception");
+ }
+}
diff --git a/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/QuartzConfig.java b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/QuartzConfig.java
index e4d2e48..4ca979e 100644
--- a/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/QuartzConfig.java
+++ b/test/plugin/scenarios/quartz-scheduler-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/quartzscheduler/job/QuartzConfig.java
@@ -38,12 +38,15 @@ public class QuartzConfig {
Map.Entry<JobDetail, Trigger> demoJobConfig = demoJobConfig();
scheduler.scheduleJob(demoJobConfig.getKey(), demoJobConfig.getValue());
+ Map.Entry<JobDetail, Trigger> exceptionJobConfig = exceptionJobConfig();
+ scheduler.scheduleJob(exceptionJobConfig.getKey(), exceptionJobConfig.getValue());
+
return scheduler;
}
private Map.Entry<JobDetail, Trigger> demoJobConfig() throws ParseException {
JobDetail demoJobDetail = JobBuilder.newJob(DemoJob.class)
- .withIdentity("DemoJob","DemoJobGroup")
+ .withIdentity("DemoJob", "DemoJobGroup")
.usingJobData("param1", "test")
.storeDurably()
.build();
@@ -56,4 +59,20 @@ public class QuartzConfig {
return new AbstractMap.SimpleEntry(demoJobDetail, demoJobTrigger);
}
+
+ private Map.Entry<JobDetail, Trigger> exceptionJobConfig() throws ParseException {
+ JobDetail exceptionJobDetail = JobBuilder.newJob(ExceptionJob.class)
+ .withIdentity("ExceptionJob", "ExceptionJobGroup")
+ .usingJobData("param1", "test")
+ .storeDurably()
+ .build();
+
+ Trigger exceptionJobTrigger = TriggerBuilder.newTrigger()
+ .forJob(exceptionJobDetail)
+ .startNow()
+ .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
+ .build();
+
+ return new AbstractMap.SimpleEntry(exceptionJobDetail, exceptionJobTrigger);
+ }
}
\ No newline at end of file