Skip to content
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

Adds BaggageThreadLocalAccessor #508

Merged
merged 5 commits into from
Jan 11, 2024

Conversation

marcingrzejszczak
Copy link
Contributor

@marcingrzejszczak marcingrzejszczak commented Jan 4, 2024

previously we've tried to store both baggage and span through TracingObservationHandler. That didn't hold when working with reactive applications because it would require users to create artificial baggage scopes and actually due to scopes getting closed early, we would lose the actual baggage value on the attached TraceContext.

with this change we revert to previous approach where the TOH actually creates a scope for spans only. For context propagation we are treating baggage as a first class citizen that requires its own ThreadLocalAccessor, that's why we create the BaggageThreadLocalAccessor, that should be registered after the ObservationAwareSpanThreadLocalAccessor. With that, in reactive applications, under the BaggageThreadLocalAccessor#KEY users will need to register the BaggageToPropagate in e.g. Reactor Context and then it's up to the Context Propagation library to start and stop scopes.

Additional tasks:

  • BraveBaggageManager can have the Micrometer Tracer set on it
  • BraveTracer automatically sets itself on BBM
  • Current Span will now be resolved from the MT if possible

Related issue - #504
Usage example

previously we've tried to store both baggage and span through TracingObservationHandler. That didn't hold when working with reactive applications because it would require users to create artificial baggage scopes and actually due to scopes getting closed early, we would lose the actual baggage value on the attached TraceContext.

with this change we revert to previous approach where the TOH actually creates a scope for spans only. For context propagation we are treating baggage as a first class citizen that requires its own ThreadLocalAccessor, that's why we create the BaggageThreadLocalAccessor, that should be registered after the ObservationAwareSpanThreadLocalAccessor. With that, in reactive applications, under the BaggageThreadLocalAccessor#KEY users will need to register the BaggageToPropagate in e.g. Reactor Context and then it's up to the Context Propagation library to start and stop scopes.

Additional tasks:

* BraveBaggageManager can have the Micrometer Tracer set on it
** BraveTracer automatically sets itself on BBM
** Current Span will now be resolved from the MT if possible
Copy link
Contributor

@chemicL chemicL left a comment

Choose a reason for hiding this comment

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

I'm a bit blurry on the situation where traceContext is empty for BaggageInScope, so I just expressed this in some questions. In general this effort looks good, time to add some tests :) Also, are there no changes required in the OTEL counterpart?

@@ -214,6 +179,9 @@ public void restore(Span previousValue) {

@Override
public void restore() {
if (log.isTraceEnabled()) {
log.trace("Restoring no args");
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider "restoring to empty span scope"

@@ -226,21 +194,26 @@ static class SpanAction implements Closeable {

final Map<Thread, SpanAction> todo;

Consumer<?> scope;
Closeable scope;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there any arguments against using AutoCloseable instead?

private final Map<String, String> baggage;

public BaggageToPropagate(Map<String, String> baggage) {
this.baggage = baggage;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be a reference assignment or a copy? Please see my other comment in BaggageThreadLocalAccessor.

log.trace("Current baggage in thread local [" + baggageInScope.get(Thread.currentThread())
+ "], current baggage from tracer [" + baggage + "]");
}
return (baggage == null || baggage.isEmpty()) ? null : new BaggageToPropagate(baggage);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit concerned about the isEmpty() check. I can imagine a situation where even though the map is empty, it can be filled in later, which won't be reflected. That sounds ok, but at the same time, currently, a non-empty map can become empty later and with a reference used will make the contents be reflected in the captured BaggageToPropagate. This should be consistent. Most probably by just copying the contents in the constructor of the holder.


@Override
public void setValue(BaggageToPropagate value) {
BaggageAndScope previousConsumer = baggageInScope.get(Thread.currentThread());
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the name consumer used here?

public void setValue() {
BaggageAndScope previousConsumer = baggageInScope.get(Thread.currentThread());
if (log.isTraceEnabled()) {
log.trace("setValue no args, current baggage scope [" + baggageInScope.get(Thread.currentThread()) + "]");
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider "setValue to empty baggage scope ..."

@Override
public void restore() {
if (log.isTraceEnabled()) {
log.trace("Calling restore()");
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider "restoring to empty baggage scope"

@@ -44,6 +44,9 @@ public BraveTracer(brave.Tracer tracer, CurrentTraceContext context, BaggageMana
this.tracer = tracer;
this.braveBaggageManager = braveBaggageManager;
this.currentTraceContext = context;
if (braveBaggageManager instanceof BraveBaggageManager) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If it's not a BraveBaggageManager, isn't it an error? Should the previous assignment still be executed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Theoretically a user can provide their own baggage manager. Practically there are almost zero chances that this would happen

this.delegate.updateValue(value);
boolean success = this.delegate.updateValue(value);
if (logger.isTraceEnabled()) {
logger.trace("Managed to update the baggage on set [" + success + "]");
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be beneficial to distinguish the log from the situation where a traceContext is present?

@marcingrzejszczak marcingrzejszczak force-pushed the baggage_thread_local_accessor branch 3 times, most recently from ef4d9fc to 967ca1b Compare January 9, 2024 14:13
@marcingrzejszczak marcingrzejszczak marked this pull request as ready for review January 9, 2024 16:40
@marcingrzejszczak marcingrzejszczak merged commit 3508fcc into 1.2.x Jan 11, 2024
6 checks passed
@marcingrzejszczak marcingrzejszczak deleted the baggage_thread_local_accessor branch January 11, 2024 11:52
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