Skip to content

Commit 57301ca

Browse files
SylvainJugelaurit
andauthored
make spring indy-ready (#14183)
Co-authored-by: Lauri Tulmin <[email protected]>
1 parent f1fa49f commit 57301ca

File tree

49 files changed

+820
-613
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+820
-613
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0;
7+
8+
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.SpringBatchInstrumentationConfig.shouldTraceItems;
9+
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.getChunkContext;
10+
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.itemInstrumenter;
11+
12+
import io.opentelemetry.context.Context;
13+
import io.opentelemetry.context.Scope;
14+
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons;
15+
import javax.annotation.Nullable;
16+
import org.springframework.batch.core.scope.context.ChunkContext;
17+
18+
public final class AdviceScope {
19+
private final Context context;
20+
private final String item;
21+
private final Scope scope;
22+
23+
private AdviceScope(Context context, Scope scope, String item) {
24+
this.context = context;
25+
this.scope = scope;
26+
this.item = item;
27+
}
28+
29+
@Nullable
30+
public static AdviceScope enter(String itemOperationName) {
31+
Context parentContext = Context.current();
32+
ChunkContext chunkContext = getChunkContext(parentContext);
33+
if (chunkContext == null || !shouldTraceItems()) {
34+
return null;
35+
}
36+
37+
String item = ItemSingletons.itemName(chunkContext, itemOperationName);
38+
if (!itemInstrumenter().shouldStart(parentContext, item)) {
39+
return null;
40+
}
41+
Context context = itemInstrumenter().start(parentContext, item);
42+
return new AdviceScope(context, context.makeCurrent(), item);
43+
}
44+
45+
public void exit(@Nullable Throwable thrown) {
46+
scope.close();
47+
itemInstrumenter().end(context, item, null, thrown);
48+
}
49+
}

instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/SpringBatchInstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.google.auto.service.AutoService;
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1212
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1314
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.chunk.StepBuilderInstrumentation;
1415
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ChunkOrientedTaskletInstrumentation;
1516
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.JsrChunkProcessorInstrumentation;
@@ -25,7 +26,8 @@
2526
import net.bytebuddy.matcher.ElementMatcher;
2627

2728
@AutoService(InstrumentationModule.class)
28-
public class SpringBatchInstrumentationModule extends InstrumentationModule {
29+
public class SpringBatchInstrumentationModule extends InstrumentationModule
30+
implements ExperimentalInstrumentationModule {
2931
public SpringBatchInstrumentationModule() {
3032
super("spring-batch", "spring-batch-3.0");
3133
}
@@ -59,4 +61,9 @@ public boolean defaultEnabled(ConfigProperties config) {
5961
// TODO: replace this with an experimental flag
6062
return false;
6163
}
64+
65+
@Override
66+
public boolean isIndyReady() {
67+
return true;
68+
}
6269
}

instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/chunk/StepBuilderInstrumentation.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,11 @@
1010
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
1111
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
1212

13-
import io.opentelemetry.instrumentation.api.util.VirtualField;
1413
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1514
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
16-
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.ContextAndScope;
1715
import net.bytebuddy.asm.Advice;
1816
import net.bytebuddy.description.type.TypeDescription;
1917
import net.bytebuddy.matcher.ElementMatcher;
20-
import org.springframework.batch.core.scope.context.ChunkContext;
2118
import org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder;
2219

2320
public class StepBuilderInstrumentation implements TypeInstrumentation {
@@ -43,10 +40,7 @@ public static class BuildAdvice {
4340

4441
@Advice.OnMethodEnter(suppress = Throwable.class)
4542
public static void onEnter(@Advice.This AbstractTaskletStepBuilder<?> stepBuilder) {
46-
VirtualField<ChunkContext, ContextAndScope> chunkExecutionVirtualField =
47-
VirtualField.find(ChunkContext.class, ContextAndScope.class);
48-
stepBuilder.listener(
49-
new TracingChunkExecutionListener(chunkExecutionVirtualField, stepBuilder.getClass()));
43+
stepBuilder.listener(new TracingChunkExecutionListener(stepBuilder.getClass()));
5044
}
5145
}
5246
}

instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/chunk/TracingChunkExecutionListener.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
package io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.chunk;
77

8-
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
9-
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.rootContext;
108
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.SpringBatchInstrumentationConfig.shouldCreateRootSpanForChunk;
119
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.chunk.ChunkSingletons.chunkInstrumenter;
1210

@@ -20,19 +18,18 @@
2018
import org.springframework.core.Ordered;
2119

2220
public final class TracingChunkExecutionListener implements ChunkListener, Ordered {
23-
private final VirtualField<ChunkContext, ContextAndScope> executionVirtualField;
21+
private static final VirtualField<ChunkContext, ContextAndScope> CONTEXT_AND_SCOPE =
22+
VirtualField.find(ChunkContext.class, ContextAndScope.class);
2423
private final Class<?> builderClass;
2524
private ChunkContextAndBuilder chunkContextAndBuilder;
2625

27-
public TracingChunkExecutionListener(
28-
VirtualField<ChunkContext, ContextAndScope> executionVirtualField, Class<?> builderClass) {
29-
this.executionVirtualField = executionVirtualField;
26+
public TracingChunkExecutionListener(Class<?> builderClass) {
3027
this.builderClass = builderClass;
3128
}
3229

3330
@Override
3431
public void beforeChunk(ChunkContext chunkContext) {
35-
Context parentContext = shouldCreateRootSpanForChunk() ? rootContext() : currentContext();
32+
Context parentContext = shouldCreateRootSpanForChunk() ? Context.root() : Context.current();
3633
chunkContextAndBuilder = new ChunkContextAndBuilder(chunkContext, builderClass);
3734
if (!chunkInstrumenter().shouldStart(parentContext, chunkContextAndBuilder)) {
3835
return;
@@ -41,7 +38,7 @@ public void beforeChunk(ChunkContext chunkContext) {
4138
Context context = chunkInstrumenter().start(parentContext, chunkContextAndBuilder);
4239
// beforeJob & afterJob always execute on the same thread
4340
Scope scope = context.makeCurrent();
44-
executionVirtualField.set(chunkContext, new ContextAndScope(context, scope));
41+
CONTEXT_AND_SCOPE.set(chunkContext, new ContextAndScope(context, scope));
4542
}
4643

4744
@Override
@@ -57,12 +54,12 @@ public void afterChunkError(ChunkContext chunkContext) {
5754
}
5855

5956
private void end(ChunkContext chunkContext, @Nullable Throwable throwable) {
60-
ContextAndScope contextAndScope = executionVirtualField.get(chunkContext);
57+
ContextAndScope contextAndScope = CONTEXT_AND_SCOPE.get(chunkContext);
6158
if (contextAndScope == null) {
6259
return;
6360
}
6461

65-
executionVirtualField.set(chunkContext, null);
62+
CONTEXT_AND_SCOPE.set(chunkContext, null);
6663
contextAndScope.closeScope();
6764
chunkInstrumenter().end(contextAndScope.getContext(), chunkContextAndBuilder, null, throwable);
6865
}

instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/item/ChunkOrientedTaskletInstrumentation.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.opentelemetry.context.Scope;
1818
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
20+
import javax.annotation.Nullable;
2021
import net.bytebuddy.asm.Advice;
2122
import net.bytebuddy.description.type.TypeDescription;
2223
import net.bytebuddy.matcher.ElementMatcher;
@@ -44,17 +45,18 @@ public void transform(TypeTransformer transformer) {
4445
@SuppressWarnings("unused")
4546
public static class ExecuteAdvice {
4647

48+
@Nullable
4749
@Advice.OnMethodEnter(suppress = Throwable.class)
48-
public static void onEnter(
49-
@Advice.Argument(1) ChunkContext chunkContext, @Advice.Local("otelScope") Scope scope) {
50-
if (shouldTraceItems()) {
51-
Context context = startChunk(currentContext(), chunkContext);
52-
scope = context.makeCurrent();
50+
public static Scope onEnter(@Advice.Argument(1) ChunkContext chunkContext) {
51+
if (!shouldTraceItems()) {
52+
return null;
5353
}
54+
Context context = startChunk(currentContext(), chunkContext);
55+
return context.makeCurrent();
5456
}
5557

5658
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
57-
public static void onExit(@Advice.Local("otelScope") Scope scope) {
59+
public static void onExit(@Advice.Enter @Nullable Scope scope) {
5860
if (scope != null) {
5961
scope.close();
6062
}

instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/item/JsrChunkProcessorInstrumentation.java

Lines changed: 23 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,20 @@
55

66
package io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item;
77

8-
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
9-
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.SpringBatchInstrumentationConfig.shouldTraceItems;
108
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.ITEM_OPERATION_PROCESS;
119
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.ITEM_OPERATION_READ;
1210
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.ITEM_OPERATION_WRITE;
13-
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.getChunkContext;
14-
import static io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.item.ItemSingletons.itemInstrumenter;
1511
import static net.bytebuddy.matcher.ElementMatchers.isProtected;
1612
import static net.bytebuddy.matcher.ElementMatchers.named;
1713
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
1814

19-
import io.opentelemetry.context.Context;
20-
import io.opentelemetry.context.Scope;
2115
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2216
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
17+
import io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0.AdviceScope;
18+
import javax.annotation.Nullable;
2319
import net.bytebuddy.asm.Advice;
2420
import net.bytebuddy.description.type.TypeDescription;
2521
import net.bytebuddy.matcher.ElementMatcher;
26-
import org.springframework.batch.core.scope.context.ChunkContext;
2722

2823
public class JsrChunkProcessorInstrumentation implements TypeInstrumentation {
2924
@Override
@@ -47,114 +42,57 @@ public void transform(TypeTransformer transformer) {
4742
@SuppressWarnings("unused")
4843
public static class ProvideAdvice {
4944

45+
@Nullable
5046
@Advice.OnMethodEnter(suppress = Throwable.class)
51-
public static void onEnter(
52-
@Advice.Local("otelContext") Context context,
53-
@Advice.Local("otelScope") Scope scope,
54-
@Advice.Local("otelItem") String item) {
55-
Context parentContext = currentContext();
56-
ChunkContext chunkContext = getChunkContext(parentContext);
57-
if (chunkContext == null || !shouldTraceItems()) {
58-
return;
59-
}
60-
61-
item = ItemSingletons.itemName(chunkContext, ITEM_OPERATION_READ);
62-
if (!itemInstrumenter().shouldStart(parentContext, item)) {
63-
return;
64-
}
65-
66-
context = itemInstrumenter().start(parentContext, item);
67-
scope = context.makeCurrent();
47+
public static AdviceScope onEnter() {
48+
return AdviceScope.enter(ITEM_OPERATION_READ);
6849
}
6950

7051
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
7152
public static void onExit(
72-
@Advice.Thrown Throwable thrown,
73-
@Advice.Local("otelContext") Context context,
74-
@Advice.Local("otelScope") Scope scope,
75-
@Advice.Local("otelItem") String item) {
76-
if (scope == null) {
77-
return;
53+
@Advice.Thrown @Nullable Throwable thrown,
54+
@Advice.Enter @Nullable AdviceScope adviceScope) {
55+
if (adviceScope != null) {
56+
adviceScope.exit(thrown);
7857
}
79-
80-
scope.close();
81-
itemInstrumenter().end(context, item, null, thrown);
8258
}
8359
}
8460

8561
@SuppressWarnings("unused")
8662
public static class TransformAdvice {
8763

64+
@Nullable
8865
@Advice.OnMethodEnter(suppress = Throwable.class)
89-
public static void onEnter(
90-
@Advice.Local("otelContext") Context context,
91-
@Advice.Local("otelScope") Scope scope,
92-
@Advice.Local("otelItem") String item) {
93-
Context parentContext = currentContext();
94-
ChunkContext chunkContext = getChunkContext(parentContext);
95-
if (chunkContext == null || !shouldTraceItems()) {
96-
return;
97-
}
98-
99-
item = ItemSingletons.itemName(chunkContext, ITEM_OPERATION_PROCESS);
100-
if (!itemInstrumenter().shouldStart(parentContext, item)) {
101-
return;
102-
}
103-
104-
context = itemInstrumenter().start(parentContext, item);
105-
scope = context.makeCurrent();
66+
public static AdviceScope onEnter() {
67+
return AdviceScope.enter(ITEM_OPERATION_PROCESS);
10668
}
10769

10870
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
10971
public static void onExit(
110-
@Advice.Thrown Throwable thrown,
111-
@Advice.Local("otelContext") Context context,
112-
@Advice.Local("otelScope") Scope scope,
113-
@Advice.Local("otelItem") String item) {
114-
if (scope == null) {
115-
return;
72+
@Advice.Thrown @Nullable Throwable thrown,
73+
@Advice.Enter @Nullable AdviceScope adviceScope) {
74+
if (adviceScope != null) {
75+
adviceScope.exit(thrown);
11676
}
117-
118-
scope.close();
119-
itemInstrumenter().end(context, item, null, thrown);
12077
}
12178
}
12279

12380
@SuppressWarnings("unused")
12481
public static class PersistAdvice {
12582

83+
@Nullable
12684
@Advice.OnMethodEnter(suppress = Throwable.class)
127-
public static void onEnter(
128-
@Advice.Local("otelContext") Context context,
129-
@Advice.Local("otelScope") Scope scope,
130-
@Advice.Local("otelItem") String item) {
131-
Context parentContext = currentContext();
132-
ChunkContext chunkContext = getChunkContext(parentContext);
133-
if (chunkContext == null || !shouldTraceItems()) {
134-
return;
135-
}
136-
137-
item = ItemSingletons.itemName(chunkContext, ITEM_OPERATION_WRITE);
138-
if (!itemInstrumenter().shouldStart(parentContext, item)) {
139-
return;
140-
}
141-
142-
context = itemInstrumenter().start(parentContext, item);
143-
scope = context.makeCurrent();
85+
public static AdviceScope onEnter() {
86+
return AdviceScope.enter(ITEM_OPERATION_WRITE);
14487
}
14588

14689
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
14790
public static void onExit(
148-
@Advice.Thrown Throwable thrown,
149-
@Advice.Local("otelContext") Context context,
150-
@Advice.Local("otelScope") Scope scope,
151-
@Advice.Local("otelItem") String item) {
152-
if (scope == null) {
153-
return;
91+
@Advice.Thrown @Nullable Throwable thrown,
92+
@Advice.Enter @Nullable AdviceScope adviceScope) {
93+
if (adviceScope != null) {
94+
adviceScope.exit(thrown);
15495
}
155-
156-
scope.close();
157-
itemInstrumenter().end(context, item, null, thrown);
15896
}
15997
}
16098
}

0 commit comments

Comments
 (0)