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

Merge SpanContext into Span #1033

Closed
wants to merge 13 commits into from
4 changes: 2 additions & 2 deletions specification/context/api-propagators.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Injects the value into a carrier. For example, into the headers of an HTTP reque
Required arguments:

- A `Context`. The Propagator MUST retrieve the appropriate value from the `Context` first, such as
`SpanContext`, `Baggage` or another cross-cutting concern context.
`Span`, `Baggage` or another cross-cutting concern context.
- The carrier that holds the propagation fields. For example, an outgoing message or HTTP request.

#### Extract
Expand All @@ -93,7 +93,7 @@ Required arguments:
- The carrier that holds the propagation fields. For example, an incoming message or http response.

Returns a new `Context` derived from the `Context` passed as argument,
containing the extracted value, which can be a `SpanContext`,
containing the extracted value, which can be a `Span`,
`Baggage` or another cross-cutting concern context.

## TextMap Propagator
Expand Down
19 changes: 6 additions & 13 deletions specification/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ Table of Contents
- [Distributed Tracing](#distributed-tracing)
* [Trace](#trace)
* [Span](#span)
* [SpanContext](#spancontext)
* [Links between spans](#links-between-spans)
- [Metrics](#metrics)
* [Recording raw measurements](#recording-raw-measurements)
Expand Down Expand Up @@ -96,15 +95,10 @@ Each **Span** encapsulates the following state:
- A set of zero or more **Events**, each of which is itself a tuple (timestamp, name, [**Attributes**](./common/common.md#attributes)). The name must be strings.
- Parent's **Span** identifier.
- [**Links**](#links-between-spans) to zero or more causally-related **Spans**
(via the **SpanContext** of those related **Spans**).
- **SpanContext** identification of a Span. See below.
- Identifiers of a Span. See below.

### SpanContext

Represents all the information that identifies **Span** in the **Trace** and
MUST be propagated to child Spans and across process boundaries. A
**SpanContext** contains the tracing identifiers and the options that are
propagated from parent to child **Spans**.
A **Span** has the following identifiers and the options which MUST be propagated to child Spans
and across process boundaries. These are propagated from parent to child **Spans**.

- **TraceId** is the identifier for a trace. It is worldwide unique with
practically sufficient probability by being made as 16 randomly generated
Expand All @@ -125,9 +119,8 @@ propagated from parent to child **Spans**.

### Links between spans

A **Span** may be linked to zero or more other **Spans** (defined by
**SpanContext**) that are causally related. **Links** can point to
**SpanContexts** inside a single **Trace** or across different **Traces**.
A **Span** may be linked to zero or more other **Spans** that are causally related.
**Links** can point to **Spans** inside a single **Trace** or across different **Traces**.
**Links** can be used to represent batched operations where a **Span** was
initiated by multiple initiating **Spans**, each representing a single incoming
item being processed in the batch.
Expand Down Expand Up @@ -280,7 +273,7 @@ See the [Context](context/context.md)
## Propagators

OpenTelemetry uses `Propagators` to serialize and deserialize cross-cutting concern values
such as `SpanContext` and `Baggage`. Different `Propagator` types define the restrictions
such as `Span` and `Baggage`. Different `Propagator` types define the restrictions
imposed by a specific transport and bound to a data type.

The Propagators API currently defines one `Propagator` type:
Expand Down
85 changes: 36 additions & 49 deletions specification/trace/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Table of Contents
* [Tracing Context Utilities](#tracing-context-utilities)
* [Tracer](#tracer)
* [Tracer operations](#tracer-operations)
* [SpanContext](#spancontext)
* [Span Identifiers](#span-identifiers)
* [Retrieving the TraceId and SpanId](#retrieving-the-traceid-and-spanid)
* [IsValid](#isvalid)
* [IsRemote](#isremote)
Expand All @@ -23,7 +23,6 @@ Table of Contents
* [Determining the Parent Span from a Context](#determining-the-parent-span-from-a-context)
* [Add Links](#add-links)
* [Span operations](#span-operations)
* [Get Context](#get-context)
* [IsRecording](#isrecording)
* [Set Attributes](#set-attributes)
* [Add Events](#add-events)
Expand Down Expand Up @@ -166,14 +165,12 @@ The `Tracer` MAY provide functions to:

These functions MUST delegate to the `Tracing Context Utilities`.

## SpanContext
## Span Identifiers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't call the TraceId part of the identity.


A `SpanContext` represents the portion of a `Span` which must be serialized and
propagated along side of a distributed context. `SpanContext`s are immutable.

The OpenTelemetry `SpanContext` representation conforms to the [W3C TraceContext
specification](https://www.w3.org/TR/trace-context/). It contains two
identifiers - a `TraceId` and a `SpanId` - along with a set of common
These parts of the span serve to identify it, both in-process and remotely. They are immutable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They do more than just identify it. This information is what is required to connect a parent span to a child span. For just identifying trace+span ID are usually enough (though some vendors might require a part of the tracestate).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took advantage of this line in the previous spec referring to SpanContext as an identifier

"An immutable SpanContext that uniquely identifies the Span"

But I agree the name isn't so great, just couldn't come up with a better one. It may be a reason to keep SpanContext as a concept indeed though ideally not implementation requirement as in #999.

I'll hold off on significant edits to this one until getting some more ideas on which to go with.

pieces of the `Span`, as opposed to the data collecting [span operations](#span-operations).
These identifiers conform to the [W3C TraceContext specification](https://www.w3.org/TR/trace-context/).
It contains two identifiers - a `TraceId` and a `SpanId` - along with a set of common
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing -- it says that identifiers contains identifiers (and more stuff). So now we have two different definitions for "identifiers".

`TraceFlags` and system-specific `TraceState` values.

`TraceId` A valid trace identifier is a 16-byte array with at least one
Expand All @@ -191,13 +188,12 @@ of key-value pairs. TraceState allows multiple tracing
systems to participate in the same trace. It is fully described in the [W3C Trace Context
specification](https://www.w3.org/TR/trace-context/#tracestate-header).

The API MUST implement methods to create a `SpanContext`. These methods SHOULD be the only way to
create a `SpanContext`. This functionality MUST be fully implemented in the API, and SHOULD NOT be
overridable.
The API MUST allow creating a `Span` with these identifiers, either during [span creation](#span-creation)
or when creating a [propagated span](#propagated-span-creation).

### Retrieving the TraceId and SpanId

The API MUST allow retrieving the `TraceId` and `SpanId` in the following forms:
The API MUST allow retrieving the `TraceId` and `SpanId` from a span in the following forms:

* Hex - returns the lowercase [hex encoded](https://tools.ietf.org/html/rfc4648#section-8)
`TraceId` (result MUST be a 32-hex-character lowercase string) or `SpanId`
Expand All @@ -209,19 +205,19 @@ The API should not expose details about how they are internally stored.

### IsValid

An API called `IsValid`, that returns a boolean value, which is `true` if the SpanContext has a
An API called `IsValid`, that returns a boolean value, which is `true` if the Span has a
non-zero TraceID and a non-zero SpanID, MUST be provided.

### IsRemote

An API called `IsRemote`, that returns a boolean value, which is `true` if the SpanContext was
An API called `IsRemote`, that returns a boolean value, which is `true` if the Span was
propagated from a remote parent, MUST be provided.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A span cannot be propagated from a remote parent unless it's a "Propagated span". We should clarify this. E.g. "A remote span is never recording", otherwise we re-open the discussion at #359.

When extracting a `SpanContext` through the [Propagators API](../context/api-propagators.md#propagators-api),
`IsRemote` MUST return true, whereas for the SpanContext of any child spans it MUST return false.
When extracting span identifiers through the [Propagators API](../context/api-propagators.md#propagators-api),
`IsRemote` MUST return true, whereas for any child spans it MUST return false.

### TraceState

`TraceState` is a part of [`SpanContext`](./api.md#spancontext), represented by an immutable list of string key/value pairs and
`TraceState` is a part of the [span's identifiers](#span-identifiers), represented by an immutable list of string key/value pairs and
formally defined by the [W3C Trace Context specification](https://www.w3.org/TR/trace-context/#tracestate-header).
Tracing API MUST provide at least the following operations on `TraceState`:

Expand All @@ -237,9 +233,9 @@ Every mutating operations MUST validate input parameters.
If invalid value is passed the operation MUST NOT return `TraceState` containing invalid data
and MUST follow the [general error handling guidelines](../error-handling.md) (e.g. it usually must not return null or throw an exception).

Please note, since `SpanContext` is immutable, it is not possible to update `SpanContext` with a new `TraceState`.
Please note, since span identifiers are immutable, it is not possible to update a span with a new `TraceState`.
Such changes then make sense only right before
[`SpanContext` propagation](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/api-propagators.md)
[`Context` propagation](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/api-propagators.md)
or [telemetry data exporting](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk.md#span-exporter).
In both cases, `Propagators` and `SpanExporters` may create a modified `TraceState` copy before serializing it to the wire.

Expand All @@ -253,9 +249,9 @@ the entire operation and, optionally, one or more sub-spans for its sub-operatio
`Span`s encapsulate:

- The span name
- An immutable [`SpanContext`](#spancontext) that uniquely identifies the
- Immutable [span identifiers](#span-identifiers) that uniquely identifies the
`Span`
- A parent span in the form of a [`Span`](#span), [`SpanContext`](#spancontext),
- A parent span in the form of a [`Span`](#span) that is stored in a [Context](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/context.md)
or null
- A [`SpanKind`](#spankind)
- A start timestamp
Expand Down Expand Up @@ -312,7 +308,7 @@ MUST NOT be changed after the `Span`'s end time has been set.

`Span`s are not meant to be used to propagate information within a process. To
prevent misuse, implementations SHOULD NOT provide access to a `Span`'s
attributes besides its `SpanContext`.
attributes besides its identifiers.

Vendors may implement the `Span` interface to effect vendor-specific logic.
However, alternative implementations MUST NOT allow callers to create `Span`s
Expand All @@ -332,7 +328,7 @@ The API MUST accept the following parameters:
- The parent `Context` or an indication that the new `Span` should be a root `Span`.
The API MAY also have an option for implicitly using
the current Context as parent as a default behavior.
This API MUST NOT accept a `Span` or `SpanContext` as parent, only a full `Context`.
This API MUST NOT accept a `Span` as parent, only a full `Context`.

The semantic parent of the Span MUST be determined according to the rules
described in [Determining the Parent Span from a Context](#determining-the-parent-span-from-a-context).
Expand Down Expand Up @@ -362,7 +358,7 @@ Also, the child span MUST inherit all `TraceState` values of its parent by defau

A `Span` is said to have a _remote parent_ if it is the child of a `Span`
created in another process. Each propagators' deserialization must set
`IsRemote` to true on a parent `SpanContext` so `Span` creation knows if the
`IsRemote` to true on a parent `Span` so `Span` creation knows if the
parent is remote.

#### Determining the Parent Span from a Context
Expand All @@ -371,8 +367,8 @@ When a new `Span` is created from a `Context`, the `Context` may contain a `Span
representing the currently active instance, and will be used as parent.
If there is no `Span` in the `Context`, the newly created `Span` will be a root span.

A `SpanContext` cannot be set as active in a `Context` directly, but through the use
of a [Propagated Span](#propagated-span-creation) wrapping it.
A remote span's [span identifiers](#span-identifiers) can be set as active in a `Context`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels especially clumsy. How can span identifiers be set anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is some clumsiness inherited from the previous wording too, one confusion I had is that since we make spans active, it's a bit mysterious to also have spancontexts that are active.

What do you think of just "A remote span can be set as active in a Context"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think we can remove this sentence now without replacement.

through the use of a [Propagated Span](#propagated-span-creation).
For example, a `Propagator` performing context extraction may need this.

#### Add Links
Expand All @@ -385,7 +381,7 @@ description](../overview.md#links-between-spans).

A `Link` is defined by the following properties:

- (Required) `SpanContext` of the `Span` to link to.
- (Required) the `Span` to link to or its [span identifiers](#span-identifiers).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the meaning. SpanContext also contains TraceState (which might be considered part of the identifier for proprietary systems) and TraceFlags (which are definitely not part of the identifier).

- (Optional) One or more `Attribute`s as defined [here](../common/common.md#attributes).

The `Link` SHOULD be an immutable type.
Expand All @@ -399,17 +395,9 @@ Links SHOULD preserve the order in which they're set.

### Span operations

With the exception of the function to retrieve the `Span`'s `SpanContext` and
With the exception of the function to retrieve the `Span`'s identifiers and
recording status, none of the below may be called after the `Span` is finished.

#### Get Context
Oberon00 marked this conversation as resolved.
Show resolved Hide resolved

The Span interface MUST provide:

- An API that returns the `SpanContext` for the given `Span`. The returned value
may be used even after the `Span` is finished. The returned value MUST be the
same for the entire Span lifetime. This MAY be called `GetContext`.

#### IsRecording

Returns true if this `Span` is recording information like events with the
Expand All @@ -421,8 +409,7 @@ There should be no parameter.
This flag SHOULD be used to avoid expensive computations of a Span attributes or
events in case when a Span is definitely not recorded. Note that any child
span's recording is determined independently from the value of this flag
(typically based on the `sampled` flag of a `TraceFlag` on
[SpanContext](#spancontext)).
(typically based on the `sampled` flag of a `TraceFlag` on [Span](#span)).
anuraaga marked this conversation as resolved.
Show resolved Hide resolved

This flag may be `true` despite the entire trace being sampled out. This
allows to record and process information about the individual Span without
Expand Down Expand Up @@ -578,15 +565,15 @@ calling of corresponding API.

### Propagated Span creation

The API MUST provide an operation for wrapping a `SpanContext` with an object
implementing the `Span` interface. This is done in order to expose a `SpanContext`
as a `Span` in operations such as in-process `Span` propagation.
The API MUST provide an operation for creating an object implementing the `Span` interface
anuraaga marked this conversation as resolved.
Show resolved Hide resolved
provided its identifiers. This is done in order to expose it in operations such as in-process
`Span` propagation.

If a new type is required for supporting this operation, it SHOULD be named `PropagatedSpan`.

The behavior is defined as follows:

- `GetContext()` MUST return the wrapped `SpanContext`.
- It MUST have accessors for all the [span identifiers](#span-identifiers).
- `IsRecording` MUST return `false` to signal that events, attributes and other elements
are not being recorded, i.e. they are being dropped.

Expand Down Expand Up @@ -732,14 +719,14 @@ The API layer MAY include the following `Propagator`s:

In general, in the absence of an installed SDK, the Trace API is a "no-op" API.
This means that operations on a Tracer, or on Spans, should have no side effects and do nothing. However, there
is one important exception to this general rule, and that is related to propagation of a SpanContext.
is one important exception to this general rule, and that is related to propagation of a Span.

The following cases must be considered when a new Span is requested to be created, especially in relation to the
requested parent SpanContext:
requested parent Span:

* A valid `SpanContext` is specified as the parent of the new `Span`: The API MUST treat this parent context as the
context for the newly created `Span`. This means that a `SpanContext` that has been provided by a configured `Propagator`
will be propagated through to any child span, but that no new `SpanContext`s will be created.
* No valid `SpanContext` is specified as the parent of the new `Span`: The API MUST create an non-valid
* A valid `Span` is specified as the parent of the new `Span`: The API MUST treat this parent context as the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related #1023

context for the newly created `Span`. This means that a `Span` that has been provided by a configured `Propagator`
will be propagated through to any child span.
* No valid `Span` is specified as the parent of the new `Span`: The API MUST create an non-valid
(both SpanID and TradeID are equivalent to being all zeros) `Span` for use
by the API caller. This means that both the `TraceID` and the `SpanID` should be invalid.
19 changes: 9 additions & 10 deletions specification/trace/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ The OpenTelemetry API has two properties responsible for the data collection:
Processor](#span-processor) MUST receive only those spans which have this
field set to `true`. However, [Span Exporter](#span-exporter) SHOULD NOT
receive them unless the `Sampled` flag was also set.
* `Sampled` flag in `TraceFlags` on `SpanContext`. This flag is propagated via
the `SpanContext` to child Spans. For more details see the [W3C Trace Context
* `Sampled` flag in `TraceFlags` on `Span`. This flag is propagated via
the `Context` to child Spans. For more details see the [W3C Trace Context
specification](https://www.w3.org/TR/trace-context/#sampled-flag). This flag indicates that the `Span` has been
`sampled` and will be exported. [Span Exporters](#span-exporter) MUST
receive those spans which have `Sampled` flag set to true and they SHOULD NOT receive the ones
Expand Down Expand Up @@ -78,9 +78,9 @@ Returns the sampling Decision for a `Span` to be created.

**Required arguments:**

* Parent `SpanContext`. May be invalid to indicate a root span.
* Parent `Span`. May be invalid to indicate a root span.
* `TraceId` of the `Span` to be created.
If the parent `SpanContext` contains a valid `TraceId`, they MUST always match.
If the parent `Span` contains a valid `TraceId`, they MUST always match.
* Name of the `Span` to be created.
* `SpanKind` of the `Span` to be created.
* Initial set of `Attributes` of the `Span` to be created.
Expand All @@ -99,8 +99,7 @@ It produces an output called `SamplingResult` which contains:
* `RECORD_AND_SAMPLE` - `IsRecording() == true` AND `Sampled` flag` MUST be set.
* A set of span Attributes that will also be added to the `Span`. The returned
object must be immutable (multiple calls may return different immutable objects).
* A `Tracestate` that will be associated with the `Span` through the new
`SpanContext`.
* A `Tracestate` that will be associated with the `Span`.
Note: If the sampler returns an empty `Tracestate` here, the `Tracestate` will be cleared,
so samplers should normally return the passed-in `Tracestate` if they do not intend
to change it.
Expand Down Expand Up @@ -156,10 +155,10 @@ still be sampled and extra traces will be sampled on the backend only.
* This is a composite sampler. `ParentBased` helps distinguished between the
following cases:
* No parent (root span).
* Remote parent (`SpanContext.IsRemote() == true`) with `SampledFlag` equals `true`
* Remote parent (`SpanContext.IsRemote() == true`) with `SampledFlag` equals `false`
* Local parent (`SpanContext.IsRemote() == false`) with `SampledFlag` equals `true`
* Local parent (`SpanContext.IsRemote() == false`) with `SampledFlag` equals `false`
* Remote parent (`Span.IsRemote() == true`) with `SampledFlag` equals `true`
Oberon00 marked this conversation as resolved.
Show resolved Hide resolved
* Remote parent (`Span.IsRemote() == true`) with `SampledFlag` equals `false`
* Local parent (`Span.IsRemote() == false`) with `SampledFlag` equals `true`
* Local parent (`Span.IsRemote() == false`) with `SampledFlag` equals `false`

Required parameters:

Expand Down