未验证 提交 fbf49b2c 编写于 作者: H hailin0 提交者: GitHub

Change the operation name of quartz-scheduler plugin (#5934)

上级 972145c2
......@@ -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
......
/*
* 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}'}
\ 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
/*
* 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);
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册