RUM-16886: Mark sampled-out network spans as droppable while preserving stats#3596
RUM-16886: Mark sampled-out network spans as droppable while preserving stats#3596abrooksv wants to merge 1 commit into
Conversation
3f00c72 to
f51c50e
Compare
|
@codex review this |
f51c50e to
e2c6a81
Compare
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feature/client-side-stats #3596 +/- ##
=============================================================
+ Coverage 73.31% 73.34% +0.03%
=============================================================
Files 986 986
Lines 35981 36011 +30
Branches 6068 6068
=============================================================
+ Hits 26376 26409 +33
- Misses 7921 7922 +1
+ Partials 1684 1680 -4
🚀 New features to boost your workflow:
|
…ng stats CoreTracer needs to see all spans to calculate APM client-side stats. Since network spans have their own sampling rate, sampled-out spans are now finished with the `_dd.local.force_drop` tag instead of being dropped. This tells downstream systems to discard the span while still letting CoreTracer process it for stats calculations. This only applies when the active tracer is the SDK's own `DatadogTracerAdapter`, which routes through `CoreTraceWriter` — the only implementation that honors `_dd.local.force_drop`. When a custom or global `DatadogTracer` is in use, sampled-out spans are dropped via `drop()` as before, preserving backward compatibility.
e2c6a81 to
5410db4
Compare
satween
left a comment
There was a problem hiding this comment.
Left few comments.
isSDKBacked is a bit confusing if someone would look at it without the all context of the feture, so maybe change it into something like isDefaultTracer or isDropingSpanWithTags or something like this
| * Internal tag which indicates the span should be created locally but never sent to the backend. | ||
| */ | ||
| @InternalApi | ||
| const val FORCE_DROP_SPAN: String = "_dd.local.force_drop" |
There was a problem hiding this comment.
Not sure I follow, it is a const?
| internal fun DatadogSpan.finishRumAware(isSampled: Boolean, canSendSpan: Boolean) { | ||
| if (canSendSpan && isSampled) { | ||
| internal fun DatadogSpan.finishRumAware(isSampled: Boolean, canSendSpan: Boolean, isSDKBacked: Boolean) { | ||
| if (canSendSpan && (isSDKBacked || isSampled)) { |
There was a problem hiding this comment.
it's hard to understand that complex boolean combination.
maybe could be simplified?
when {
!canSendSpan -> drop()
isSDKBacked && !sSampled -> {
setTag(FORCE_DROP_SPAN, true)
finish()
}
else -> dtop()
}
Not sure if the code does the same, but flattening it a bit will make it more readable."
| val span: DatadogSpan? = null, | ||
| val sampleRate: Float? = null | ||
| val sampleRate: Float? = null, | ||
| val isSDKBacked: Boolean |
There was a problem hiding this comment.
maybe isDefaultTracer bit better name for this var ?
There was a problem hiding this comment.
Yep, that is much better :D
| // THEN | ||
| verifyNoInteractions(mockEventBatchWriter) | ||
|
|
||
| ddSpans.forEach { it.finish() } |
There was a problem hiding this comment.
this is wired line:
If this is an assertion and you've expected for example that there is no exception thrown - it's better to wrap into assertNotThrowing or something similar.
If this code tries to free up resources - this is the wrong way to do so as if test fails on the lines above - this line won't be executed
There was a problem hiding this comment.
A few of the tests in this file have that and I am not sure why, they don't look to serve a purpose to me given they are Forge generated spans
| // Then | ||
| if (fakeIsSampled) verify(mockSpan).finish() else verify(mockSpan).drop() | ||
| if (fakeIsSampled) { | ||
| verify(mockSpan, never()).setTag(FORCE_DROP_SPAN, true) |
There was a problem hiding this comment.
verify(mockSpan, never()).setTag(eq(FORCE_DROP_SPAN), any())
| // Then | ||
| if (fakeIsSampled) verify(mockSpan).finish() else verify(mockSpan).drop() | ||
| if (fakeIsSampled) { | ||
| verify(mockSpan, never()).setTag(FORCE_DROP_SPAN, true) |
| private fun DatadogSpan.finishRumAware(isSampled: Boolean) { | ||
| if (canSendSpan()) { | ||
| if (isSampled) finish() else drop() | ||
| private fun DatadogSpan.finishRumAware(isSampled: Boolean, isSDKBacked: Boolean) { |
There was a problem hiding this comment.
same here for the complex if-else logic. Maybe worth to move it somewhere into DatadogSpanExt extensions?
There was a problem hiding this comment.
Ya, its the logic in ApmNetworkInstrumentationExt.kt but that is not visible to the feature/okhttp
Is it worth taking internal off that one and sharing it?
What does this PR do?
CoreTracer needs to see all spans to calculate APM client-side stats. Since network spans have their own sampling rate, sampled-out spans are now finished with the
_dd.local.force_droptag instead of being dropped. This tells downstream systems to discard the span while still letting CoreTracer process it for stats calculations.This only applies when the active tracer is the SDK's own
DatadogTracerAdapter, which routes throughCoreTraceWriter— the only implementation that honours_dd.local.force_drop. When a custom or globalDatadogTraceris in use, sampled-out spans are dropped viadrop()as before, preserving backward compatibility.Note: Some of this can be cleaned up if we drop OpenTrace and move the OKHttp feature to use the new ApmNetworkInstrumentation in V4
Motivation
Allows us to capture APM metrics for traces that are sampled out at the request level
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)