Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenTracing compatibility section. #1101

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1c9bc9d
Initial OpenTracing compatibility section.
carlosalberto Aug 10, 2020
bcdfb00
Fixes.
carlosalberto Aug 10, 2020
3195643
Fix typo.
carlosalberto Aug 10, 2020
92da36f
Apply feedback.
carlosalberto Aug 12, 2020
dd331ab
Fix typo.
carlosalberto Aug 12, 2020
b944a2c
Have the OT doc under a compatibility subdir.
carlosalberto Aug 14, 2020
c6027ba
Apply feedback.
carlosalberto Aug 17, 2020
272198e
Remove the read-only restriction for SpanContext values.
carlosalberto Aug 17, 2020
bf66d04
Update this PR.
carlosalberto Oct 14, 2020
36043f6
Do an improvement pass.
carlosalberto Oct 15, 2020
57ed80a
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Oct 15, 2020
d1ce668
Update the toplevel organization.
carlosalberto Oct 15, 2020
88fa597
Clarify returned values.
carlosalberto Oct 15, 2020
5c8bc99
Add a note on intention.
carlosalberto Oct 15, 2020
7ded0ce
Use Context as the container for Span/Baggage.
carlosalberto Oct 16, 2020
1567a97
Minor fixes.
carlosalberto Oct 16, 2020
155a286
Update specification/compatibility/opentracing.md
carlosalberto Dec 10, 2020
d92c209
Mention semantic conventions mapping.
carlosalberto Dec 10, 2020
597fff7
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Dec 11, 2020
e5deff1
Fix typo.
carlosalberto Dec 11, 2020
bb173ca
Improve the doc & clarify things.
carlosalberto Dec 11, 2020
a6fd708
BaggageManager is not needed anymore.
carlosalberto Dec 11, 2020
10d4ac4
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Dec 14, 2020
69d1424
More feedback.
carlosalberto Dec 16, 2020
1920d88
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Dec 16, 2020
b569ee9
Merge branch 'master' into add_ot_compatibility_new
yurishkuro Dec 27, 2020
0dff253
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Jan 6, 2021
439f484
Update specification/compatibility/opentracing.md
carlosalberto Jan 23, 2021
c18c10b
Update specification/compatibility/opentracing.md
carlosalberto Jan 23, 2021
ab02876
Merge branch 'master' into add_ot_compatibility_new
carlosalberto Jan 23, 2021
40b396c
Merge branch 'main' into add_ot_compatibility_new
carlosalberto Mar 4, 2021
d65fcdc
Merge branch 'main' into add_ot_compatibility_new
carlosalberto Mar 5, 2021
42a55e7
Add status.
carlosalberto Mar 5, 2021
c783567
Initial pass of feedback applied.
carlosalberto Mar 7, 2021
8547dc4
Automatically store Span Shim in the Context.
carlosalberto Mar 7, 2021
1fb02e6
Address Reiley's feedback.
carlosalberto Mar 7, 2021
350310f
Specify custom propagators to handle TextMap/HTTPHeaders.
carlosalberto Mar 7, 2021
1e842c7
Mention that Inject/Extract MAY indeed raise errors.
carlosalberto Mar 8, 2021
2a8dd16
Simplify the Span/SpanContext relationship explanation.
carlosalberto Mar 8, 2021
cfcb3d5
Clarify the Propagators used for Inject/Extract().
carlosalberto Mar 9, 2021
8c2d494
Fix links.
carlosalberto Mar 9, 2021
3c5f040
Merge branch 'main' into add_ot_compatibility_new
SergeyKanzhelev Mar 9, 2021
b1296a7
Merge branch 'main' into add_ot_compatibility_new
carlosalberto Mar 16, 2021
c340224
Merge branch 'main' into add_ot_compatibility_new
carlosalberto Mar 17, 2021
c2281fc
Update CHANGELOG.
carlosalberto Mar 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ release.

### Semantic Conventions

### Compatibility

- Add initial OpenTracing compatibility section.
([#1101](https://github.com/open-telemetry/opentelemetry-specification/pull/1101))

## v1.1.0 (2021-03-11)

### Traces
Expand Down
343 changes: 343 additions & 0 deletions specification/compatibility/opentracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
# OpenTracing Compatibility

**Status**: [Experimental](../document-status.md).

<details>
<summary>Table of Contents</summary>

carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
* [Abstract](#abstract)
* [Create an OpenTracing Tracer Shim](#create-an-opentracing-tracer-shim)
* [Tracer Shim](#tracer-shim)
* [Inject](#inject)
* [Extract](#extract)
* [OpenTelemetry Span and SpanContext Shim relationship](#opentelemetry-span-and-spancontext-shim-relationship)
* [Span Shim](#span-shim)
* [Get Context](#get-context)
* [Get Baggage Item](#get-baggage-item)
* [Set Baggage Item](#set-baggage-item)
* [Set Tag](#set-tag)
* [Log](#log)
* [Finish](#finish)
* [SpanContext Shim](#spancontext-shim)
* [Get Baggage Items](#get-baggage-items)
* [ScopeManager Shim](#scopemanager-shim)
* [Activate a Span](#activate-a-span)
* [Get the active Span](#get-the-active-span)

</details>

## Abstract

The OpenTelemetry project aims to provide backwards compatibility with the
[OpenTracing](https://opentracing.io) project in order to ease migration of
instrumented codebases.
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved

This functionality will be provided as a bridge layer implementing the
[OpenTracing API](https://github.com/opentracing/specification) using the
OpenTelemetry API. This layer MUST NOT rely on implementation specific details
of any SDK.
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved

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 create `Span`s.
- OpenTelemetry `Propagator`s to be used to perform injection and extraction
for the the OpenTracing `TextMap` and `HTTPHeaders` formats.
If not specified, no `Propagator` values will be stored in the Shim, and
the global OpenTelemetry `TextMap` propagator will be used for both OpenTracing
`TextMap` and `HTTPHeaders` formats.

The API MUST return an OpenTracing `Tracer`.

```java
// 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](https://github.com/opentracing/specification/blob/master/specification.md#extract-a-spancontext-from-a-carrier).

## 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` and `HttpHeaders` formats MUST use their explicitly specified `TextMapPropagator`,
if any, or else use the global `TextMapPropagator`.

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` and `HttpHeaders` formats MUST use their explicitly specified `TextMapPropagator`,
if any, or else use the global `TextMapPropagator`.

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](#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](#set-baggage-item) operation called from two different
execution units (e.g. threads, coroutines), and afterwards have its
[Context](#get-context) fetched in order to
[iterate over its baggage values](#get-baggage-items).

```java
// 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
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
```

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
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
`Span`'s `Add Events` operations.

The `Set Tag` operations MUST be implemented using the OpenTelemetry
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
`Span`'s `Set Attributes` operations.

### Get Context

Returns the [associated](#opentelemetry-span-and-spancontext-shim-relationship)
`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](#opentelemetry-span-and-spancontext-shim-relationship)
`SpanContext` Shim and do a lookup for the specified key in the OpenTelemetry
`Baggage` instance.

```java
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](#opentelemetry-span-and-spancontext-shim-relationship) to the underlying
OpenTelemetry `Span`.

carlosalberto marked this conversation as resolved.
Show resolved Hide resolved
```java
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](https://github.com/opentracing/specification/blob/master/semantic_conventions.md#standard-span-tags-and-log-fields)
to the respective OpenTelemetry `Attribute`:

- `error` maps to [StatusCode](../trace/api.md##set-status):
- `true` maps to `Error`.
- `false` maps to `Ok`.
- 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.
carlosalberto marked this conversation as resolved.
Show resolved Hide resolved

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](#opentelemetry-span-and-spancontext-shim-relationship)
`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.

```java
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.

```java
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());
}
```