Change the operation name of quartz-scheduler plugin (#5934)
This commit is contained in:
parent
972145c208
commit
fbf49b2cc6
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.plugin.quartz;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManager;
|
||||
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.quartz.JobExecutionException;
|
||||
import org.quartz.core.JobRunShell;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Intercept method of {@link JobRunShell#notifyJobListenersComplete(org.quartz.JobExecutionContext, org.quartz.JobExecutionException)}.
|
||||
* record the quartz job execute exception.
|
||||
*/
|
||||
public class JobExecuteStateMethodInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
|
||||
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 {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}`.
|
||||
|
|
|
|||
|
|
@ -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}'}
|
||||
- {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}
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue