question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ThreadLocalScopeManager should be extensible

See original GitHub issue

Adding custom behavior for activating and deactivating scope is real pain - one have to copy ThreadLocalScopeManager and ThreadLocalScope into project and modify them. It is because while activate can be overriden by ScopeManager, the actual deactivation happens in ThreadLocalScope.close() and is conditional. Even wrapping ThreadLocalScope and hooking to close() 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() in ThreadLocalScope with protected method in ThreadLocalScopeManager:

protected void setThreadScope(ThreadLocalScope scope) {
  this.tlsScope.set(scope);
}

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:

public interface Listener {
    void onActiveSpanChanged(Span span);
}
final Listener listener;

Whenever ThreadLocalScope calls scopeManager.tlsScope.set(), it also calls scopeManager.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:

new JaegerTracer.Builder("sample")
            .withScopeManager(new ThreadLocalScopeManager(this::setThreadContext))
            .build();
// ...
private void setThreadContext(Span span) {
    if (span instanceof JaegerSpan) {
        JaegerSpan jaegerSpan = (JaegerSpan) span;
        ThreadContext.putAll(Map.of(
            "traceId", jaegerSpan.context().getTraceId(),
            "spanId", Long.toHexString(jaegerSpan.context().getSpanId())
        ));
    } else {
        ThreadContext.removeAll(asList("traceId", "spanId"));
    }
}

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:4
  • Comments:16 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
tylerbensoncommented, Mar 12, 2019

I strongly favor the listener option, but I think there should be a onActivate/onDeactivate or onStart/onStop (or some other matching terminology) pair.

0reactions
carlosalbertocommented, Mar 13, 2019

@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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How do you write code that is extensible and maintainable ...
How do you write code that is extensible and maintainable when you don't know what new features and changes will be demanded in...
Read more >
Index (liquibase 4.18.0 API) - javadoc.io
Template class for all types of database objects can be manipulated using ChangeSets. ... AbstractExtensibleObject() - Constructor for class liquibase.
Read more >
AbstractPathResourceAccessor (liquibase 4.18.0 API)
Returns all Resource s at the given path. For many resource accessors (such as a file system), only one resource can exist at...
Read more >
Streams à la carte: Extensible Pipelines with Object Algebras
one needs to use implicits. In our work, we propose a new design and architecture for streaming libraries for Java-like languages, to maximize...
Read more >
EXPOSING A FLEXIBLE, COMPOSABLE & EXTENSIBLE ...
Other users should not see inconsistent data. Maintain encapsulation. ​Client should not make assertion on server implementation. Client consumes a service, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found