Skip to content

Commit 8923112

Browse files
steveraolauritotelbot[bot]
authored
Add support for Apache Elasticjob (#14933)
Co-authored-by: Lauri Tulmin <[email protected]> Co-authored-by: otelbot <[email protected]>
1 parent 6360a2c commit 8923112

21 files changed

+1066
-0
lines changed

.fossa.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ targets:
7373
- type: gradle
7474
path: ./
7575
target: ':instrumentation:apache-dubbo-2.7:library-autoconfigure'
76+
- type: gradle
77+
path: ./
78+
target: ':instrumentation:apache-elasticjob-3.0:javaagent'
7679
- type: gradle
7780
path: ./
7881
target: ':instrumentation:apache-httpasyncclient-4.1:javaagent'

docs/supported-libraries.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ These are the supported libraries and frameworks:
2929
| [Apache CXF JAX-WS](https://cxf.apache.org/) | 3.0+ (not including 4.0+ yet) | N/A | Provides `http.route` [2], Controller Spans [3] |
3030
| [Apache DBCP](https://commons.apache.org/proper/commons-dbcp/) | 2.0+ | [opentelemetry-apache-dbcp-2.0](../instrumentation/apache-dbcp-2.0/library) | [Database Pool Metrics] |
3131
| [Apache Dubbo](https://github.com/apache/dubbo/) | 2.7+ | [opentelemetry-apache-dubbo-2.7](../instrumentation/apache-dubbo-2.7/library-autoconfigure) | [RPC Client Spans], [RPC Server Spans] |
32+
| [Apache ElasticJob](https://shardingsphere.apache.org/elasticjob/) | 3.0+ | N/A | none |
3233
| [Apache HttpAsyncClient](https://hc.apache.org/index.html) | 4.1+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
3334
| [Apache HttpClient](https://hc.apache.org/index.html) | 2.0+ | [opentelemetry-apache-httpclient-4.3](../instrumentation/apache-httpclient/apache-httpclient-4.3/library),<br>[opentelemetry-apache-httpclient-5.2](../instrumentation/apache-httpclient/apache-httpclient-5.2/library) | [HTTP Client Spans], [HTTP Client Metrics] |
3435
| [Apache ShenYu](https://shenyu.apache.org/) | 2.4+ | N/A | Provides `http.route` [2] |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Settings for the Apache ElasticJob instrumentation
2+
3+
| System property | Type | Default | Description |
4+
|-----------------------------------------------------------------------|---------|---------|-----------------------------------------------------|
5+
| `otel.instrumentation.apache-elasticjob.experimental-span-attributes` | Boolean | `false` | Enable the capture of experimental span attributes. |
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
plugins {
2+
id("otel.javaagent-instrumentation")
3+
}
4+
5+
muzzle {
6+
pass {
7+
group.set("org.apache.shardingsphere.elasticjob")
8+
module.set("elasticjob-lite-core")
9+
versions.set("[3.0.0,)")
10+
assertInverse.set(true)
11+
}
12+
}
13+
14+
dependencies {
15+
library("org.apache.shardingsphere.elasticjob:elasticjob-lite-core:3.0.0")
16+
17+
testImplementation("org.apache.curator:curator-test:5.1.0")
18+
}
19+
20+
tasks.withType<Test>().configureEach {
21+
jvmArgs("-Dotel.instrumentation.apache-elasticjob.experimental-span-attributes=true")
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import static io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0.ElasticJobSingletons.helper;
9+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
10+
import static net.bytebuddy.matcher.ElementMatchers.named;
11+
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
12+
13+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
14+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
15+
import javax.annotation.Nullable;
16+
import net.bytebuddy.asm.Advice;
17+
import net.bytebuddy.description.type.TypeDescription;
18+
import net.bytebuddy.matcher.ElementMatcher;
19+
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
20+
import org.apache.shardingsphere.elasticjob.dataflow.job.DataflowJob;
21+
22+
public class DataflowJobExecutorInstrumentation implements TypeInstrumentation {
23+
24+
@Override
25+
public ElementMatcher<TypeDescription> typeMatcher() {
26+
return named("org.apache.shardingsphere.elasticjob.dataflow.executor.DataflowJobExecutor");
27+
}
28+
29+
@Override
30+
public void transform(TypeTransformer transformer) {
31+
transformer.applyAdviceToMethod(
32+
isMethod()
33+
.and(named("process"))
34+
.and(
35+
takesArgument(
36+
0, named("org.apache.shardingsphere.elasticjob.dataflow.job.DataflowJob")))
37+
.and(
38+
takesArgument(
39+
3, named("org.apache.shardingsphere.elasticjob.api.ShardingContext"))),
40+
DataflowJobExecutorInstrumentation.class.getName() + "$ProcessAdvice");
41+
}
42+
43+
@SuppressWarnings("unused")
44+
public static class ProcessAdvice {
45+
46+
@Nullable
47+
@Advice.OnMethodEnter(suppress = Throwable.class)
48+
public static ElasticJobHelper.ElasticJobScope onEnter(
49+
@Advice.Argument(0) DataflowJob<?> elasticJob,
50+
@Advice.Argument(3) ShardingContext shardingContext) {
51+
52+
ElasticJobProcessRequest request =
53+
ElasticJobProcessRequest.create(
54+
shardingContext, ElasticJobType.DATAFLOW, elasticJob.getClass(), "processData");
55+
56+
return helper().startSpan(request);
57+
}
58+
59+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
60+
public static void onExit(
61+
@Advice.Enter ElasticJobHelper.ElasticJobScope scope, @Advice.Thrown Throwable throwable) {
62+
helper().endSpan(scope, throwable);
63+
}
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
9+
import javax.annotation.Nullable;
10+
11+
class ElasticJobCodeAttributesGetter implements CodeAttributesGetter<ElasticJobProcessRequest> {
12+
@Nullable
13+
@Override
14+
public Class<?> getCodeClass(ElasticJobProcessRequest request) {
15+
return request.getUserJobClass();
16+
}
17+
18+
@Nullable
19+
@Override
20+
public String getMethodName(ElasticJobProcessRequest request) {
21+
return request.getUserMethodName();
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import static io.opentelemetry.api.common.AttributeKey.longKey;
9+
import static io.opentelemetry.api.common.AttributeKey.stringKey;
10+
11+
import io.opentelemetry.api.common.AttributeKey;
12+
import io.opentelemetry.api.common.AttributesBuilder;
13+
import io.opentelemetry.context.Context;
14+
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
15+
import javax.annotation.Nullable;
16+
17+
class ElasticJobExperimentalAttributeExtractor
18+
implements AttributesExtractor<ElasticJobProcessRequest, Void> {
19+
20+
private static final AttributeKey<String> ELASTICJOB_JOB_NAME =
21+
stringKey("scheduling.apache-elasticjob.job.name");
22+
private static final AttributeKey<String> ELASTICJOB_TASK_ID =
23+
stringKey("scheduling.apache-elasticjob.task.id");
24+
private static final AttributeKey<Long> ELASTICJOB_SHARDING_ITEM_INDEX =
25+
longKey("scheduling.apache-elasticjob.sharding.item.index");
26+
private static final AttributeKey<Long> ELASTICJOB_SHARDING_TOTAL_COUNT =
27+
longKey("scheduling.apache-elasticjob.sharding.total.count");
28+
private static final AttributeKey<String> ELASTICJOB_SHARDING_ITEM_PARAMETER =
29+
stringKey("scheduling.apache-elasticjob.sharding.item.parameter");
30+
private static final AttributeKey<String> ELASTICJOB_JOB_TYPE =
31+
stringKey("scheduling.apache-elasticjob.job.type");
32+
33+
@Override
34+
public void onStart(
35+
AttributesBuilder attributes,
36+
Context parentContext,
37+
ElasticJobProcessRequest elasticJobProcessRequest) {
38+
attributes.put(ELASTICJOB_JOB_NAME, elasticJobProcessRequest.getJobName());
39+
attributes.put(ELASTICJOB_TASK_ID, elasticJobProcessRequest.getTaskId());
40+
attributes.put(ELASTICJOB_SHARDING_ITEM_INDEX, elasticJobProcessRequest.getShardingItemIndex());
41+
attributes.put(
42+
ELASTICJOB_SHARDING_TOTAL_COUNT, elasticJobProcessRequest.getShardingTotalCount());
43+
attributes.put(ELASTICJOB_JOB_TYPE, elasticJobProcessRequest.getJobType().name());
44+
String shardingItemParameter = elasticJobProcessRequest.getShardingItemParameter();
45+
if (shardingItemParameter != null) {
46+
attributes.put(ELASTICJOB_SHARDING_ITEM_PARAMETER, shardingItemParameter);
47+
}
48+
}
49+
50+
@Override
51+
public void onEnd(
52+
AttributesBuilder attributes,
53+
Context context,
54+
ElasticJobProcessRequest elasticJobProcessRequest,
55+
@Nullable Void unused,
56+
@Nullable Throwable error) {}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import io.opentelemetry.context.Context;
9+
import io.opentelemetry.context.Scope;
10+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
11+
import javax.annotation.Nullable;
12+
13+
public final class ElasticJobHelper {
14+
private final Instrumenter<ElasticJobProcessRequest, Void> instrumenter;
15+
16+
private ElasticJobHelper(Instrumenter<ElasticJobProcessRequest, Void> instrumenter) {
17+
this.instrumenter = instrumenter;
18+
}
19+
20+
public static ElasticJobHelper create(Instrumenter<ElasticJobProcessRequest, Void> instrumenter) {
21+
return new ElasticJobHelper(instrumenter);
22+
}
23+
24+
@Nullable
25+
public ElasticJobScope startSpan(ElasticJobProcessRequest request) {
26+
Context parentContext = Context.current();
27+
if (!this.instrumenter.shouldStart(parentContext, request)) {
28+
return null;
29+
}
30+
Context context = this.instrumenter.start(parentContext, request);
31+
return new ElasticJobScope(request, context, context.makeCurrent());
32+
}
33+
34+
public void endSpan(@Nullable ElasticJobScope scope, @Nullable Throwable throwable) {
35+
if (scope != null) {
36+
scope.scope.close();
37+
this.instrumenter.end(scope.context, scope.request, null, throwable);
38+
}
39+
}
40+
41+
public static class ElasticJobScope {
42+
private final ElasticJobProcessRequest request;
43+
private final Context context;
44+
private final Scope scope;
45+
46+
private ElasticJobScope(ElasticJobProcessRequest request, Context context, Scope scope) {
47+
this.request = request;
48+
this.context = context;
49+
this.scope = scope;
50+
}
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import static java.util.Arrays.asList;
9+
10+
import com.google.auto.service.AutoService;
11+
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
12+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
14+
import java.util.List;
15+
16+
@AutoService(InstrumentationModule.class)
17+
public class ElasticJobInstrumentationModule extends InstrumentationModule
18+
implements ExperimentalInstrumentationModule {
19+
20+
public ElasticJobInstrumentationModule() {
21+
super("apache-elasticjob", "apache-elasticjob-3.0");
22+
}
23+
24+
@Override
25+
public List<TypeInstrumentation> typeInstrumentations() {
26+
return asList(
27+
new SimpleJobExecutorInstrumentation(),
28+
new DataflowJobExecutorInstrumentation(),
29+
new ScriptJobExecutorInstrumentation(),
30+
new HttpJobExecutorInstrumentation());
31+
}
32+
33+
@Override
34+
public boolean isIndyReady() {
35+
return true;
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.apacheelasticjob.v3_0;
7+
8+
import org.apache.shardingsphere.elasticjob.api.ShardingContext;
9+
10+
public final class ElasticJobProcessRequest {
11+
private final String jobName;
12+
private final String taskId;
13+
private final int shardingItemIndex;
14+
private final int shardingTotalCount;
15+
private final String shardingItemParameter;
16+
private final ElasticJobType jobType;
17+
private final Class<?> userJobClass;
18+
private final String userMethodName;
19+
20+
private ElasticJobProcessRequest(
21+
ShardingContext shardingContext,
22+
ElasticJobType jobType,
23+
Class<?> userJobClass,
24+
String userMethodNam) {
25+
this.jobName = shardingContext.getJobName();
26+
this.taskId = shardingContext.getTaskId();
27+
this.shardingItemIndex = shardingContext.getShardingItem();
28+
this.shardingTotalCount = shardingContext.getShardingTotalCount();
29+
this.shardingItemParameter = emptyToNull(shardingContext.getShardingParameter());
30+
this.jobType = jobType;
31+
this.userJobClass = userJobClass;
32+
this.userMethodName = userMethodNam;
33+
}
34+
35+
private static String emptyToNull(String string) {
36+
return string == null || string.isEmpty() ? null : string;
37+
}
38+
39+
public static ElasticJobProcessRequest create(
40+
ShardingContext shardingContext,
41+
ElasticJobType jobType,
42+
Class<?> userJobClass,
43+
String userMethodName) {
44+
return new ElasticJobProcessRequest(shardingContext, jobType, userJobClass, userMethodName);
45+
}
46+
47+
public String getJobName() {
48+
return this.jobName;
49+
}
50+
51+
public String getTaskId() {
52+
return this.taskId;
53+
}
54+
55+
public int getShardingItemIndex() {
56+
return this.shardingItemIndex;
57+
}
58+
59+
public int getShardingTotalCount() {
60+
return this.shardingTotalCount;
61+
}
62+
63+
public String getShardingItemParameter() {
64+
return this.shardingItemParameter;
65+
}
66+
67+
public ElasticJobType getJobType() {
68+
return this.jobType;
69+
}
70+
71+
public Class<?> getUserJobClass() {
72+
return this.userJobClass;
73+
}
74+
75+
public String getUserMethodName() {
76+
return this.userMethodName;
77+
}
78+
}

0 commit comments

Comments
 (0)