Add support for XXL-JOB (#10421)
Co-authored-by: Lauri Tulmin <tulmin@gmail.com>
This commit is contained in:
parent
93bb1febea
commit
86c3263868
|
@ -145,6 +145,7 @@ These are the supported libraries and frameworks:
|
|||
| [Vert.x SQL Client](https://github.com/eclipse-vertx/vertx-sql-client/) | 4.0+ | N/A | [Database Client Spans] |
|
||||
| [Vert.x Web](https://vertx.io/docs/vertx-web/java/) | 3.0+ | N/A | Provides `http.route` [2] |
|
||||
| [Vibur DBCP](https://www.vibur.org/) | 11.0+ | [opentelemetry-vibur-dbcp-11.0](../instrumentation/vibur-dbcp-11.0/library) | [Database Pool Metrics] |
|
||||
| [XXL-JOB](https://www.xuxueli.com/xxl-job/en/) | 1.9.2+ | N/A | none |
|
||||
| [ZIO](https://zio.dev/) | 2.0+ | N/A | Context propagation |
|
||||
|
||||
**[1]** Standalone library instrumentation refers to instrumentation that can be used without the Java agent.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Settings for the XXL-JOB instrumentation
|
||||
|
||||
| System property | Type | Default | Description |
|
||||
|-------------------------------------------------------------|---------|---------|-----------------------------------------------------|
|
||||
| `otel.instrumentation.xxl-job.experimental-span-attributes` | Boolean | `false` | Enable the capture of experimental span attributes. |
|
|
@ -0,0 +1,36 @@
|
|||
plugins {
|
||||
id("otel.javaagent-instrumentation")
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group.set("com.xuxueli")
|
||||
module.set("xxl-job-core")
|
||||
versions.set("[1.9.2, 2.1.2)")
|
||||
assertInverse.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
library("com.xuxueli:xxl-job-core:1.9.2") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
implementation(project(":instrumentation:xxl-job:xxl-job-common:javaagent"))
|
||||
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-2.1.2:javaagent"))
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-2.3.0:javaagent"))
|
||||
|
||||
// It needs the javax.annotation-api in xxl-job-core 1.9.2.
|
||||
testImplementation("javax.annotation:javax.annotation-api:1.3.2")
|
||||
testImplementation(project(":instrumentation:xxl-job:xxl-job-common:testing"))
|
||||
latestDepTestLibrary("com.xuxueli:xxl-job-core:2.1.1") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
// required on jdk17
|
||||
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
|
||||
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
|
||||
jvmArgs("-Dotel.instrumentation.xxl-job.experimental-span-attributes=true")
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class GlueJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.GlueJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesArguments(String.class)),
|
||||
GlueJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("jobHandler") IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createGlueJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class ScriptJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.ScriptJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesArguments(1).and(takesArgument(0, String.class))),
|
||||
ScriptJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("glueType") GlueTypeEnum glueType,
|
||||
@Advice.FieldValue("jobId") int jobId,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createScriptJobRequest(glueType, jobId);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_GLUE_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_METHOD_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_SCRIPT_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class SimpleJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return hasSuperType(named("com.xxl.job.core.handler.IJobHandler"))
|
||||
.and(not(namedOneOf(XXL_GLUE_JOB_HANDLER, XXL_SCRIPT_JOB_HANDLER, XXL_METHOD_JOB_HANDLER)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesArguments(1).and(takesArgument(0, String.class))),
|
||||
SimpleJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.This IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createSimpleJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||
import static java.util.Arrays.asList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
public class XxlJobInstrumentationModule extends InstrumentationModule {
|
||||
|
||||
public XxlJobInstrumentationModule() {
|
||||
super("xxl-job", "xxl-job-1.9.2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||
// Class was added in 2.1.2
|
||||
return not(hasClassesNamed("com.xxl.job.core.handler.impl.MethodJobHandler"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return asList(
|
||||
new ScriptJobHandlerInstrumentation(),
|
||||
new SimpleJobHandlerInstrumentation(),
|
||||
new GlueJobHandlerInstrumentation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobHelper;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobInstrumenterFactory;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
|
||||
public final class XxlJobSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.xxl-job-1.9.2";
|
||||
private static final Instrumenter<XxlJobProcessRequest, Void> INSTRUMENTER =
|
||||
XxlJobInstrumenterFactory.create(INSTRUMENTATION_NAME);
|
||||
private static final XxlJobHelper HELPER =
|
||||
XxlJobHelper.create(
|
||||
INSTRUMENTER,
|
||||
object -> {
|
||||
if (object != null && (object instanceof ReturnT)) {
|
||||
ReturnT<?> result = (ReturnT<?>) object;
|
||||
return result.getCode() == ReturnT.FAIL_CODE;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
public static XxlJobHelper helper() {
|
||||
return HELPER;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"Unused", "ReturnValueIgnored"})
|
||||
private static void limitSupportedVersions() {
|
||||
// GLUE_POWERSHELL was added in 1.9.2. Using this constant here ensures that muzzle will disable
|
||||
// this instrumentation on earlier versions where this constant does not exist.
|
||||
GlueTypeEnum.GLUE_POWERSHELL.name();
|
||||
}
|
||||
|
||||
private XxlJobSingletons() {}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v1_9_2;
|
||||
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.DEFAULT_GLUE_UPDATE_TIME;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_GROOVY_SOURCE_OLD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_SHELL_SCRIPT;
|
||||
|
||||
import com.xxl.job.core.glue.GlueFactory;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.impl.GlueJobHandler;
|
||||
import com.xxl.job.core.handler.impl.ScriptJobHandler;
|
||||
import io.opentelemetry.instrumentation.xxljob.AbstractXxlJobTest;
|
||||
import io.opentelemetry.instrumentation.xxljob.CustomizedFailedHandler;
|
||||
import io.opentelemetry.instrumentation.xxljob.SimpleCustomizedHandler;
|
||||
|
||||
class XxlJobTest extends AbstractXxlJobTest {
|
||||
|
||||
private static final IJobHandler GROOVY_HANDLER;
|
||||
|
||||
static {
|
||||
try {
|
||||
GROOVY_HANDLER = GlueFactory.getInstance().loadNewInstance(GLUE_JOB_GROOVY_SOURCE_OLD);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final GlueJobHandler GLUE_JOB_HANDLER =
|
||||
new GlueJobHandler(GROOVY_HANDLER, DEFAULT_GLUE_UPDATE_TIME);
|
||||
|
||||
private static final ScriptJobHandler SCRIPT_JOB_HANDLER =
|
||||
new ScriptJobHandler(
|
||||
2, DEFAULT_GLUE_UPDATE_TIME, GLUE_JOB_SHELL_SCRIPT, GlueTypeEnum.GLUE_SHELL);
|
||||
|
||||
@Override
|
||||
protected String getPackageName() {
|
||||
return "io.opentelemetry.instrumentation.xxljob";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getGlueJobHandler() {
|
||||
return GLUE_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getScriptJobHandler() {
|
||||
return SCRIPT_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeHandler() {
|
||||
return new SimpleCustomizedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeFailedHandler() {
|
||||
return new CustomizedFailedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getMethodHandler() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
plugins {
|
||||
id("otel.javaagent-instrumentation")
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group.set("com.xuxueli")
|
||||
module.set("xxl-job-core")
|
||||
versions.set("[2.1.2,2.3.0)")
|
||||
assertInverse.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
library("com.xuxueli:xxl-job-core:2.1.2") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
implementation(project(":instrumentation:xxl-job:xxl-job-common:javaagent"))
|
||||
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-1.9.2:javaagent"))
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-2.3.0:javaagent"))
|
||||
|
||||
testImplementation(project(":instrumentation:xxl-job:xxl-job-common:testing"))
|
||||
latestDepTestLibrary("com.xuxueli:xxl-job-core:2.2.+") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
// required on jdk17
|
||||
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
|
||||
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
|
||||
jvmArgs("-Dotel.instrumentation.xxl-job.experimental-span-attributes=true")
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class GlueJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.GlueJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()),
|
||||
GlueJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("jobHandler") IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createGlueJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class MethodJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.MethodJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()),
|
||||
MethodJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("target") Object target,
|
||||
@Advice.FieldValue("method") Method method,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createMethodJobRequest(target, method);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class ScriptJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.ScriptJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()),
|
||||
ScriptJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("glueType") GlueTypeEnum glueType,
|
||||
@Advice.FieldValue("jobId") int jobId,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createScriptJobRequest(glueType, jobId);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_GLUE_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_METHOD_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_SCRIPT_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class SimpleJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return hasSuperType(named("com.xxl.job.core.handler.IJobHandler"))
|
||||
.and(not(namedOneOf(XXL_GLUE_JOB_HANDLER, XXL_SCRIPT_JOB_HANDLER, XXL_METHOD_JOB_HANDLER)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()),
|
||||
SimpleJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.This IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createSimpleJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Return(typing = Assigner.Typing.DYNAMIC) Object result,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(result, request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||
import static java.util.Arrays.asList;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
public class XxlJobInstrumentationModule extends InstrumentationModule {
|
||||
|
||||
public XxlJobInstrumentationModule() {
|
||||
super("xxl-job", "xxl-job-2.1.2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||
return hasClassesNamed("com.xxl.job.core.handler.impl.MethodJobHandler")
|
||||
// Class was added in 2.3.0
|
||||
.and(not(hasClassesNamed("com.xxl.job.core.context.XxlJobHelper")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return asList(
|
||||
new MethodJobHandlerInstrumentation(),
|
||||
new ScriptJobHandlerInstrumentation(),
|
||||
new SimpleJobHandlerInstrumentation(),
|
||||
new GlueJobHandlerInstrumentation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobHelper;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobInstrumenterFactory;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
|
||||
public final class XxlJobSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.xxl-job-2.1.2";
|
||||
private static final Instrumenter<XxlJobProcessRequest, Void> INSTRUMENTER =
|
||||
XxlJobInstrumenterFactory.create(INSTRUMENTATION_NAME);
|
||||
private static final XxlJobHelper HELPER =
|
||||
XxlJobHelper.create(
|
||||
INSTRUMENTER,
|
||||
object -> {
|
||||
if (object != null && (object instanceof ReturnT)) {
|
||||
ReturnT<?> result = (ReturnT<?>) object;
|
||||
return result.getCode() == ReturnT.FAIL_CODE;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
public static XxlJobHelper helper() {
|
||||
return HELPER;
|
||||
}
|
||||
|
||||
private XxlJobSingletons() {}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_1_2;
|
||||
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.DEFAULT_GLUE_UPDATE_TIME;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_GROOVY_SOURCE_OLD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_SHELL_SCRIPT;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_DESTROY_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_INIT_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_OBJECT;
|
||||
|
||||
import com.xxl.job.core.glue.GlueFactory;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.impl.GlueJobHandler;
|
||||
import com.xxl.job.core.handler.impl.MethodJobHandler;
|
||||
import com.xxl.job.core.handler.impl.ScriptJobHandler;
|
||||
import io.opentelemetry.instrumentation.xxljob.AbstractXxlJobTest;
|
||||
import io.opentelemetry.instrumentation.xxljob.CustomizedFailedHandler;
|
||||
import io.opentelemetry.instrumentation.xxljob.SimpleCustomizedHandler;
|
||||
|
||||
class XxlJobTest extends AbstractXxlJobTest {
|
||||
|
||||
private static final MethodJobHandler METHOD_JOB_HANDLER =
|
||||
new MethodJobHandler(
|
||||
METHOD_JOB_HANDLER_OBJECT,
|
||||
METHOD_JOB_HANDLER_METHOD,
|
||||
METHOD_JOB_HANDLER_INIT_METHOD,
|
||||
METHOD_JOB_HANDLER_DESTROY_METHOD);
|
||||
|
||||
private static final IJobHandler GROOVY_HANDLER;
|
||||
|
||||
static {
|
||||
try {
|
||||
GROOVY_HANDLER = GlueFactory.getInstance().loadNewInstance(GLUE_JOB_GROOVY_SOURCE_OLD);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final GlueJobHandler GLUE_JOB_HANDLER =
|
||||
new GlueJobHandler(GROOVY_HANDLER, DEFAULT_GLUE_UPDATE_TIME);
|
||||
|
||||
private static final ScriptJobHandler SCRIPT_JOB_HANDLER =
|
||||
new ScriptJobHandler(
|
||||
2, DEFAULT_GLUE_UPDATE_TIME, GLUE_JOB_SHELL_SCRIPT, GlueTypeEnum.GLUE_SHELL);
|
||||
|
||||
@Override
|
||||
protected String getPackageName() {
|
||||
return "io.opentelemetry.instrumentation.xxljob";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getGlueJobHandler() {
|
||||
return GLUE_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getScriptJobHandler() {
|
||||
return SCRIPT_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeHandler() {
|
||||
return new SimpleCustomizedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeFailedHandler() {
|
||||
return new CustomizedFailedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getMethodHandler() {
|
||||
return METHOD_JOB_HANDLER;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
plugins {
|
||||
id("otel.javaagent-instrumentation")
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group.set("com.xuxueli")
|
||||
module.set("xxl-job-core")
|
||||
versions.set("[2.3.0,)")
|
||||
assertInverse.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
library("com.xuxueli:xxl-job-core:2.3.0") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
implementation(project(":instrumentation:xxl-job:xxl-job-common:javaagent"))
|
||||
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-2.1.2:javaagent"))
|
||||
testInstrumentation(project(":instrumentation:xxl-job:xxl-job-2.3.0:javaagent"))
|
||||
|
||||
testImplementation(project(":instrumentation:xxl-job:xxl-job-common:testing"))
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
// required on jdk17
|
||||
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
|
||||
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
|
||||
jvmArgs("-Dotel.instrumentation.xxl-job.experimental-span-attributes=true")
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class GlueJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.GlueJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesNoArguments()),
|
||||
GlueJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("jobHandler") IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createGlueJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class MethodJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.MethodJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesNoArguments()),
|
||||
MethodJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("target") Object target,
|
||||
@Advice.FieldValue("method") Method method,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createMethodJobRequest(target, method);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class ScriptJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("com.xxl.job.core.handler.impl.ScriptJobHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesNoArguments()),
|
||||
ScriptJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.FieldValue("glueType") GlueTypeEnum glueType,
|
||||
@Advice.FieldValue("jobId") int jobId,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createScriptJobRequest(glueType, jobId);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_GLUE_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_METHOD_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobConstants.XXL_SCRIPT_JOB_HANDLER;
|
||||
import static io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0.XxlJobSingletons.helper;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
|
||||
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public class SimpleJobHandlerInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return hasSuperType(named("com.xxl.job.core.handler.IJobHandler"))
|
||||
.and(not(namedOneOf(XXL_GLUE_JOB_HANDLER, XXL_SCRIPT_JOB_HANDLER, XXL_METHOD_JOB_HANDLER)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
named("execute").and(isPublic()).and(takesNoArguments()),
|
||||
SimpleJobHandlerInstrumentation.class.getName() + "$ScheduleAdvice");
|
||||
}
|
||||
|
||||
public static class ScheduleAdvice {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void onSchedule(
|
||||
@Advice.This IJobHandler handler,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
request = XxlJobProcessRequest.createSimpleJobRequest(handler);
|
||||
context = helper().startSpan(parentContext, request);
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void stopSpan(
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelRequest") XxlJobProcessRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
helper().stopSpan(request, throwable, scope, context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
public class XxlJobInstrumentationModule extends InstrumentationModule {
|
||||
|
||||
public XxlJobInstrumentationModule() {
|
||||
super("xxl-job", "xxl-job-2.3.0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
|
||||
return hasClassesNamed(
|
||||
"com.xxl.job.core.handler.impl.MethodJobHandler", "com.xxl.job.core.context.XxlJobHelper");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return asList(
|
||||
new MethodJobHandlerInstrumentation(),
|
||||
new ScriptJobHandlerInstrumentation(),
|
||||
new SimpleJobHandlerInstrumentation(),
|
||||
new GlueJobHandlerInstrumentation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static com.xxl.job.core.context.XxlJobContext.HANDLE_COCE_SUCCESS;
|
||||
|
||||
import com.xxl.job.core.context.XxlJobContext;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobHelper;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobInstrumenterFactory;
|
||||
import io.opentelemetry.javaagent.instrumentation.xxljob.common.XxlJobProcessRequest;
|
||||
|
||||
public final class XxlJobSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.xxl-job-2.3.0";
|
||||
private static final Instrumenter<XxlJobProcessRequest, Void> INSTRUMENTER =
|
||||
XxlJobInstrumenterFactory.create(INSTRUMENTATION_NAME);
|
||||
private static final XxlJobHelper HELPER =
|
||||
XxlJobHelper.create(
|
||||
INSTRUMENTER,
|
||||
unused -> {
|
||||
// From 2.3.0, XxlJobContext is used to store the result of the job execution.
|
||||
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
|
||||
if (xxlJobContext != null) {
|
||||
int handleCode = xxlJobContext.getHandleCode();
|
||||
return handleCode != HANDLE_COCE_SUCCESS;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
public static XxlJobHelper helper() {
|
||||
return HELPER;
|
||||
}
|
||||
|
||||
private XxlJobSingletons() {}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import com.xxl.job.core.context.XxlJobHelper;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
class CustomizedFailedHandler extends IJobHandler {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
XxlJobHelper.handleFail();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import com.xxl.job.core.context.XxlJobHelper;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
class SimpleCustomizedHandler extends IJobHandler {
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
XxlJobHelper.handleSuccess();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0;
|
||||
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.DEFAULT_GLUE_UPDATE_TIME;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_GROOVY_SOURCE;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.GLUE_JOB_SHELL_SCRIPT;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_DESTROY_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_INIT_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_METHOD;
|
||||
import static io.opentelemetry.instrumentation.xxljob.XxlJobTestingConstants.METHOD_JOB_HANDLER_OBJECT;
|
||||
|
||||
import com.xxl.job.core.glue.GlueFactory;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.handler.impl.GlueJobHandler;
|
||||
import com.xxl.job.core.handler.impl.MethodJobHandler;
|
||||
import com.xxl.job.core.handler.impl.ScriptJobHandler;
|
||||
import io.opentelemetry.instrumentation.xxljob.AbstractXxlJobTest;
|
||||
|
||||
class XxlJobTest extends AbstractXxlJobTest {
|
||||
|
||||
private static final MethodJobHandler METHOD_JOB_HANDLER =
|
||||
new MethodJobHandler(
|
||||
METHOD_JOB_HANDLER_OBJECT,
|
||||
METHOD_JOB_HANDLER_METHOD,
|
||||
METHOD_JOB_HANDLER_INIT_METHOD,
|
||||
METHOD_JOB_HANDLER_DESTROY_METHOD);
|
||||
|
||||
private static final IJobHandler GROOVY_HANDLER;
|
||||
|
||||
static {
|
||||
try {
|
||||
GROOVY_HANDLER = GlueFactory.getInstance().loadNewInstance(GLUE_JOB_GROOVY_SOURCE);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final GlueJobHandler GLUE_JOB_HANDLER =
|
||||
new GlueJobHandler(GROOVY_HANDLER, DEFAULT_GLUE_UPDATE_TIME);
|
||||
|
||||
private static final ScriptJobHandler SCRIPT_JOB_HANDLER =
|
||||
new ScriptJobHandler(
|
||||
2, DEFAULT_GLUE_UPDATE_TIME, GLUE_JOB_SHELL_SCRIPT, GlueTypeEnum.GLUE_SHELL);
|
||||
|
||||
@Override
|
||||
protected String getPackageName() {
|
||||
return "io.opentelemetry.javaagent.instrumentation.xxljob.v2_3_0";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getGlueJobHandler() {
|
||||
return GLUE_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getScriptJobHandler() {
|
||||
return SCRIPT_JOB_HANDLER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeHandler() {
|
||||
return new SimpleCustomizedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getCustomizeFailedHandler() {
|
||||
return new CustomizedFailedHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IJobHandler getMethodHandler() {
|
||||
return METHOD_JOB_HANDLER;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
plugins {
|
||||
id("otel.javaagent-instrumentation")
|
||||
}
|
||||
dependencies {
|
||||
compileOnly("com.xuxueli:xxl-job-core:2.1.2")
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class XxlJobCodeAttributesGetter implements CodeAttributesGetter<XxlJobProcessRequest> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Class<?> getCodeClass(XxlJobProcessRequest xxlJobProcessRequest) {
|
||||
GlueTypeEnum glueType = xxlJobProcessRequest.getGlueType();
|
||||
if (!glueType.isScript()) {
|
||||
return xxlJobProcessRequest.getDeclaringClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getMethodName(XxlJobProcessRequest xxlJobProcessRequest) {
|
||||
GlueTypeEnum glueType = xxlJobProcessRequest.getGlueType();
|
||||
if (!glueType.isScript()) {
|
||||
return xxlJobProcessRequest.getMethodName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
public final class XxlJobConstants {
|
||||
|
||||
private XxlJobConstants() {}
|
||||
|
||||
public static final String XXL_GLUE_JOB_HANDLER = "com.xxl.job.core.handler.impl.GlueJobHandler";
|
||||
public static final String XXL_SCRIPT_JOB_HANDLER =
|
||||
"com.xxl.job.core.handler.impl.ScriptJobHandler";
|
||||
public static final String XXL_METHOD_JOB_HANDLER =
|
||||
"com.xxl.job.core.handler.impl.MethodJobHandler";
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class XxlJobExperimentalAttributeExtractor
|
||||
implements AttributesExtractor<XxlJobProcessRequest, Void> {
|
||||
|
||||
private static final AttributeKey<String> XXL_JOB_GLUE_TYPE =
|
||||
AttributeKey.stringKey("scheduling.xxl-job.glue.type");
|
||||
|
||||
private static final AttributeKey<Long> XXL_JOB_JOB_ID =
|
||||
AttributeKey.longKey("scheduling.xxl-job.job.id");
|
||||
|
||||
@Override
|
||||
public void onStart(
|
||||
AttributesBuilder attributes,
|
||||
Context parentContext,
|
||||
XxlJobProcessRequest xxlJobProcessRequest) {
|
||||
GlueTypeEnum glueType = xxlJobProcessRequest.getGlueType();
|
||||
attributes.put(XXL_JOB_GLUE_TYPE, glueType.getDesc());
|
||||
// store jobId in experimental attribute for script job.
|
||||
if (glueType.isScript()) {
|
||||
attributes.put(XXL_JOB_JOB_ID, xxlJobProcessRequest.getJobId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnd(
|
||||
AttributesBuilder attributes,
|
||||
Context context,
|
||||
XxlJobProcessRequest xxlJobProcessRequest,
|
||||
@Nullable Void unused,
|
||||
@Nullable Throwable error) {}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class XxlJobHelper {
|
||||
private final Instrumenter<XxlJobProcessRequest, Void> instrumenter;
|
||||
private final Predicate<Object> failedStatusPredicate;
|
||||
|
||||
private XxlJobHelper(
|
||||
Instrumenter<XxlJobProcessRequest, Void> instrumenter,
|
||||
Predicate<Object> failedStatusPredicate) {
|
||||
this.instrumenter = instrumenter;
|
||||
this.failedStatusPredicate = failedStatusPredicate;
|
||||
}
|
||||
|
||||
public static XxlJobHelper create(
|
||||
Instrumenter<XxlJobProcessRequest, Void> instrumenter,
|
||||
Predicate<Object> failedStatusPredicate) {
|
||||
return new XxlJobHelper(instrumenter, failedStatusPredicate);
|
||||
}
|
||||
|
||||
public Context startSpan(Context parentContext, XxlJobProcessRequest request) {
|
||||
if (!instrumenter.shouldStart(parentContext, request)) {
|
||||
return null;
|
||||
}
|
||||
return instrumenter.start(parentContext, request);
|
||||
}
|
||||
|
||||
public void stopSpan(
|
||||
Object result,
|
||||
XxlJobProcessRequest request,
|
||||
Throwable throwable,
|
||||
Scope scope,
|
||||
Context context) {
|
||||
if (scope == null) {
|
||||
return;
|
||||
}
|
||||
if (failedStatusPredicate.test(result)) {
|
||||
request.setFailed();
|
||||
}
|
||||
scope.close();
|
||||
instrumenter.end(context, request, null, throwable);
|
||||
}
|
||||
|
||||
public void stopSpan(
|
||||
XxlJobProcessRequest request, Throwable throwable, Scope scope, Context context) {
|
||||
stopSpan(null, request, throwable, scope, context);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.trace.StatusCode;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
|
||||
|
||||
public final class XxlJobInstrumenterFactory {
|
||||
|
||||
private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
|
||||
InstrumentationConfig.get()
|
||||
.getBoolean("otel.instrumentation.xxl-job.experimental-span-attributes", false);
|
||||
|
||||
public static Instrumenter<XxlJobProcessRequest, Void> create(String instrumentationName) {
|
||||
XxlJobCodeAttributesGetter codeAttributesGetter = new XxlJobCodeAttributesGetter();
|
||||
XxlJobSpanNameExtractor spanNameExtractor = new XxlJobSpanNameExtractor(codeAttributesGetter);
|
||||
InstrumenterBuilder<XxlJobProcessRequest, Void> builder =
|
||||
Instrumenter.<XxlJobProcessRequest, Void>builder(
|
||||
GlobalOpenTelemetry.get(), instrumentationName, spanNameExtractor)
|
||||
.addAttributesExtractor(CodeAttributesExtractor.create(codeAttributesGetter))
|
||||
.setSpanStatusExtractor(
|
||||
(spanStatusBuilder, xxlJobProcessRequest, response, error) -> {
|
||||
if (error != null || xxlJobProcessRequest.isFailed()) {
|
||||
spanStatusBuilder.setStatus(StatusCode.ERROR);
|
||||
}
|
||||
});
|
||||
if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) {
|
||||
builder.addAttributesExtractor(
|
||||
AttributesExtractor.constant(AttributeKey.stringKey("job.system"), "xxl-job"));
|
||||
builder.addAttributesExtractor(new XxlJobExperimentalAttributeExtractor());
|
||||
}
|
||||
return builder.buildInstrumenter();
|
||||
}
|
||||
|
||||
private XxlJobInstrumenterFactory() {}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class XxlJobProcessRequest {
|
||||
|
||||
private String methodName;
|
||||
private int jobId;
|
||||
private Class<?> declaringClass;
|
||||
private boolean failed;
|
||||
private final GlueTypeEnum glueType;
|
||||
|
||||
private XxlJobProcessRequest(GlueTypeEnum glueType) {
|
||||
this.glueType = glueType;
|
||||
}
|
||||
|
||||
public static XxlJobProcessRequest createRequestForMethod(
|
||||
GlueTypeEnum glueType, Class<?> declaringClass, String methodName) {
|
||||
XxlJobProcessRequest request = new XxlJobProcessRequest(glueType);
|
||||
request.declaringClass = declaringClass;
|
||||
request.methodName = methodName;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public static XxlJobProcessRequest createGlueJobRequest(IJobHandler handler) {
|
||||
return createRequestForMethod(GlueTypeEnum.GLUE_GROOVY, handler.getClass(), "execute");
|
||||
}
|
||||
|
||||
public static XxlJobProcessRequest createScriptJobRequest(GlueTypeEnum glueType, int jobId) {
|
||||
XxlJobProcessRequest request = new XxlJobProcessRequest(glueType);
|
||||
request.jobId = jobId;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public static XxlJobProcessRequest createSimpleJobRequest(IJobHandler handler) {
|
||||
return createRequestForMethod(GlueTypeEnum.BEAN, handler.getClass(), "execute");
|
||||
}
|
||||
|
||||
public static XxlJobProcessRequest createMethodJobRequest(Object target, Method method) {
|
||||
return createRequestForMethod(
|
||||
GlueTypeEnum.BEAN, target.getClass(), method != null ? method.getName() : null);
|
||||
}
|
||||
|
||||
public void setFailed() {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return failed;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public int getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public Class<?> getDeclaringClass() {
|
||||
return declaringClass;
|
||||
}
|
||||
|
||||
public GlueTypeEnum getGlueType() {
|
||||
return glueType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.xxljob.common;
|
||||
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
|
||||
class XxlJobSpanNameExtractor implements SpanNameExtractor<XxlJobProcessRequest> {
|
||||
private final SpanNameExtractor<XxlJobProcessRequest> codeSpanNameExtractor;
|
||||
|
||||
XxlJobSpanNameExtractor(CodeAttributesGetter<XxlJobProcessRequest> getter) {
|
||||
codeSpanNameExtractor = CodeSpanNameExtractor.create(getter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String extract(XxlJobProcessRequest request) {
|
||||
GlueTypeEnum glueType = request.getGlueType();
|
||||
if (glueType.isScript()) {
|
||||
// TODO: need to discuss a better span name for script job in the future.
|
||||
// for detail can refer to
|
||||
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10421#discussion_r1511532584
|
||||
return glueType.getDesc();
|
||||
}
|
||||
return codeSpanNameExtractor.extract(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":testing-common"))
|
||||
|
||||
compileOnly("com.xuxueli:xxl-job-core:2.1.2") {
|
||||
exclude("org.codehaus.groovy", "groovy")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.xxljob;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
import com.xxl.job.core.log.XxlJobFileAppender;
|
||||
import com.xxl.job.core.thread.JobThread;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.trace.SpanKind;
|
||||
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
|
||||
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
public abstract class AbstractXxlJobTest {
|
||||
|
||||
@RegisterExtension
|
||||
private static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() {
|
||||
XxlJobFileAppender.initLogPath("build/xxljob/log");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGlueJob() {
|
||||
JobThread jobThread = new JobThread(1, getGlueJobHandler());
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setExecutorTimeout(0);
|
||||
jobThread.pushTriggerQueue(triggerParam);
|
||||
jobThread.start();
|
||||
checkXxlJob(
|
||||
"CustomizedGroovyHandler.execute",
|
||||
StatusData.unset(),
|
||||
GlueTypeEnum.GLUE_GROOVY,
|
||||
"CustomizedGroovyHandler",
|
||||
"execute");
|
||||
jobThread.toStop("Test finish");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testScriptJob() {
|
||||
JobThread jobThread = new JobThread(2, getScriptJobHandler());
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setExecutorParams("");
|
||||
triggerParam.setExecutorTimeout(0);
|
||||
jobThread.pushTriggerQueue(triggerParam);
|
||||
jobThread.start();
|
||||
checkXxlJobWithoutCodeAttributes("GLUE(Shell)", StatusData.unset(), GlueTypeEnum.GLUE_SHELL, 2);
|
||||
jobThread.toStop("Test finish");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleJob() {
|
||||
JobThread jobThread = new JobThread(3, getCustomizeHandler());
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setExecutorTimeout(0);
|
||||
jobThread.pushTriggerQueue(triggerParam);
|
||||
jobThread.start();
|
||||
checkXxlJob(
|
||||
"SimpleCustomizedHandler.execute",
|
||||
StatusData.unset(),
|
||||
GlueTypeEnum.BEAN,
|
||||
getPackageName() + ".SimpleCustomizedHandler",
|
||||
"execute");
|
||||
jobThread.toStop("Test finish");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodJob() {
|
||||
// method handle is null if test is not supported by tested version of the library
|
||||
Assumptions.assumeTrue(getMethodHandler() != null);
|
||||
|
||||
JobThread jobThread = new JobThread(4, getMethodHandler());
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setExecutorTimeout(0);
|
||||
jobThread.pushTriggerQueue(triggerParam);
|
||||
jobThread.start();
|
||||
checkXxlJob(
|
||||
"ReflectObject.echo",
|
||||
StatusData.unset(),
|
||||
GlueTypeEnum.BEAN,
|
||||
"io.opentelemetry.instrumentation.xxljob.ReflectiveMethodsFactory$ReflectObject",
|
||||
"echo");
|
||||
jobThread.toStop("Test finish");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailedJob() {
|
||||
JobThread jobThread = new JobThread(5, getCustomizeFailedHandler());
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setExecutorTimeout(0);
|
||||
jobThread.pushTriggerQueue(triggerParam);
|
||||
jobThread.start();
|
||||
checkXxlJob(
|
||||
"CustomizedFailedHandler.execute",
|
||||
StatusData.error(),
|
||||
GlueTypeEnum.BEAN,
|
||||
getPackageName() + ".CustomizedFailedHandler",
|
||||
"execute");
|
||||
jobThread.toStop("Test finish");
|
||||
}
|
||||
|
||||
protected abstract IJobHandler getGlueJobHandler();
|
||||
|
||||
protected abstract IJobHandler getScriptJobHandler();
|
||||
|
||||
protected abstract IJobHandler getCustomizeHandler();
|
||||
|
||||
protected abstract IJobHandler getCustomizeFailedHandler();
|
||||
|
||||
protected abstract IJobHandler getMethodHandler();
|
||||
|
||||
protected abstract String getPackageName();
|
||||
|
||||
private static void checkXxlJob(
|
||||
String spanName, StatusData statusData, List<AttributeAssertion> assertions) {
|
||||
testing.waitAndAssertTraces(
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span ->
|
||||
span.hasKind(SpanKind.INTERNAL)
|
||||
.hasName(spanName)
|
||||
.hasStatus(statusData)
|
||||
.hasAttributesSatisfyingExactly(assertions)));
|
||||
}
|
||||
|
||||
private static void checkXxlJob(
|
||||
String spanName,
|
||||
StatusData statusData,
|
||||
GlueTypeEnum glueType,
|
||||
String codeNamespace,
|
||||
String codeFunction) {
|
||||
List<AttributeAssertion> attributeAssertions = new ArrayList<>();
|
||||
attributeAssertions.addAll(attributeAssertions(glueType));
|
||||
attributeAssertions.add(equalTo(AttributeKey.stringKey("code.namespace"), codeNamespace));
|
||||
attributeAssertions.add(equalTo(AttributeKey.stringKey("code.function"), codeFunction));
|
||||
|
||||
checkXxlJob(spanName, statusData, attributeAssertions);
|
||||
}
|
||||
|
||||
private static void checkXxlJobWithoutCodeAttributes(
|
||||
String spanName, StatusData statusData, GlueTypeEnum glueType, int jobId) {
|
||||
List<AttributeAssertion> attributeAssertions = new ArrayList<>();
|
||||
attributeAssertions.addAll(attributeAssertions(glueType));
|
||||
attributeAssertions.add(equalTo(AttributeKey.longKey("scheduling.xxl-job.job.id"), jobId));
|
||||
|
||||
checkXxlJob(spanName, statusData, attributeAssertions);
|
||||
}
|
||||
|
||||
private static List<AttributeAssertion> attributeAssertions(GlueTypeEnum glueType) {
|
||||
return asList(
|
||||
equalTo(AttributeKey.stringKey("job.system"), "xxl-job"),
|
||||
equalTo(AttributeKey.stringKey("scheduling.xxl-job.glue.type"), glueType.getDesc()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.xxljob;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
public class CustomizedFailedHandler extends IJobHandler {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> execute(String s) throws Exception {
|
||||
return FAIL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.xxljob;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
class ReflectiveMethodsFactory {
|
||||
|
||||
private ReflectiveMethodsFactory() {}
|
||||
|
||||
public static class ReflectObject {
|
||||
|
||||
private ReflectObject() {}
|
||||
|
||||
public void initMethod() {}
|
||||
|
||||
public void destroyMethod() {}
|
||||
|
||||
public ReturnT<String> echo(String param) {
|
||||
return new ReturnT<>("echo: " + param);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Object SINGLETON_OBJECT = new ReflectObject();
|
||||
|
||||
static Object getTarget() {
|
||||
return SINGLETON_OBJECT;
|
||||
}
|
||||
|
||||
static Method getMethod() {
|
||||
try {
|
||||
return SINGLETON_OBJECT.getClass().getMethod("echo", String.class);
|
||||
} catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Method getInitMethod() {
|
||||
try {
|
||||
return SINGLETON_OBJECT.getClass().getMethod("initMethod");
|
||||
} catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Method getDestroyMethod() {
|
||||
try {
|
||||
return SINGLETON_OBJECT.getClass().getMethod("destroyMethod");
|
||||
} catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.xxljob;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
public class SimpleCustomizedHandler extends IJobHandler {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> execute(String s) throws Exception {
|
||||
return new ReturnT<>("Hello World");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.xxljob;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class XxlJobTestingConstants {
|
||||
|
||||
private XxlJobTestingConstants() {}
|
||||
|
||||
public static final String GLUE_JOB_SHELL_SCRIPT = "echo 'hello'";
|
||||
|
||||
public static final long DEFAULT_GLUE_UPDATE_TIME = System.currentTimeMillis();
|
||||
|
||||
public static final Object METHOD_JOB_HANDLER_OBJECT = ReflectiveMethodsFactory.getTarget();
|
||||
|
||||
public static final Method METHOD_JOB_HANDLER_METHOD = ReflectiveMethodsFactory.getMethod();
|
||||
|
||||
public static final Method METHOD_JOB_HANDLER_INIT_METHOD =
|
||||
ReflectiveMethodsFactory.getInitMethod();
|
||||
|
||||
public static final Method METHOD_JOB_HANDLER_DESTROY_METHOD =
|
||||
ReflectiveMethodsFactory.getDestroyMethod();
|
||||
|
||||
public static final String GLUE_JOB_GROOVY_SOURCE_OLD =
|
||||
"import com.xxl.job.core.handler.IJobHandler\n"
|
||||
+ "import com.xxl.job.core.biz.model.ReturnT\n"
|
||||
+ "class CustomizedGroovyHandler extends IJobHandler {\n"
|
||||
+ " @Override\n"
|
||||
+ " public ReturnT<String> execute(String s) throws Exception {\n"
|
||||
+ " return new ReturnT<>(\"Hello World\")\n"
|
||||
+ " }\n"
|
||||
+ "}\n";
|
||||
|
||||
public static final String GLUE_JOB_GROOVY_SOURCE =
|
||||
"import com.xxl.job.core.handler.IJobHandler\n"
|
||||
+ "\n"
|
||||
+ "class CustomizedGroovyHandler extends IJobHandler {\n"
|
||||
+ " @Override\n"
|
||||
+ " void execute() throws Exception {\n"
|
||||
+ " }\n"
|
||||
+ "}\n";
|
||||
}
|
|
@ -576,6 +576,11 @@ include(":instrumentation:wicket-8.0:common-testing")
|
|||
include(":instrumentation:wicket-8.0:javaagent")
|
||||
include(":instrumentation:wicket-8.0:wicket8-testing")
|
||||
include(":instrumentation:wicket-8.0:wicket10-testing")
|
||||
include(":instrumentation:xxl-job:xxl-job-1.9.2:javaagent")
|
||||
include(":instrumentation:xxl-job:xxl-job-2.1.2:javaagent")
|
||||
include(":instrumentation:xxl-job:xxl-job-2.3.0:javaagent")
|
||||
include(":instrumentation:xxl-job:xxl-job-common:javaagent")
|
||||
include(":instrumentation:xxl-job:xxl-job-common:testing")
|
||||
include(":instrumentation:zio:zio-2.0:javaagent")
|
||||
|
||||
// benchmark
|
||||
|
|
Loading…
Reference in New Issue