-
Notifications
You must be signed in to change notification settings - Fork 845
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
Context usability improvements #1807
Comments
It's the other way round: Context is not in itself related to telemetry, but telemetry uses Context. So I think the code snippet above violates the layering prescribed by the spec. |
I guess that makes sense - in that case context storage will always be separate from |
+1 on removing current span access from tracer. EDIT: It also removes the confusion I have often seen, where users wanted to get access to a particular named tracer because they wanted the current span on that tracer (which is not a thing) |
|
I think that was the whole purpose of open-telemetry/opentelemetry-specification#1019 to remove the confusion and avoid duplicate shortcuts/functionality in one package. Currently after the latest PR @anuraaga merged we have 3 ways to get access to the current Span in the trace package :))) we must go deeper maybe add this to the TracerProvider to not require using a name for the Tracer :))) (joking) |
I've reread #1019 about 10 times now to try to make sure to align with it but unfortunately still have a hard time understanding what it's saying. If the point is OTel must not provide an API to access the current Context, then things get more clear.
Which PR? Can't find adding a new way to access the span. That being said, I think having multiple ways to do the same thing is not automatically a bad thing as long as it provides real value, which tracer.currentSpan wouldn't if it just delegates to a static lookup anyways. If something is useful to users we should do it - any time the spec blocks that, it failed. |
Sorry, is not yet merged #1795
The points are very simple, but had to explain it in a very complicated way, because sometimes I feel simple things are not easy to explain:
Indeed initially I suggested that we should not provide the API to access the CurrentContext, with the idea that if that functionality needs to be injected, we complicate more things than simplify unless we do SPI as we do now and we have a global. Also I was thinking that it can be removed for the moment (because it is just a shortcut) and we can add later when we understand better the CurrentContext. |
Exactly my point, maybe you call "multiple ways to do the same thing" differently than me and you have examples in mind where that can help, but I cannot think of an example where that is good. Maybe I am limiting the definition to just "duplicate code" like the example above, and that's why I think is always bad. |
One way is made private so don't think so. Hope it makes clear we are generally on the same page :) The main point is whether context is owned by OTel or not. For telemetry APIs so far except OC, it was - in that pattern, I think |
+1 for this one. I still feel that, because of how we do things in Java, static all the way is the only way to go. |
So, are we converging on something like this?
This will keep the Tracer a very anemic factory for spans, with just one method on it for creating Span.Builders, but at least this will get us out of TracingContextUtils, which is a giant step in the right direction. Any thoughts on what to do with the Tracer, now that it's nothing but a span factory? I guess the Meter is only an instrument factory, so maybe that parallelism is the right way to go, at least for consistency? |
That looks quite sensible to me. I think we also need Some naming suggestions:
|
I like So, updated: Baggage baggage = Baggage.fromContext()
Scope s = baggage.inContext()
Context withBaggage = baggage.appendToContext(context)
Span span = Span.fromContext()
Scope s = span.inContext()
Context withSpan = span.appendToContext(context) |
I like append even less than add. It suggests that the first item is still there, and it also suggests that there is some ordered list in the context. |
"withContext" doesn't make any sense, though, since you're putting the item into the provided context and returning the updated context. |
Hey @jkwatson
We (very) briefly mentioned the possibility of having |
So you get the the item with the provided Context merged into a new context. To me it makes sense. "a with b" is the same as "b with a" in this case. |
but, you're definitely putting the span/baggage into the context, and not the other way around. If we don't make that clear from the API, users will be confused. |
Which is why I don't like the "with" word. :) |
It wasn't clear to me that there's much appetite to doing that, since you wouldn't do the same with baggage. If we want parallel APIs, then we need to make baggage and spans work the same way. |
Wouldn't it be the 'same' having a static (Not trying to defend this, just trying to get an overview of our options ;) ) |
Possibly, but I'm assuming at this point that the BaggageManager is going away very shortly due to open-telemetry/opentelemetry-specification#1070. |
First, about static methods on Tracer, I do feel strongly that we should not do this because of my original point of
If we can provide all the functionality such users need in the So for methods on a
This has a downside of not having a parallel with
also seems OK mostly since the former is shorter and will likely be the most common for end users. I think I lean towards it with less risk that a user will static-import For inserting span there seems to be less consensus.
Unfortunately, So how about this idea? interface ContextValue {
Context storeInContext(Context context);
}
interface Span extends ContextValue {
default Context storeInContext(Context context);
// Any package private class is fine to hold the key
return context.withValues(PropagatedSpan.SPAN_KEY, this);
}
default Span getContextValue() {
return this;
}
}
interface Context {
Context withValues(ContextValue value) {
return value.storeInContext(this);
}
}
try (Scope ignored = Context.current().withValues(span).makeCurrent()) {
}
// In practice, instrumentation needs a context before creating a span, then new context, almost all the time.
// So usually
Context context = Context.current();
Span span = tracer.spanBuilder().setParent(context).start();
try (Scope ignored = context.withValues(span).makeCurrent()) {
} I think it solves the desire of keeping the context key private to tracing while also giving us an idiomatic Java API where we would usually mutate |
I really like the idea of the Context exposing an interface that makes it easy for it to interact with, across any of the items that need propagation. Your proposal seems pretty good, although I would |
Context is an object that is a global concern in
OpenTelemetry
, while the "current span" is a concept of tracing specifically. I'm hoping we can model this ownership correctly, while also provide users an intuitive way of accessing these objects when they need to.Accessing Context
The
Context
is outside ofOpenTelemetry
and something we use statically to insert telemetry information. So we only expect static access like thisAccessing Span
The active span is only available during tracing. The parallel to the above for a span is
This is very important, since many users don't do any tracing at all, they're just using the agent, or added some library instrumentation. But adding attributes is common -
Span.current
allows them to enrich spans without worry about the concept of tracing itself.Making context / span current
Because the context / span are by definition available if a user needs to make them current, instance methods are convenient
try (Scope ignored = context.makeCurrent())
,try (Scope ignored = span.makeCurrent())
.Adding span to context
The final operation is adding a span to a existing context, which instrumentation authors need. Because we only really expect instrumentation authors to use this,
tracer.addToContext(Span span, Context context)
orspan.addToContext(Context context)
both seem OK.The text was updated successfully, but these errors were encountered: