OpenTracing Compatibility
Status: Experimental.
Abstract
The OpenTelemetry project aims to provide backwards compatibility with the OpenTracing project in order to ease migration of instrumented codebases.
This functionality will be provided as a bridge layer implementing the OpenTracing API using the OpenTelemetry API. This layer MUST NOT rely on implementation specific details of any SDK.
More specifically, the intention is to allow OpenTracing instrumentation to be recorded using OpenTelemetry. This Shim Layer MUST NOT publicly expose any upstream OpenTelemetry API.
This functionality MUST be defined in its own OpenTracing Shim Layer, not in the OpenTracing nor the OpenTelemetry API or SDK.
The OpenTracing Shim and the OpenTelemetry API/SDK are expected to be consumed simultaneously in a running service, in order to ease migration from the former to the latter.
Create an OpenTracing Tracer Shim
This operation is used to create a new OpenTracing Tracer
:
This operation MUST accept the following parameters:
- An OpenTelemetry
Tracer
, used to createSpan
s. - OpenTelemetry
Propagator
s to be used to perform injection and extraction for the the OpenTracingTextMap
andHTTPHeaders
formats. If not specified, noPropagator
values will be stored in the Shim, and the global OpenTelemetryTextMap
propagator will be used for both OpenTracingTextMap
andHTTPHeaders
formats.
The API MUST return an OpenTracing Tracer
.
// Create a Tracer Shim relying on the global propagators.
createTracerShim(tracer);
// Create a Tracer Shim using:
// 1) TraceContext propagator for TextMap
// 2) Jaeger propagator for HttPHeaders.
createTracerShim(tracer, OTPropagatorsBuilder()
.setTextMap(W3CTraceContextPropagator.getInstance())
.setHttpHeaders(JaegerPropagator.getInstance())
.build());
See OpenTracing Propagation Formats.
Tracer Shim
Inject
Parameters:
- A
SpanContext
. - A
Format
descriptor. - A carrier.
Inject the underlying OpenTelemetry Span
and Bagagge
using either the explicitly
registered or the global OpenTelemetry Propagator
s, as configured at construction time.
TextMap
andHttpHeaders
formats MUST use their explicitly specifiedTextMapPropagator
, if any, or else use the globalTextMapPropagator
.
Errors MAY be raised if the specified Format
is not recognized, depending
on the specific OpenTracing Language API (e.g. Go and Python do, but Java may not).
Extract
Parameters:
- A
Format
descriptor. - A carrier.
Extract the underlying OpenTelemetry Span
and Bagagge
using either the explicitly
registered or the global OpenTelemetry Propagator
s, as configured at construction time.
TextMap
andHttpHeaders
formats MUST use their explicitly specifiedTextMapPropagator
, if any, or else use the globalTextMapPropagator
.
Returns a SpanContext
Shim with the underlying extracted OpenTelemetry
Span
and Baggage
. Errors MAY be raised if either the Format
is not recognized
or no value could be extracted, depending on the specific OpenTracing Language API
(e.g. Go and Python do, but Java may not).
OpenTelemetry Span and SpanContext Shim relationship
OpenTracing SpanContext
, just as OpenTelemetry SpanContext
, MUST be
immutable, but it MUST also store Baggage
. Hence, it MUST be replaced
every time baggage is updated through the OpenTracing
Span Set Baggage Item operation. Special handling
MUST be done by the Shim layer in order to retain these invariants.
Because of the previous requirement, a given OpenTelemetry Span
MUST be associated with ONE AND ONLY ONE SpanContext
Shim object at all times
for ALL execution units, in order to keep any linked Baggage
consistent
at all times. It MUST BE safe to get and set the associated SpanContext
Shim
object for a specified OpenTelemetry Span
from different execution units.
An example showing the need for these requirements is having an OpenTracing Span
have its Set Baggage Item operation called from two different
execution units (e.g. threads, coroutines), and afterwards have its
Context fetched in order to
iterate over its baggage values.
// Thread A: New SpanContextShim and Baggage values are created.
openTracingSpan.setBaggageItem("1", "a")
// Thread B: New SpanContextShim and Baggage values are created again.
openTracingSpan.setBaggageItem("2", "b")
// Thread C: Up-to-date SpanContextShim and Bagggage values are retrieved.
for (Map.Entry<String, String> entry : openTracingSpan.context().baggageItems()) {
...
}
This is a simple graphical representation of the mentioned objects:
Span Shim
+- OpenTelemetry Span
+- SpanContext Shim
+- OpenTelemetry SpanContext
+- OpenTelemetry Baggage
The OpenTelemetry Span
in the Span
Shim object is used to get and set
its currently associated SpanContext
Shim.
Managing this one-to-one relationship between an OpenTelemetry Span
and
a SpanContext
Shim object is an implementation detail. It can be implemented,
for example, with the help of a global synchronized dictionary, or with an
additional attribute in each OpenTelemetry Span
object for dynamic languages.
Span Shim
The OpenTracing Span
operations MUST be implemented using underlying OpenTelemetry Span
and Baggage
values with the help of a SpanContext
Shim object.
The Log
operations MUST be implemented using the OpenTelemetry
Span
’s Add Events
operations.
The Set Tag
operations MUST be implemented using the OpenTelemetry
Span
’s Set Attributes
operations.
Get Context
Returns the associated
SpanContext
Shim.
Get Baggage Item
Parameters:
- The baggage key, a string.
Returns a value for the specified key in the OpenTelemetry Baggage
of the
associated SpanContext
Shim or null if none exists.
This is accomplished by getting the
associated
SpanContext
Shim and do a lookup for the specified key in the OpenTelemetry
Baggage
instance.
String getBaggageItem(String key) {
getSpanContextShim().getBaggage().getEntryValue(key);
}
Set Baggage Item
Parameters:
- The baggage key, a string.
- The baggage value, a string.
Creates a new SpanContext
Shim with a new OpenTelemetry Baggage
containing
the specified Baggage
key/value pair. The resulting SpanContext
Shim is then
associated to the underlying
OpenTelemetry Span
.
void setBaggageItem(String key, String value) {
SpanContextShim spanContextShim = getSpanContextShim();
// Add value/key to the existing Baggage.
Baggage newBaggage = spanContextShim.getBaggage().toBuilder()
.put(key, value)
.build();
// Set a new SpanContext Shim object with the updated Baggage.
setSpanContextShim(spanContextShim.newWithBaggage(newBaggage));
}
Set Tag
Parameters:
- The tag key, a string.
- The tag value, which must be either a string, a boolean value, or a numeric type.
Calls Set Attribute
on the underlying OpenTelemetry Span
with the specified
key/value pair.
Certain values MUST be mapped from
OpenTracing Span Tags
to the respective OpenTelemetry Attribute
:
error
maps to StatusCode:true
maps toError
.false
maps toOk
.- no value being set maps to
Unset
.
If the type of the specified value is not supported by the OTel API, the value MUST be converted to a string.
Log
Parameters:
- A set of key/value pairs, where keys must be strings, and the values may have any type.
Calls Add Events
on the underlying OpenTelemetry Span
with the specified
key/value pair set.
The Add Event
’s name
parameter MUST be the value with the event
key in
the pair set, or else fallback to use the log
literal string.
If pair set contains a event=error
entry, the values MUST be mapped from
OpenTracing Log Fields
to an Event
with the conventions outlined in the
Exception semantic conventions document:
- If an entry with
error.object
key exists and the value is a language-specific error object, a call toRecordException(e)
is performed along the rest of the specified key/value pair set as additional event attributes. - Else, a call to
AddEvent
is performed withname
being set toexception
, along the specified key/value pair set as additional event attributes, including mapping of the following key/value pairs:error.kind
maps toexception.type
.message
maps toexception.message
.stack
maps toexception.stacktrace
.
If an explicit timestamp is specified, a conversion MUST be done to match the OpenTracing and OpenTelemetry units.
Finish
Calls End
on the underlying OpenTelemetry Span
.
If an explicit timestamp is specified, a conversion MUST be done to match the OpenTracing and OpenTelemetry units.
SpanContext Shim
SpanContext
Shim MUST be immutable and MUST contain the associated
SpanContext
and Baggage
values.
Get Baggage Items
Returns a dictionary, collection, or iterator (depending on the requirements of
the OpenTracing API for a specific language) backed by the associated OpenTelemetry
Baggage
values.
ScopeManager Shim
For OpenTracing languages implementing the ScopeManager
interface, its operations
MUST be implemented using the OpenTelemetry Context Propagation API in order
to get and set active Context
instances.
Activate a Span
Parameters:
- A
Span
.
Gets the associated
SpanContext
Shim for the specified Span
and puts its OpenTelemetry
Span
, Baggage
and Span
Shim objects in a new Context
,
which is then set as the currently active instance.
Scope activate(Span span) {
SpanContextShim spanContextShim = getSpanContextShim(span);
// Put the associated Span and Baggage in the used Context.
Context context = Context.current()
.withValue(spanContextShim.getSpan())
.withValue(spanContextShim.getBaggage())
.withValue((SpanShim)spanShim);
// Set context as the current instance.
return context.makeCurrent();
}
Get the active Span
Returns a Span
Shim wrapping the currently active OpenTelemetry Span
.
If there are related OpenTelemetry Span
and Span
Shim objects in the
current Context
, the Span
Shim MUST be returned. Else, a new Span
Shim
referencing the OpenTelemetry Span
MUST be created and returned.
The API MUST return null if no actual OpenTelemetry Span
is set.
Span active() {
io.opentelemetry.api.trace.Span span = Span.fromContext(Context.current());
SpanShim spanShim = SpanShim.fromContext(Context.current());
// Span was activated through the Shim layer, re-use it.
if (spanShim != null && spanShim.getSpan() == span) {
return spanShim;
}
// Span was NOT activated through the Shim layer.
new SpanShim(Span.current());
}