-
Notifications
You must be signed in to change notification settings - Fork 345
ThreadLocalScopeManager should be extensible #334
Comments
Also relates to opentracing-contrib/java-spring-cloud#92 |
FYI, I have identified a need for a similar concept in my context-propagation library: |
I strongly favor the listener option, but I think there should be a onActivate/onDeactivate or onStart/onStop (or some other matching terminology) pair. |
Scope: onActivate / onDeactivate ? |
I'd also vote to add an event listener layer, as it feels to me as the cleanest option ;) |
@tylerbenson I was thinking about that, problem is, that as long as its single method interface, its easily usable as lambda :) onActivate/onDeactivate is probably cleanest. But again, for primary use-case, it is actually harmful to handle onDeactivate, when scope changes (e.g. for child span), since all MDC/ThreadContext internal structures are immutable, and any change causes clone of the internal HashMap. And for such listener, you cannot distinguish, whether you are leaving outer scope, or just changing it. And calling onDeactivate for only outer scope seems wrong to me. So, single callback looks most versatile, while not the cleanest. @sjoerdtalsma This is about scopes only. Lifecycle of spans is far more complex and outside power of the |
Agree, I think is misinterpreted the comment from @carlosalberto 😉.. @mdvorak Have you looked at the interface I use for observing? It passes both the activated / deactivated value and the previous / reactivated value. Maybe that could be of use? 🤷♂️ shameless plug:
|
@sjoerdtalsma Well, I think your implementation is a bit too complex for the goal I wanted to achieve. I was more thinking about something like this: Also, from
So separate handling, which avoid calling finish twice, should not be necessary. |
@mdvorak interesting insight regarding:
I was not aware of that. That makes sense then why you'd want to reduce thrashing and limit it to just the changes. I assume in the case where the root scope is being closed, you'd pass in |
My preference is for symmetric onActivate/onClose. The latter can be used, for example, to track how much time the span was "runnable" on a given thread. |
That is not actually a bad idea, dunno why it did not occur to me. This aproach does not enforce unnecessary MDC modifications, yet it provides strong contract. Passing null on deactivating is a bit ugly. But still great for simple lambda handler :) |
@yurishkuro What about |
Isn't it deprecated? |
Not in code, neither in master or v0.32.0: https://github.com/opentracing/opentracing-java/blob/master/opentracing-util/src/main/java/io/opentracing/util/AutoFinishScopeManager.java#L21 |
@carlosalberto do we still need AutoFinishScopeManager.java ? |
@yurishkuro It was added as an experimental/esoteric feature, but given the latest changes, guess we can deprecate it (and if any continuation-based framework like Akka needs it, they can either have their own). Long story short: we should deprecate it, yes. |
Implementation of ScopeManager based on our own AbstractThreadLocalContext class with the following advantages over the 'standard' opentracing-util ThreadLocalScopeManager: 1. Close is explicitly idempotent; closing more than once has no additional side-effects (even when finishOnClose is set to true). 2. More predictable behaviour for out-of-order closing of scopes. Although this is explicitly unsupported by the opentracing specification, we think having consistent and predictable behaviour is an advantage. 3. Support for {@link nl.talsmasoftware.context.observer.ContextObserver}. See opentracing/opentracing-java#334 why this is an advantage.
Implementation of ScopeManager based on our own AbstractThreadLocalContext class with the following advantages over the 'standard' opentracing-util ThreadLocalScopeManager: 1. Close is explicitly idempotent; closing more than once has no additional side-effects (even when finishOnClose is set to true). 2. More predictable behaviour for out-of-order closing of scopes. Although this is explicitly unsupported by the opentracing specification, we think having consistent and predictable behaviour is an advantage. 3. Support for {@link nl.talsmasoftware.context.observer.ContextObserver}. See opentracing/opentracing-java#334 why this is an advantage. Signed-off-by: Sjoerd Talsma <[email protected]>
Adding custom behavior for activating and deactivating scope is real pain - one have to copy
ThreadLocalScopeManager
andThreadLocalScope
into project and modify them.It is because while
activate
can be overriden byScopeManager
, the actual deactivation happens inThreadLocalScope.close()
and is conditional. Even wrappingThreadLocalScope
and hooking toclose()
won't work. Thus, copy-paste it is.Main use-case here is setting
MDC
context. Even with 0.32 and exposed spanId and traceId, there is no straightforward way to set those to MDC (unless I'm oblivious to something). While setting always MDC is a little opinionated and can be part of more automated libraries like for Spring (as stated in #202), ot-java should provide extension point for both apps and libraries to do that with ease.Now, I'll prepare PR, just pick a solution :)
1) Replace calls to
ThreadLocalScopeManager.tlsScope.set()
inThreadLocalScope
with protected method inThreadLocalScopeManager
:This has least impact on current code, but exposes class internals. Question is, whether it is actually an issue.
2) Similar to 1), but add listener to
ThreadLocalScopeManager
instead of protected setter, to allow composition over inheritance:Whenever
ThreadLocalScope
callsscopeManager.tlsScope.set()
, it also callsscopeManager.listener.onActiveSpanChanged
.3) Create some more sophisticated and complex observer system. Problem with above solutions is, that
AutoFinishScopeManager
could have exactly same logic. Is it worth adding complex structures to avoid little code duplication?Also question is, what are actually plans with
AutoFinishScopeManager
, since it couples app code with specific configuration, and the implementation itself is error-prone IMO (leaking spans, not closing spans).I prefer solution 2), as it allows very simple use in Java8+. Example for Jaeger and Log4j2:
The text was updated successfully, but these errors were encountered: