Skip to content

OTEP: Context-scoped Attributes#4931

Open
carlosalberto wants to merge 7 commits intoopen-telemetry:mainfrom
carlosalberto:otep-context-scoped-attrs
Open

OTEP: Context-scoped Attributes#4931
carlosalberto wants to merge 7 commits intoopen-telemetry:mainfrom
carlosalberto:otep-context-scoped-attrs

Conversation

@carlosalberto
Copy link
Contributor

@carlosalberto carlosalberto commented Mar 10, 2026

Add Context-scoped telemetry attributes which typically apply to all signals associated with a trace as it crosses a single service.

Resurrecting open-telemetry/oteps#207 while updating some changes that have happened since (e.g. changes in InstrumentationScope being a runtime concept rather than a compile-time one). Originally proposed by @Oberon00

Additionally:

  1. A Processor alternative being discarded as we would need to add an additional pre OnStart call in order to support Samplers.
  2. The open question whether Baggage should be included as part of stamping attributes to individual telemetry items (similar enough functionality).
  3. We disable this functionality by default. Users have to opt-in to use this.

Java prototype for traces/logs: https://github.com/open-telemetry/opentelemetry-java/compare/main...carlosalberto:context-scoped-attrs-proto?expand=1

Summary

This OTEP aims to address various related demands that have been brought up in the past, where the scope of Resource attributes is too broad, but the scope of Span attributes is too narrow. For example, this happens where there is a mismatch between the OpenTelemetry SDK’s (and thus TracerProvider’s, MeterProvider’s) process-wide initialization and the semantic scope of a (sub)service.

The context-scoped attributes allows you to attach attributes to all telemetry signals emitted within a Context. Context-scoped attributes are normal attributes, which means you can use strings, integers, floating point numbers, booleans or arrays thereof, just like for Span or Resource attributes. Context-scoped attributes are associated with all telemetry signals emitted while the Context containing the Context-scoped attributes is active and are available to telemetry exporters. For spans, the context within which the span is started applies. Like other telemetry APIs, Context-scoped attributes are write-only for applications. You cannot query the currently set Context-scoped attributes, they are only available on the SDK level (e.g. to Samplers and SpanProcessors and exporters).

Context-scoped attributes should be thought of equivalent to adding the attribute directly to each single telemetry item it applies to.

@carlosalberto carlosalberto requested review from a team as code owners March 10, 2026 15:17
(i.e., it is not necessary to make Context-scoped attributes distinguishable
from “direct” telemetry attributes).

### Exporter changes (none required)
Copy link
Member

Choose a reason for hiding this comment

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

its best to just remove this section completely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

}
```

The Context-scoped attributes must be available for all telemetry items they
Copy link
Member

Choose a reason for hiding this comment

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

we need to specify something about how it gets added to log/span/metrics. This OTEP says opt-in, but does not say anything specific beyond that. Is that intentionally left out in OTEP

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clarified this to (very) succinctly mention that the Context-scoped attributes are added at telemetry creation/emit time.

# Context-scoped attributes

Add Context-scoped telemetry attributes which typically apply to all signals
associated with a trace as it crosses a single service.
Copy link
Member

Choose a reason for hiding this comment

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

do we need to mention "trace" here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to "request" to make it more general.

## Motivation

This OTEP aims to address various related demands that have been brought up
in the past, where the scope of resource attributes is too broad, but the scope
Copy link
Member

Choose a reason for hiding this comment

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

not just the scope, but the lifetime too. Or it is implied I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

This OTEP aims to address various related demands that have been brought up
in the past, where the scope of resource attributes is too broad, but the scope
of span attributes is too narrow. For example, this happens where there is a
mismatch between the OpenTelemetry SDK’s (and thus TracerProvider’s, MeterProvider’s)
Copy link
Member

Choose a reason for hiding this comment

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

include LoggerProvider too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

between these, other than with the generic HTTP attributes like
`http.route` or `url.template`. The mentioned issue proposes to add an
`http.app` attribute but it is unclear where this could be placed.
The resource cannot be used, since there is only one that is shared between
Copy link
Member

Choose a reason for hiding this comment

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

resource cannot be used - this seems like a very specific limitation for the jvm example? Isn't it possible to create multiple Meter/Tracer/Logger providers, each with its own resource, for each independent application within the same process?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Included this as an alternative mentioned in the Motivation section (albeit being a prohibitive one, given you would need to duplicate the pipeline).

booleans or arrays thereof, just like for span or resource attributes.
Context-scoped attributes are associated with all telemetry signals emitted while
the Context containing the Context-scoped attributes is active and are available
to samplers, processors and exporters. For spans, the context within which the span
Copy link
Member

Choose a reason for hiding this comment

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

exporters? That would be incorrect as a batching_processor can call exporter in its background thread, losing the original context.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clarified this. Context-scoped attributes only apply to telemetry at creation time.

to samplers, processors and exporters. For spans, the context within which the span
is started applies. Like other telemetry APIs, Context-scoped attributes are
write-only for applications. You cannot query the currently set Context-scoped attributes,
as they are only available on the SDK level (to samplers, processors and exporters).
Copy link
Member

Choose a reason for hiding this comment

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

remove exporters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed them.

must be implemented for them. This is because they are meant to annotate (a subset of)
the spans of a single service (see also [the next section](#comp-baggage)).

Context-scoped attributes MUST be disabled by default. They MUST be offered as an opt-in
Copy link
Member

Choose a reason for hiding this comment

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

lets make it clear what is meant by disabled here. I guess you are referring to "Context-scoped attributes are not automatically added to spans/logs/metrics unless user has explicitly opted into it. Opt-in mechanism are in [link to the section where we talk about it.]"

Copy link
Member

Choose a reason for hiding this comment

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

I didn't see any text describing what an opt-in mechanism would look like. I expected it to take the form of config params on SDK TracerProvider, LoggerProvider, MeterProvider, or new built-in SpanProcessor, LogRecordProcessors, MeasurementProcessor (rejected 🙁) with corresponding config handles.

Did I miss something or is the opt-in mechanism TBD?


However, the use cases are very different: Baggage is meant to transport app-level
data along the path of execution, while Context-scoped attributes are annotations
for telemetry in the same execution path.
Copy link
Member

Choose a reason for hiding this comment

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

app-level data vs telemetry annotations - not sure of the differences between them.. In my view, the only difference between Baggage is that Baggage is out-of-proc+in-proc, whereas Context-scope Attributes is in-proc only.
(I can think of calling this as InProcOnlyBagagge as well)

What kind of data users put inside it - totally upto them. They can put data to affect control flow, telemetry attributes, feature-flags etc. OTel don't put any restrictions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Baggage only accepts strings. Also, if we were to go any Baggage way, we should offer automatic attachment of Baggage values at the SDK level, like the one defined by this OTEP.

Context-scoped attributes would be implementable, it would break the intended
meaning by extending the scope of attributes to called services and would also
raise many security concerns.
* Baggage is both readable and writable for the application, while Context-scoped
Copy link
Member

Choose a reason for hiding this comment

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

I am not so sure about "write-only" aspect. Why restrict it, when Context itself supports reading:
specification/tree/main/specification/context#get-value

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'd like to reduce the area if possible. If we get cases were it is valuable to expose this to the public, we can go ahead and do that.

* Baggage is both readable and writable for the application, while Context-scoped
attributes, like all other telemetry attributes, are write-only.
* Baggage only supports string values.
* Baggage is not available to telemetry exporters (although e.g., a SpanProcessor
Copy link
Member

Choose a reason for hiding this comment

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

Left this same comment elsewhere too, but repeating here as this statement feels incorrect to me. Exporters can always access a Context, but that is very unlikely the one present during the actual telemetry creation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call, made a clarification.

* Both apply a set of telemetry attributes to a set of telemetry items
(those in their "scope").

While Instrumentation Scope attributes apply to all items emitted by the same
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 a good way to describe this is - they differ in lifetime. Tracer/Meter etc. typically lives same time as the application itself. But context-scoped ties its lifetime to the context itself, so if the context is per-request, then it lives only that long. But if the context is app-start, then it lives entire application.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a small paragraph to mention this.

* If the context already contains any attributes with that name, they MUST be
overwritten with the attributes of the later call.
* If an associated telemetry item (e.g. Span) already has an attribute with
a name that is also in the Context-scoped attributes, the telemetry attribute
Copy link
Member

Choose a reason for hiding this comment

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

this API section is merely talking about adding ScopedAttribtues to Context - so it is better to avoid the mentioning of Span case here (and span attributes)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think examples are useful in order to be super clear. Changed this to "e.g. Span or LogRecordItem".


The Context-scoped attributes must be available for all telemetry items they
are logically associated with. For example, the `ReadableSpan` should include
the context attributes in the list of Span attributes, and they must be included
Copy link
Member

Choose a reason for hiding this comment

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

This section feels a bit odd - we directly jump into the state where Span attributes already contain Context attributes, without specifying who/how that happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed this paragraph and simplified the previous one - it may be too short but it's now more explicit.


This OTEP relies on the
[`Context`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/README.md)
concept that has been in the spec since 1.0. However, at least .NET went 1.0
Copy link
Member

Choose a reason for hiding this comment

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

Don't think this is true - .NET also has context. Used by Baggage.

(Its span (activity)/span context are implemented outside of this context. It can be an issue in some cases. But those cases already have issues with Baggage too.).

Its better to avoid including .NET's exceptions to the OTEP.

Copy link
Member

Choose a reason for hiding this comment

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

.NET folks anyway has to deal with a competing concept in ILogger - it has ILogger.BeginScope()., quite similar to this proposal - but sadly, it's tied to loggging signal only and not general purpose like this proposal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

is injected in a JVM running a classical Java Application Server (such as tomcat),
there will be a single resource for the whole JVM. The application server can
host multiple independent applications. There is currently no way to distinguish
between these, other than with the generic HTTP attributes like
Copy link
Member

@jack-berg jack-berg Mar 12, 2026

Choose a reason for hiding this comment

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

I think this is the wrong example because we have another OTEP #4665 which targets this same use case.

The classic example of the value of this feature for me is a service serving multi tenant traffic:

  • Every request is associated with a tenant, which is resolved from something like a header, access token, standard request param, etc
  • The same service handles requests for many many tenants. Its not like the application server example with one application per tenant, with maybe tens of distinct applications. It could be thousands, tens of thousands, or more running through a single application.
  • Its critical that some or all telemetry be associated with this telemetry. I.e. metrics, logs, and traces, and from a variety of different scopes recording instrumentation.

With something like the java agent, its not possible to modify all the instrumentation needed to capture this tenant information. You could put it into a custom context key, and write a custom log record processor, custom span processor to extract it from context and stamp it onto spans and logs, but what about metrics? Also, since this is a common requirement, why don't we make it easy instead of requiring users to build a bunch of custom machinery to accomplish it?

^^ Just giving ideas about an alternative example you could use.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestions. Re-massaged the section, including a pair of new paragraphs with this information.

is executed in is lost in any child spans that may occur within the function (app).

There is also the issue
[open-telemetry/opentelemetry-specification#1089](https://github.com/open-telemetry/opentelemetry-specification/issues/1089)
Copy link
Member

Choose a reason for hiding this comment

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

FYI, this issue is solved. Currently, my read is that the text implies that this is an open problem. Despite being solved, its probably still relevant and maybe a part of the solution. I.e. perhaps we define built in processors to make it easy to life context scoped attributes onto telemetry. The span processor would be able to leverage BeforeEnd.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, good point. I moved to the prior art section (IMHO it could be useful for people but not as crucial as before).

signals emitted within a Context. Context-scoped attributes are standard
attributes, which means you can use strings, integers, floating point numbers,
booleans or arrays thereof, just like for any telemetry item.
Context-scoped attributes MUST be added to telemetry items that were **emitted**
Copy link
Member

Choose a reason for hiding this comment

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

this MUST here somewhat conflicts with the "MUST be disabled by default" later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants