specification

The OpenTracing Semantic Specification

Version: 1.1

Document Overview

This is the “formal” OpenTracing semantic specification. Since OpenTracing must work across many languages, this document takes care to avoid language-specific concepts. That said, there is an understanding throughout that all languages have some concept of an “interface” which encapsulates a set of related capabilities.

Versioning policy

The OpenTracing specification uses a Major.Minor version number but has no .Patch component. The major version increments when backwards-incompatible changes are made to the specification. The minor version increments for non-breaking changes like the introduction of new standard tags, log fields, or SpanContext reference types. (You can read more about the motivation for this versioning scheme at Issue specification#2)

The OpenTracing Data Model

Traces in OpenTracing are defined implicitly by their Spans. In particular, a Trace can be thought of as a directed acyclic graph (DAG) of Spans, where the edges between Spans are called References.

For example, the following is an example Trace made up of 8 Spans:

Causal relationships between Spans in a single Trace


        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)

Sometimes it’s easier to visualize Traces with a time axis as in the diagram below:

Temporal relationships between Spans in a single Trace


––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··] [Span G··] [Span H··]

Each Span encapsulates the following state:

Each SpanContext encapsulates the following state:

References between Spans

A Span may reference zero or more other SpanContexts that are causally related. OpenTracing presently defines two types of references: ChildOf and FollowsFrom. Both reference types specifically model direct causal relationships between a child Span and a parent Span. In the future, OpenTracing may also support reference types for Spans with non-causal relationships (e.g., Spans that are batched together, Spans that are stuck in the same queue, etc).

ChildOf references: A Span may be the ChildOf a parent Span. In a ChildOf reference, the parent Span depends on the child Span in some capacity. All of the following would constitute ChildOf relationships:

These could all be valid timing diagrams for children that are the ChildOf a parent.

    [-Parent Span---------]
         [-Child Span----]

    [-Parent Span--------------]
         [-Child Span A----]
          [-Child Span B----]
        [-Child Span C----]
         [-Child Span D---------------]
         [-Child Span E----]

FollowsFrom references: Some parent Spans do not depend in any way on the result of their child Spans. In these cases, we say merely that the child Span FollowsFrom the parent Span in a causal sense. There are many distinct FollowsFrom reference sub-categories, and in future versions of OpenTracing they may be distinguished more formally.

These can all be valid timing diagrams for children that “FollowFrom” a parent.

    [-Parent Span-]  [-Child Span-]


    [-Parent Span--]
     [-Child Span-]


    [-Parent Span-]
                [-Child Span-]

The OpenTracing API

There are three critical and inter-related types in the OpenTracing specification: Tracer, Span, and SpanContext. Below, we go through the behaviors of each type; roughly speaking, each behavior becomes a “method” in a typical programming language, though it may actually be a set of related sibling methods due to type overloading and so on.

When we discuss “optional” parameters, it is understood that different languages have different ways to construe such concepts. For example, in Go we might use the “functional Options” idiom, whereas in Java we might use a builder pattern.

Tracer

The Tracer interface creates Spans and understands how to Inject (serialize) and Extract (deserialize) them across process boundaries. Formally, it has the following capabilities:

Start a new Span

Required parameters

For example, here are potential operation names for a Span that gets hypothetical account information:

Operation Name Guidance
get Too general
get_account/792 Too specific
get_account Good, and account_id=792 would make a nice Span tag

Optional parameters

Returns a Span instance that’s already started (but not Finished)

Inject a SpanContext into a carrier

Required parameters

Extract a SpanContext from a carrier

Required parameters

Returns a SpanContext instance suitable for use as a reference when starting a new Span via the Tracer.

Note: required formats for injection and extraction

Both injection and extraction rely on an extensible format parameter that dictates the type of the associated “carrier” as well as how a SpanContext is encoded in that carrier. All of the following formats must be supported by all Tracer implementations.

Span

With the exception of the method to retrieve the Span’s SpanContext, none of the below may be called after the Span is finished.

Retrieve the Spans SpanContext

There should be no parameters.

Returns the SpanContext for the given Span. The returned value may be used even after the Span is finished.

Overwrite the operation name

Required parameters

Finish the Span

Optional parameters

With the exception of the method to retrieve a Span’s SpanContext, no method may be called on a Span instance after it’s finished.

Set a Span tag

Required parameters

Note that the OpenTracing project documents certain “standard tags” that have prescribed semantic meanings.

Log structured data

Required parameters

Optional parameters

Note that the OpenTracing project documents certain “standard log keys” which have prescribed semantic meanings.

Set a baggage item

Baggage items are key:value string pairs that apply to the given Span, its SpanContext, and all Spans which directly or transitively reference the local Span. That is, baggage items propagate in-band along with the trace itself.

Baggage items enable powerful functionality given a full-stack OpenTracing integration (for example, arbitrary application data from a mobile app can make it, transparently, all the way into the depths of a storage system), and with it some powerful costs: use this feature with care.

Use this feature thoughtfully and with care. Every key and value is copied into every local and remote child of the associated Span, and that can add up to a lot of network and cpu overhead.

Required parameters

Get a baggage item

Required parameters

Returns either the corresponding baggage value, or some indication that such a value was missing.

SpanContext

The SpanContext is more of a “concept” than a useful piece of functionality at the generic OpenTracing layer. That said, it is of critical importance to OpenTracing implementations and does present a thin API of its own. Most OpenTracing users only interact with SpanContext via references when starting new Spans, or when injecting/extracting a trace to/from some transport protocol.

In OpenTracing we force SpanContext instances to be immutable in order to avoid complicated lifetime issues around Span finish and references.

Iterate through all baggage items

This is modeled in different ways depending on the language, but semantically the caller should be able to efficiently iterate through all baggage items in one pass given a SpanContext instance.

NoopTracer

All OpenTracing language APIs must also provide some sort of NoopTracer implementation which can be used to flag-control OpenTracing or inject something harmless for tests (et cetera). In some cases (for example, Java) the NoopTracer may be in its own packaging artifact.

Optional API Elements

Some languages also provide utilities to pass an active Span and/or SpanContext around a single process. For instance, opentracing-go provides helpers to set and get the active Span in Go’s context.Context mechanism.