Contact Us 1-800-596-4880

Tracing Features in the Mule Java SDK

Tracing in the Mule Java SDK enables SDK-developed components to contribute telemetry data to the Mule runtime engine. Sources and operations can customize spans by defining span names, adding attributes, and setting the OpenTelemetry span kind.

Tracing also supports trace context propagation, which integrates the Mule Java SDK with distributed tracing systems.

Implementing Tracing Features

For operations, add DistributedTraceContextManager as an argument. The SDK implicitly injects this argument during each operation call.

For sources, obtain DistributedTraceContextManager from SourceCallbackContext.

DistributedTraceContextManager provides access to all the available tracing features for both sources and operations.

Example: Customize an Operation Span

This example shows a module definition:

@Extension(name = "Foo")
@Operations(FooOperations.class)
public class FooModule {

    @Parameter
    private String fooModuleParameter;

    public String getFooModuleParameter() {
        return fooModuleParameter;
    }
}

This operation customizes the span:

public class FooOperations {

    public String foo(@Config FooModule config, DistributedTraceContextManager distributedTraceContextManager) {

        // Implicit parameters must handle potential null values.
        if (distributedTraceContextManager != null) {
            // Override the current span name.
            distributedTraceContextManager.setCurrentSpanName("fooOperation");
            // Add an attribute to the span.
            distributedTraceContextManager.addCurrentSpanAttribute("attributeKey", "attributeValue");
        }

        return "OK";
    }
}

Example: Customize a Source Span

Sources push messages to flows by using SourceCallbackContext. This example is based on the HTTP Listener behavior:

public class HttpListener extends Source<InputStream, HttpRequestAttributes> {

    @Override
    public void onStart(SourceCallback<InputStream, HttpRequestAttributes> sourceCallback) throws MuleException {
        httpServer = serverProvider.connect();

        server.listen(path).onRequest(request -> {

            SourceCallbackContext context = sourceCallback.createContext();

            // Obtain the DistributedTraceContextManager from the SourceCallbackContext.
            DistributedTraceContextManager distributedTraceContextManager = sourceCallback.getDistributedTraceContextManager();
            // Override the current span name.
            distributedTraceContextManager.setCurrentSpanName("http:special-source");
            // Add an attribute to the span.
            distributedTraceContextManager.addCurrentSpanAttribute("attributeKey", "attributeValue");

            Result<InputStream, HttpRequestAttributes> result = requestToResult(request, context);
            sourceCallback.handle(result);
        });
    }
}

Trace Context Propagation

Sources and connectors play different roles in both Mule and distributed tracing.

In Mule, a source triggers a flow and creates the first span in its corresponding trace. Because of this role, the source must handle distributed trace context. If a trace already exists, the source must continue that trace instead of creating a new one.

Connectors propagate the current trace context to external systems outside Mule runtime. These systems can include databases, non-Mule APIs, and message queues.

The Mule runtime Java SDK supports the W3C trace context propagation standard. This standard defines a trace context that consists of a traceparent and a tracestate:

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: congo=t61rcWkgMzE

This representation enables trace context propagation across systems that support the standard.

Example: Trace Context Propagation in Sources and Connectors

This example uses the HTTP Listener and the HTTP Requester to demonstrate trace context propagation.

When the HTTP Listener receives W3C trace context headers in a request, use the DistributedTraceContextManager to indicate where to retrieve the W3C trace context:

public class HttpListener extends Source<InputStream, HttpRequestAttributes> {

    @Override
    public void onStart(SourceCallback<InputStream, HttpRequestAttributes> sourceCallback) throws MuleException {
        httpServer = serverProvider.connect();

        server.listen(path).onRequest(request -> {

            SourceCallbackContext context = sourceCallback.createContext();

            // Obtain the DistributedTraceContextManager from the SourceCallbackContext.
            DistributedTraceContextManager distributedTraceContextManager = sourceCallback.getDistributedTraceContextManager();
            // This defines the map where the W3C trace context key values are available for retrieval (an HTTP request in this case, so the HTTP headers are used).
            // The mule runtime will trace the flow execution as child spans of this provided trace context.
            distributedTraceContextManager.setRemoteTraceContextMap(request.getHeaders());

            Result<InputStream, HttpRequestAttributes> result = requestToResult(request, context);

            sourceCallback.handle(result);
        });
    }
}

The HTTP Requester retrieves the current W3C trace context during request operations by using getRemoteTraceContextMap(), and then propagates it:

public class HttpRequestOperations implements Initialisable, Disposable {

    public void request(HttpRequesterConfig config, DistributedTraceContextManager distributedTraceContextManager) {

        HttpRequestBuilder builder = HttpRequestBuilder.createRequestBuilder(config);

        // Implicit parameters must handle potential null values.
        if (distributedTraceContextManager != null) {
            // This obtains the current trace context as a map, propagating it to the connected system (an HTTP endpoint in this case, so HTTP headers are added).
            distributedTraceContextManager.getRemoteTraceContextMap().forEach(builder::addHeader);
        }
    }
}

Distributed Trace Context API

This table shows the distributed trace context manager methods:

Method

Parameter

Description

void setRemoteTraceContextMap(Map<String, String> contextMap)

contextMap

A Map<String, String> that contains the key-value pairs that store the information of the remote trace context.

void setCurrentSpanName(String name)

name

Sets the name of the current span.

Map<String, String> getRemoteTraceContextMap()

N/A

Returns the context map for the remote trace context.

void addCurrentSpanAttribute(String key, String value)

  • key

  • value

  • Key of the span attribute.

  • Value of the span attribute. Use span.kind.override as the key to override the span kind.

void addCurrentSpanAttributes(Map<String, String> attributes)

attributes

A Map<String, String> that contains the attributes to add to the current span. Use span.kind.override as the key to override the span kind.

setRemoteTraceContextMap() is intended for sources only. Mule silently ignores calls made from connector operations.