Use 'Tasklet' for spans that are produced by custom Spring Batch asklets
MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/ChunkExecutionTracer.java
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/ChunkExecutionTracer.java
@@ -14,6 +14,7 @@ import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import org.springframework.batch.core.scope.context.ChunkContext;
+import org.springframework.batch.core.step.builder.SimpleStepBuilder;
public class ChunkExecutionTracer extends BaseTracer {
private static final ChunkExecutionTracer TRACER = new ChunkExecutionTracer();
@@ -22,19 +23,22 @@ public class ChunkExecutionTracer extends BaseTracer {
return TRACER;
}
- public Context startSpan(ChunkContext chunkContext) {
+ public Context startSpan(ChunkContext chunkContext, Class<?> builderClass) {
Context parentContext = Context.current();
- SpanBuilder spanBuilder = spanBuilder(parentContext, spanName(chunkContext), INTERNAL);
+ SpanBuilder spanBuilder =
+ spanBuilder(parentContext, spanName(chunkContext, builderClass), INTERNAL);
if (shouldCreateRootSpanForChunk()) {
linkParentSpan(spanBuilder, parentContext);
}
return parentContext.with(spanBuilder.startSpan());
}
- private static String spanName(ChunkContext chunkContext) {
+ private static String spanName(ChunkContext chunkContext, Class<?> builderClass) {
String jobName = chunkContext.getStepContext().getJobName();
String stepName = chunkContext.getStepContext().getStepName();
- return "BatchJob " + jobName + "." + stepName + ".Chunk";
+ // only use "Chunk" for item processing steps, steps that use custom Tasklets will get "Tasklet"
+ String type = SimpleStepBuilder.class.isAssignableFrom(builderClass) ? "Chunk" : "Tasklet";
+ return "BatchJob " + jobName + "." + stepName + "." + type;
}
private static void linkParentSpan(SpanBuilder spanBuilder, Context parentContext) {

MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/StepBuilderInstrumentation.java
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/StepBuilderInstrumentation.java
@@ -46,7 +46,8 @@ public class StepBuilderInstrumentation implements TypeInstrumentation {
public static void onEnter(@Advice.This AbstractTaskletStepBuilder<?> stepBuilder) {
ContextStore<ChunkContext, ContextAndScope> chunkExecutionContextStore =
InstrumentationContext.get(ChunkContext.class, ContextAndScope.class);
- stepBuilder.listener(new TracingChunkExecutionListener(chunkExecutionContextStore));
+ stepBuilder.listener(
+ new TracingChunkExecutionListener(chunkExecutionContextStore, stepBuilder.getClass()));
}
}
}

MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/TracingChunkExecutionListener.java
instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/chunk/TracingChunkExecutionListener.java
@@ -17,15 +17,17 @@ import org.springframework.core.Ordered;
public final class TracingChunkExecutionListener implements ChunkListener, Ordered {
private final ContextStore<ChunkContext, ContextAndScope> executionContextStore;
+ private final Class<?> builderClass;
public TracingChunkExecutionListener(
- ContextStore<ChunkContext, ContextAndScope> executionContextStore) {
+ ContextStore<ChunkContext, ContextAndScope> executionContextStore, Class<?> builderClass) {
this.executionContextStore = executionContextStore;
+ this.builderClass = builderClass;
}
@Override
public void beforeChunk(ChunkContext chunkContext) {
- Context context = tracer().startSpan(chunkContext);
+ Context context = tracer().startSpan(chunkContext, builderClass);
// beforeJob & afterJob always execute on the same thread
Scope scope = context.makeCurrent();
executionContextStore.put(chunkContext, new ContextAndScope(context, scope));

MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/ChunkRootSpanTest.groovy
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/ChunkRootSpanTest.groovy
@@ -67,7 +67,7 @@ abstract class ChunkRootSpanTest extends AgentInstrumentationSpecification {
}
trace(4, 1) {
span(0) {
- name "BatchJob itemsAndTaskletJob.taskletStep.Chunk"
+ name "BatchJob itemsAndTaskletJob.taskletStep.Tasklet"
kind INTERNAL
hasLink taskletStepSpan
}

MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/ItemLevelSpanTest.groovy
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/ItemLevelSpanTest.groovy
@@ -121,7 +121,7 @@ abstract class ItemLevelSpanTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(36) {
- name "BatchJob itemsAndTaskletJob.taskletStep.Chunk"
+ name "BatchJob itemsAndTaskletJob.taskletStep.Tasklet"
kind INTERNAL
childOf span(35)
}
@@ -411,7 +411,7 @@ class JsrConfigItemLevelSpanTest extends AgentInstrumentationSpecification imple
childOf span(0)
}
span(36) {
- name "BatchJob itemsAndTaskletJob.taskletStep.Chunk"
+ name "BatchJob itemsAndTaskletJob.taskletStep.Tasklet"
kind INTERNAL
childOf span(35)
}

MODIFY
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/SpringBatchTest.groovy
instrumentation/spring/spring-batch-3.0/javaagent/src/test/groovy/SpringBatchTest.groovy
@@ -34,7 +34,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(2) {
- name "BatchJob taskletJob.step.Chunk"
+ name "BatchJob taskletJob.step.Tasklet"
kind INTERNAL
childOf span(1)
}
@@ -59,7 +59,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(2) {
- name "BatchJob taskletJob.step.Chunk"
+ name "BatchJob taskletJob.step.Tasklet"
kind INTERNAL
childOf span(1)
status ERROR
@@ -106,7 +106,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(6) {
- name "BatchJob itemsAndTaskletJob.taskletStep.Chunk"
+ name "BatchJob itemsAndTaskletJob.taskletStep.Tasklet"
kind INTERNAL
childOf span(5)
}
@@ -131,7 +131,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(2) {
- name "BatchJob flowJob.flowStep1.Chunk"
+ name "BatchJob flowJob.flowStep1.Tasklet"
kind INTERNAL
childOf span(1)
}
@@ -141,7 +141,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(4) {
- name "BatchJob flowJob.flowStep2.Chunk"
+ name "BatchJob flowJob.flowStep2.Tasklet"
kind INTERNAL
childOf span(3)
}
@@ -166,7 +166,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(2) {
- name ~/BatchJob splitJob\.splitFlowStep[12]\.Chunk/
+ name ~/BatchJob splitJob\.splitFlowStep[12]\.Tasklet/
kind INTERNAL
childOf span(1)
}
@@ -176,7 +176,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(4) {
- name ~/BatchJob splitJob\.splitFlowStep[12]\.Chunk/
+ name ~/BatchJob splitJob\.splitFlowStep[12]\.Tasklet/
kind INTERNAL
childOf span(3)
}
@@ -201,7 +201,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(2) {
- name "BatchJob decisionJob.decisionStepStart.Chunk"
+ name "BatchJob decisionJob.decisionStepStart.Tasklet"
kind INTERNAL
childOf span(1)
}
@@ -211,7 +211,7 @@ abstract class SpringBatchTest extends AgentInstrumentationSpecification {
childOf span(0)
}
span(4) {
- name "BatchJob decisionJob.decisionStepLeft.Chunk"
+ name "BatchJob decisionJob.decisionStepLeft.Tasklet"
kind INTERNAL
childOf span(3)
}

Use 'Tasklet' for spans that are produced by custom Spring Batch asklets (#3528)