For anyone looking at this, we solved the problem by using process instance variables and the OpenTelemetry Java API. In our code that kicks off the process instances, we did something like the following.
String operationId = Span.current().getSpanContext().getTraceId();
String spanId = Span.current().getSpanContext().getSpanId();
Map<String, Object> loggingVariables = new HashMap<String, Object>();
loggingVariables.put(LoggingVariables.OPERATION_ID, operationId);
loggingVariables.put(LoggingVariables.SPAN_ID, spanId);
ProcessInstantiationBuilder builder = ProcessEngines.getProcessEngine(PROCESS_ENGINE_NAME)
.getRuntimeService()
.setVariables(loggingVariables);
builder.execute();
For our delegates, we have an abstract base class named WorkflowJavaDelegate
that extends the Camunda JavaDelegate
interface. The WorkflowJavaDelegate
class’s implementation of the execute
method from the interface calls an abstract method named doExecute
, which each derived class defines. In that WorkflowJavaDelegate
class, we fetch the variables from the DelegateExecution
object, and use them to create OpenTelemetry spans.
@Override
public void execute(DelegateExecution execution) throws Exception {
Object operationIdObj = execution.getVariables().get(LoggingVariables.OPERATION_ID);
Object spanIdObj = execution.getVariables().get(LoggingVariables.SPAN_ID);
String operationId = (operationIdObj != null) ? operationIdObj.toString() : "";
String spanId = (spanIdObj != null) ? spanIdObj.toString() : "";
io.opentelemetry.context.Context context = io.opentelemetry.context.Context.root()
.with(
Span.wrap(
SpanContext.create(
operationId,
spanId,
TraceFlags.getSampled(),
TraceState.getDefault())));
try (Scope ignored = createLogContext(execution).makeCurrent()) {
doExecute(execution);
}
}