-
-
Notifications
You must be signed in to change notification settings - Fork 444
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
Feat: Add tracestate
HTTP header support.
#1683
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1683 +/- ##
============================================
- Coverage 75.93% 74.82% -1.11%
- Complexity 2025 2078 +53
============================================
Files 207 210 +3
Lines 7060 7428 +368
Branches 699 782 +83
============================================
+ Hits 5361 5558 +197
- Misses 1361 1488 +127
- Partials 338 382 +44
Continue to review full report at Codecov.
|
sentry/src/main/java/io/sentry/SentryEnvelopeHeaderAdapter.java
Outdated
Show resolved
Hide resolved
ps: important to test the serialization and deserialization of an envelope without such information and guarantee that nothing is broken since users that do offline caching might experience the broken behavior, if any |
To ensure that the state header for a transaction does not change once its calculated once, I moved computing the header from capturing transaction/event, to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make it opt-in, aligning with option named here: https://develop.sentry.dev/sdk/trace-context/
Please please add a huge javadoc to the option that this is experimental and will be removed without notice.
@marandaneto before merging this could you help @maciejwalkowiak test the OkHttp bit? He'll setup the sentry-sdks org, sentry-java repo with some rules and we can test things out: https://sentry.io/settings/sentry-sdks/projects/sentry-java/filters-and-sampling/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple notes but lets merge and make a release of this please.
Lets make a beta first please
if (hub.getOptions().isTraceSampling()) { | ||
if (traceState == null) { | ||
final AtomicReference<User> userAtomicReference = new AtomicReference<>(); | ||
hub.configureScope( | ||
scope -> { | ||
userAtomicReference.set(scope.getUser()); | ||
}); | ||
this.traceState = new TraceState(this, userAtomicReference.get(), hub.getOptions()); | ||
} | ||
return this.traceState; | ||
} else { | ||
return null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the trace gets passed around to different threads so they can create child spans, this could have concurrent access, right?
If so, what about a double check lock?
if (hub.getOptions().isTraceSampling()) { | |
if (traceState == null) { | |
final AtomicReference<User> userAtomicReference = new AtomicReference<>(); | |
hub.configureScope( | |
scope -> { | |
userAtomicReference.set(scope.getUser()); | |
}); | |
this.traceState = new TraceState(this, userAtomicReference.get(), hub.getOptions()); | |
} | |
return this.traceState; | |
} else { | |
return null; | |
} | |
if (hub.getOptions().isTraceSampling()) { | |
if (traceState == null) { | |
synchronized(this) { | |
if (traceState == null) { | |
final AtomicReference<User> userAtomicReference = new AtomicReference<>(); | |
hub.configureScope( | |
scope -> { | |
userAtomicReference.set(scope.getUser()); | |
}); | |
this.traceState = new TraceState(this, userAtomicReference.get(), hub.getOptions()); | |
} | |
} | |
} | |
} | |
return this.traceState; | |
} else { | |
return null; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
} | ||
|
||
@Override | ||
public @Nullable TraceStateHeader toTraceStateHeader() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since TraceState
has a reference to options
, could we have toTraceStateHeader
be part of TraceState
instead and avoid this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TraceState
does not have a reference to options
. We can put it to a transient field, just somehow does not seem right to me as TraceState
was meant to be just a data container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair point. I'm just trying to find any way not to add these two public methods here but I'm about to lose hope (the PR is approved anyway so)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SentryTracer
is @ApiStatus.Internal
already, so it'd be fine to be there.
@marandaneto we need to ship soon, would you like to give this a pass before we merge? |
@@ -280,6 +280,9 @@ | |||
*/ | |||
private @NotNull RequestSize maxRequestBodySize = RequestSize.NONE; | |||
|
|||
/** Controls if the `tracestate` header is attached to envelopes and HTTP client integrations. */ | |||
private boolean traceSampling; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it disabled by default?
if this is intended for mobile too, let's add the ability to turn it on via Android Manifest
See: ManifestMetadataReader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
public @Nullable TraceState traceState() { | ||
if (hub.getOptions().isTraceSampling()) { | ||
if (traceState == null) { | ||
final AtomicReference<User> userAtomicReference = new AtomicReference<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's about adding a function to the Scope called withUser
like we do with withSession
instead of using AtomicReference
? that executes a callback and returns the user atomically, it could be package private or @ApiStatus.Internal
. not a big fun of AtomicReference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, also didn't like it, but in this PR we need to avoid introducing changes to the API, so i think AtomicReference
as a temporary solution is a right trade off.
📜 Description
Add experimental
tracestate
HTTP header support defined in https://develop.sentry.dev/sdk/performance/trace-context/#client-options.Trace context is added to each envelope containing transaction or an event.
In addition to that,
SentryOkHttpInterceptor
attaches a newtracestate
header to all outgoing requests.By default this feature is off and is controller by a
traceSampling
flag onSentryOptions
. All new API classes or methods are marked as@Experimental
.💚 How did you test it?
Unit & Integration tests. Sending events to
sentry-java
project on insentry-sdks
and verifying if they appear.📝 Checklist