OpenTelemetry
Since Camel 3.5
The OpenTelemetry component is used for tracing and timing incoming and outgoing Camel messages using OpenTelemetry.
Events (spans) are captured for incoming and outgoing messages being sent to/from Camel.
Configuration
The configuration properties for the OpenTelemetry tracer are:
Option | Default | Description |
---|---|---|
|
camel |
A name uniquely identifying the instrumentation scope, such as the instrumentation library, package, or fully qualified class name. Must not be null. |
|
Sets exclude pattern(s) that will disable tracing for Camel messages that matches the pattern. The content is a Set<String> where the key is a pattern. The pattern uses the rules from Intercept. |
|
|
|
Sets whether the header keys need to be encoded (connector specific) or not. The value is a boolean. Dashes are required for instances to be encoded for JMS property keys. |
|
|
Setting this to true will create new OpenTelemetry Spans for each Camel Processors. Use the excludePattern property to filter out Processors |
Using Camel OpenTelemetry
Include the camel-opentelemetry
component in your POM, along with any specific dependencies associated with the
chosen OpenTelemetry compliant Tracer.
To explicitly configure OpenTelemetry support, instantiate the OpenTelemetryTracer
and initialize the camel
context. You can optionally specify a Tracer
, or alternatively it can be implicitly discovered using the
Registry
OpenTelemetryTracer otelTracer = new OpenTelemetryTracer();
// By default, it uses the DefaultTracer, but you can override it with a specific OpenTelemetry Tracer implementation.
otelTracer.setTracer(...);
// And then initialize the context
otelTracer.init(camelContext);
You would still need OpenTelemetry to instrument your code, which can be done via a Java agent. |
Using with standalone Camel
If you use camel-main
as standalone Camel, then you can enable and use OpenTelemetry without Java code.
Add camel-opentelemetry
component in your POM, and configure in application.properties
:
camel.opentelemetry.enabled = true
# you can configure the other options
# camel.opentelemetry.instrumentationName = myApp
The configuration alone provide a NOOP default implementation, which is only useful for testing purposes as it will always create the same trace and span. In order to leverage an easy configuration you can also use the OpenTelemetry zero code SDK autoconfiguration. With this approach you will need to add the io.opentelemetry:opentelemetry-sdk-extension-autoconfigure
to your Camel main application, and start the application with the following system properties:
$ java -Dotel.java.global-autoconfigure.enabled=true -Dotel.metrics.exporter=none -Dotel.traces.exporter=none -Dotel.logs.exporter=none -jar my-app.jar
you will need to check the SDK manual to configure according to your specific needs. |
MDC Logging
You can add Mapped Diagnostic Context tracing information (ie, trace_id
and span_id
) adding the specific Opentelemetry Logger MDC auto instrumentation. The configuration depends on the logging framework you’re using.
Customizing OpenTelemetry spans
In rare circumstances, it may be desirable to apply advanced customizations to the OpenTelemetry Span generated by the Camel OpenTelemetryTracer
.
To do this, you can provide a custom implementation of SpanCustomizer
and either set it explicitly on the OpenTelemetryTracer
,
or bind it to the Camel registry, where it will be automatically resolved by the tracer upon initialization.
Note that care should be taken when configuring parents & links to avoid breaking the relationship between spans & traces.
public class MySpanCustomizer implements SpanCustomizer {
@Override
public void customize(SpanBuilder spanBuilder, String operationName, Exchange exchange) {
spanBuilder.setAttribute("foo", "bar");
spanBuilder.setParent(myCustomParentContext);
spanBuilder.addLink(linkedSpanContext);
// other customizations...
}
// By default, all spans will have customizations applied. You can restrict this by overriding isEnabled
@Override
public boolean isEnabled(String operationName, Exchange exchange) {
String header = exchange.getMessage().getHeader("foo", String.class);
return operationName.equals("my-message-queue") && header.equals("bar");
}
}