-
Notifications
You must be signed in to change notification settings - Fork 344
Deprecate or remove ScopeManager.active()
#267
Comments
Hey @adriancole thanks for the feedback. I think that's a very valid point, and the important question here is whether there is a pattern that requires the Will think some though on it and try to cook some examples (both a) the need for the current design, if any, and b) the problem of exposing it in @yurishkuro @pavolloffay @tylerbenson may have some thoughts on it too ;) |
I need E.g. .NET has its own OpenTracing "span"-like construct called If I only had access to |
Hey @cwe1ss thanks for the feedback, definitely appreaciated ;) Sounds like we should cook such example for the
If we decide to keep this API, then we need to stress this point, definitely, so we avoid unintended problems for the users ;) |
I'm probably missing something, but I don't understand the problem with that method... Why wouldn't you want a way to get the current scope from the ScopeManager? How would you get it otherwise except from where it was originally created? In fact, we use it in a fair bit of our instrumentation. When writing instrumentation, it is often useful to know if there is a current active span. We also have additional logic on our scope that wouldn't be as nice to have on the span. I suggest leaving it as is. |
I understand @adriancole concern's: The current API is useful when there are no "attributes" where the Scope could be stored.
I have submitted fix for it openzipkin-contrib/brave-opentracing#83 (if there is an agreement to fix it) |
I completely disagree especially in Java about having to retain a lookup table for scope references. this adds debt which turns to permanent debt once you go v1. can you please show any prior art which does this and why it should be done here? for example knowing there is a current span is different than having a reference to close a scope (especially from another thread!) can you please engage some language experts if you desire to do this anyway? |
After discussing with Adrian in a side channel, I am ok with his proposal to have the return type change. I still think there should be a way to tell if there is an active trace currently happening, so if that is a method that returns the span or the span context and that result being null means no trace, then I guess that will work. |
My problem with the This makes it impossible to integrate it into the internal "scope manager" of a tracer, which is agnostic of OpenTracing. The only way to make this work in a bridge is to have a separate scope manager for the bridge. But then you can't get the active span when the span was created using the internal API and not the bridge. In it's current form it's impossible to write a correctly working bridge for So my suggestion would be to remove the |
folks @pavolloffay seems reluctant to fix the instrumentation he made and wants to force brave to implement this dodgy api instead. Can we please get this removed? |
@CodingFabian @raphw are either of you in love with this api that requires implementations to track and try to return scope instances? If you are can you please comment why? If not can you please help get this removed to de-burden implementations? It is worth mentioning that thinking about this problem from a library pov is important. Agents can fix all sorts of misbehavior, but libaries cannot. So, for example, I'm aware that folks using agents might "shrug off" less than ideal apis as they can wrangle them in mysterious ways. Think about this problem in a way where you can't just fix it via bytecode. I think you'll agree we are better off without it. |
I am not sure where in the world you found that I am reluctant to fix this issue in instrumentations opentracing-contrib/java-jaxrs#88. What is sure that you are reluctant to fix this in brave openzipkin-contrib/brave-opentracing#83 (comment) |
@pavolloffay your comment was that existing instrumentation are broken. you wrote the instrumentation leading to that issue. fixing the version <1 instrumentation or fixing the <1 api both sort the problem in ways more sustainable than cementing in the malpractice that exists in the tracer. stop pushing design problems on other repos |
Well there is this spec proposal to give access to span id for example, so implementations need to provide a way to access the instance anyway. |
Hey everybody, So, trying to move on with this topic, after reading the entire thread again, these are my impressions:
I'd say the last point is the important one, which needs to be addressed first, in order to in go in either direction - keep |
Hey everybody, We would like to have a Cross-Language group call on July 13th (next week) and discuss this item as part of it. Please let me know if you guys can make it, specially @adriancole @felixbarny @cwe1ss |
What was the outcome of your call? ps on your point about "Having ScopeManager.active() around can be very helpful when instrumenting libraries that have no context or similar to store the Scope" The main concern is creating an api less likely to lead to problems. The call-sites which have no other means to pass a scope are the "infected" call sites, and take the risk without exposing it (risky stuff) by default to all call sites and consumers. In other words, yes call sites like these using thread locals or a utility like brave has, have a chance of leaking. Just the surface area is much smaller and you can easily tell where that problematic code is, because it isn't.. well everywhere. |
The more I think about this, the more I tend to agree with Adrian. Scope is basically a container for In my humble opinion:
What would absolutely break if active scope was replaced by active span and couldn't be solved otherwise? Background: I made an adapter between my 'general purpose' context propagation mechanism and the OpenTracing ScopeManager and it was non-trivial when to close and not close the scope. |
@adriancole no real conclusions. I addressed the problems with |
Are there any use cases which require to get the |
@felixbarny I think the case @cwe1ss pointed out some time ago still stands:
|
Hey @sjoerdtalsma
I think this could be easily 'enforced' by indeed not exposing
So this is something that could be tried with some experimental API. We could need to think how to handle the separation between activation and lifetime in |
@adriancole Sounds like the point of your request? Remove active |
I'm not sure why there is a concept of removing active scope in favor of span.. why this is somehow experimental. This was in use in brave and also census for quite a long time. Retrieving the scope is the thing that causes issues. As mentioned in the initial description ScopeManager.activeSpan or similar is fine by me. I don't know why there is cause to stall something like this with a testbed notion, but as it is already stalled for a while if you feel you need to test the idea of only returning active span, be my guest! |
Hey @adriancole
So, if I understood correctly, you would like So the Nevertheless, I can definitely help with that as needed. |
@carlosalberto so this is still an issue.. I can see you last explained yourself are you waiting for me or someone to say go? I just recently had to do a lot of work to avoid holding up classloaders due to scenarios such as this issue. If you are planning to address this, can you go ahead and proceed? Thanks. |
Hey @adriancole Sorry, had been busy doing other work ;) So the plan is to work tomorrow on updating the PR for #291 and have something ready for testing soon. |
so far my experience with opentracing in Java has been somewhat less than stellar particularly around this api and in particular the decision to track scopes with threadlocals. Due to heavy use of executor pools and async things I've found out of the box scope management causes many mem leaks in my case. So in some cases where I know I'm in the same thread but just want to hand over context without polluting my code, I've been trialing creating an activeSpan and then immediately closing in the callee but leaving the span open - using the threadlocal in managed short bursts. this however requires great care and is still likely to come unstuck, but at least the option exists. without scopeManager().active() I couldnt do that. |
Do you have a suggestion for a better alternative? |
@yurishkuro I'm not sure tbh, and certainly don't have any good answer. I've tracked my own tracing contexts in a singleton trie model, using keys that make sense available in my application to find the active span or parent in any given circumstance. I think I might try to instrument the returned futures from the various executors and services and attempt to track the start and end of each future to maintain the tracing that way instead of code scattered everywhere. carrying the context across method calls etc if there is nothing useful to hook is very problematic though and so far the only options I can think of are all very invasive except for the threadlocal in short bursts to carry the context where I'm sure its not jumping threads. |
Not sure I follow. A central cache (your trie) is of no help unless you explicitly propagate those IDs. The point of threadlocals is that you don't pass anything between functions yet preserve the context. Take spring boot - by adding a few jars to the classpath you can get your application traced with zero code changes. I'm not aware of any technique that can do that without threadlocals or relying on some bespoke, already explicitly propagated IDs. |
I'm using spring boot, but adding a few jars to my context does not get my application traced. it gets it broken with metaspace memory leaks, and closing spans too soon. the issue is that there are executors starting services and the implementations of tracingexecutorservices assume that when the Runnable/Callable ends is when the tracing ends which just isnt always the case. the executing task might hand off to other threads several times, and invoke many other async tasks before it should terminate a span. They need to track the returned Future (if submit is called) and be very careful about the likely reuse of the same thread in a different context. |
As far as I can tell, the recent discussion is different than the "let's remove scope tracking from scope manager". Basically, @jeacott1 discusses the usual concerns about tracking futures or async work, that some work spans multiple runnables etc. This is important to understand, and why for example in zipkin we started an advanced instrumentation wiki. OTOH, it seems to me if anything an argument to remove the scope tracking requirement as it still doesn't serve the use case discussed! IOTW, can we please proceed in removing scope tracking as it has known problems, complicates scope manager and introduces error cases such as stacking and/or what happens when it is redundantly executed etc. |
If people are looking for alternatives, composition is the better answer as call sites where you need to share a thread scope are possible to coordinate within the framework that is scheduling work. For example, a ThreadLocal can be used to stash a reference between callbacks, which is more explicit and also doesn't move the responsibility to something that might not even use thread locals (scope manager!). In brave, we introduced a utility ThreadLocalSpan which eliminated most cases where you need to do repetitive work https://github.com/openzipkin/brave/blob/3be55b5cccf881104bdd80c93e97d2575b83952d/brave/README.md#working-with-callbacks That isn't to say special utilities for stream composition or executors don't need other approaches, it is to say that composition, especially bound to the utility in question, is the better answer vs forcing this concern on all scope implementations, especially knowing how many problems this causes. TLDR please let's delete this! |
fwiw anything that leans on the fork-join pool will be broken by any method that's trying to use threadlocals, and more and more I find myself using Quasar or Kotlin coroutines neither of which work out of the box (or at all) with stock threadlocals. So in the end I'm not using the ScopeManager.active() at all as it just wasn't necessary or useful
|
I am convinced by the arguments that I am not sure about @cwe1ss 's #267 (comment), as I am not that familiar with C#. The code example he provided certainly looks like an unintended API usage: creating a scope and throwing it away, then relying on active() to retrieve it. The Activity looks very much like a Span, with its own unique IDs, so it feels odd that spans are created in parallel with that. In any case, we don't need to block a decision about Java API based on the needs of C# API. Also agree with @adriancole that @jeacott1 's issue is unrelated to this ticket - if you propagate context manually/explicitly, you have no need for "active span". Creating a scope via activate() and immediately closing it is effectively no-op (+ gc noise), unless you're using some funky scope manager impl. I |
@yurishkuro "Creating a scope via activate() and immediately closing it is effectively no-op" - agreed, except that in the current setup if you dont do that you arent closing the right thing. close only closes the right thing if its also active - somewhere in the docs it says that and it tripped me up initially. |
Hey all,
I think we forgot to add a test case to showcase Christian's case (comment). But the rest of the Given the feedback, I'm wondering how often the aforementioned case shows up in real life (this case has been, historically, the reason to keep Opinion on this @opentracing/opentracing-java-maintainers @CodingFabian @tylerbenson ? |
I am ok deprecating->removing |
ScopeManager.active
is documented as a feature used to get the current span. Perhaps it is a relic from the previous design. It tempts people to call close on it eventhough ScopeManager is pretty clear that scopes should be managed directly.I would remove this api, possibly for
ScopeManager.activeSpan
if that's the intended use case to serve. Otherwise, please clarify the documentation that calls to close are undefined.If folks are doing things like subclassing, you can deprecate the api, and they can still offer "advanced" things as they exist today as their subtype would still be able to offer that functionality regardless of it it exists on a supertype.
openzipkin-contrib/brave-opentracing#74 (comment)
The text was updated successfully, but these errors were encountered: