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

Spans's parent must be passed as Context instead of Span(Context)s. #875

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ Updates:
([#911](https://github.com/open-telemetry/opentelemetry-specification/pull/911))
- Explicitly specify the SpanContext APIs IsValid and IsRemote as required
([#914](https://github.com/open-telemetry/opentelemetry-specification/pull/914))
- A full `Context` is the only way to specify a parent of a `Span`.
`SpanContext` or even `Span` are not allowed anymore.
([#875](https://github.com/open-telemetry/opentelemetry-specification/pull/875))

## v0.6.0 (07-01-2020)

Expand Down
53 changes: 24 additions & 29 deletions specification/trace/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Table of Contents
* [IsRemote](#isremote)
* [Span](#span)
* [Span creation](#span-creation)
* [Determining the Parent Span from a Context](#determining-the-parent-span-from-a-context)
* [Add Links](#add-links)
* [Effective Span](#effective-span)
* [Span operations](#span-operations)
* [Get Context](#get-context)
* [IsRecording](#isrecording)
Expand Down Expand Up @@ -240,8 +240,7 @@ the entire operation and, optionally, one or more sub-spans for its sub-operatio
- The span name
- An immutable [`SpanContext`](#spancontext) that uniquely identifies the
`Span`
- A parent span in the form of a [`Span`](#span), [`SpanContext`](#spancontext),
or null
- A parent span in the form of a (possibly empty) [`Context`](../context/context.md)
Copy link
Member

Choose a reason for hiding this comment

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

We should also allow just Span in case people are not using Context

Copy link
Member Author

@Oberon00 Oberon00 Aug 25, 2020

Choose a reason for hiding this comment

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

Why should people not use context? It is possible to support this but it would introduce a complication. We would have to specify: "If a Span is passed as Context, the parent Context of the child span is the parent Context of the parent span (i.e., the grandparent Context) with the Span in it replaced with the parent Span".
EDIT: As noted in the sdk part of this PR, a span can be in multiple contexts, therefore it is impossible to map a Span back to a Context. Thus passing a Span instead of a Context implies data-loss.

Copy link
Member

Choose a reason for hiding this comment

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

In JS I know it is a problem

Copy link
Member

Choose a reason for hiding this comment

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

Also in some cases you start an operation and directly interact with the Span.

Copy link
Member Author

Choose a reason for hiding this comment

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

Context is already the only way to inject/propagate a Span. So both of the problems you mention are necessarily already solved by all SIGs that implement the OTEP66 propagation spec.

Copy link
Member

Choose a reason for hiding this comment

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

@Oberon00 believe me or not, I saw lots of cases where just Span could be provided (no longer work at Google to show more examples). I do believe this is a mistake to not support Span as well. Don't know how to convince besides waiting for a language to implement this and make all changes to all the instrumentations to see there will be cases where this is not possible.

Copy link
Member Author

@Oberon00 Oberon00 Sep 1, 2020

Choose a reason for hiding this comment

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

In these cases, you can also not inject. Or rather, you can by using something like TracingContextUtil.currentContextWithSpan. This at least makes it more explicit that you are dropping information (and more cumbersome, which I think is OK here, as it nudges you to preserve the full 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 disagree with this and think it should be only a Span/SpanContext. Making the parent a Context means there is an association between the Span and the Baggage. I may be wrong but my understanding was that they are separate concerns.

If the issue is returning to the parent but not losing the baggage (or anything else in the context) then the fix should be to not reset the entire context.

In the Erlang implementation the Context contains a list of SpanContexts. When the current span is ended it is popped from the head of the list, the rest of the Context remains unchanged.

You could call the list of SpanContexts the TraceContext, which is just one part of the total Context.

Copy link
Member Author

Choose a reason for hiding this comment

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

my understanding was that they are separate concerns.

My understanding was that while they are separate concerns, we do want to be able to cross-reference and connect different concerns, and the Context should be the place where everything comes together. That was how I understood OTEP66, and also our current propagator spec. But I guess this needs a decision. If we don't want this connection (#867, #381 seem to imply we do), then I agree that this PR is not the way we should go and @anuraaga's idea of extending SpanContext is better.

Copy link
Member

Choose a reason for hiding this comment

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

I think, I will self apply the rule of "minimal api" :). We know for sure we need the "context" parent so it is great, for the "Span" parent we may or may not have good use-cases, so maybe add it later if that is the case.

So happy for me to start with only accepting Context for this because we can add later the "Span".

- A [`SpanKind`](#spankind)
- A start timestamp
- An end timestamp
Expand Down Expand Up @@ -307,24 +306,20 @@ directly. All `Span`s MUST be created via a `Tracer`.

There MUST NOT be any API for creating a `Span` other than with a [`Tracer`](#tracer).

When creating a new `Span`, the `Tracer` MUST allow the caller to specify the
new `Span`'s parent in the form of a `Span` or `SpanContext`. The `Tracer`
SHOULD create each new `Span` as a child of its active `Span`, unless an
explicit parent is provided or the option to create a span without a parent is
selected.

`Span` creation MUST NOT set the newly created `Span` as the currently
active `Span` by default, but this functionality MAY be offered additionally
as a separate operation.

The API MUST accept the following parameters:

- The span name. This is a required parameter.
- The parent `Span` or a `Context` containing a parent `Span` or `SpanContext`,
and whether the new `Span` should be a root `Span`. API MAY also have an
option for implicit parenting from the current context as a default behavior.
See [Determining the Parent Span from a Context](#determining-the-parent-span-from-a-context)
for guidance on `Span` parenting from explicit and implicit `Context`s.
- 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`.

The semantic parent of the Span MUST be determined according to the rules
described in the [Effective Span section](#effective-span).
- [`SpanKind`](#spankind), default to `SpanKind.Internal` if not specified.
- [`Attributes`](../common/common.md#attributes). Additionally,
these attributes may be used to make a sampling decision as noted in [sampling
Expand Down Expand Up @@ -354,21 +349,6 @@ created in another process. Each propagators' deserialization must set
`IsRemote` to true on a parent `SpanContext` so `Span` creation knows if the
parent is remote.

#### Determining the Parent Span from a Context

When a new `Span` is created from a `Context`, the `Context` may contain:

- A current `Span`
- An extracted `SpanContext`
- A current `Span` and an extracted `SpanContext`
- Neither a current `Span` nor an extracted `Span` context

The parent should be selected in the following order of precedence:

- Use the current `Span`, if available.
- Use the extracted `SpanContext`, if available.
- There is no parent. Create a root `Span`.

#### Add Links

During the `Span` creation user MUST have the ability to record links to other `Span`s.
Expand All @@ -391,6 +371,21 @@ The Span creation API MUST provide:

Links SHOULD preserve the order in which they're set.

### Effective Span

The *effective span* of a [`Context`](../context/context.md) is the first of the
following that is available in it (with the respective key if applicable):

1. An actual `Span` object.
2. An extracted `SpanContext`
(that MAY be wrapped in an otherwise empty non-recording `Span`).
3. Nothing (which SHOULD be represented as a non-null empty `SpanContext` or `Span`).

The API MUST provide functionality to get the effective Span from a `Context`.

Given a `Span` with its parent `Context`, the semantic parent Span is the
Oberon00 marked this conversation as resolved.
Show resolved Hide resolved
effective span in that parent `Context`.

### Span operations

With the exception of the function to retrieve the `Span`'s `SpanContext` and
Expand Down
7 changes: 5 additions & 2 deletions specification/trace/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,19 +276,22 @@ in the SDK:

### Interface definition

#### OnStart(Span)
#### OnStart

`OnStart` is called when a span is started. This method is called synchronously
on the thread that started the span, therefore it should not block or throw
exceptions.

**Parameters:**

* `Span` - a [read/write span object](#additional-span-interfaces) for the started span.
* `span` - a [read/write span object](#additional-span-interfaces) for the started span.
It SHOULD be possible to keep a reference to this span object and updates to the span
SHOULD be reflected in it.
For example, this is useful for creating a SpanProcessor that periodically
evaluates/prints information about all active span from a background thread.
* `parentContext` - the parent `Context` of the span that the SDK determined
(the explicitly passed `Context`, the current `Context` or an empty `Context`
if that was explicitly requested).

**Returns:** `Void`

Expand Down