Add a fixed cutoff for the activity handler reconcilliation loop for OTel#8576
Conversation
zacharycmontoya
left a comment
There was a problem hiding this comment.
LGTM, nice approach here!
BenchmarksBenchmark execution time: 2026-05-06 18:07:46 Comparing candidate commit 708fcf5 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 27 metrics, 0 unstable metrics, 58 known flaky benchmarks, 29 flaky benchmarks without significant changes.
|
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8576) and master. ✅ No regressions detected - check the details below Full Metrics ComparisonFakeDbCommand
HttpMessageHandler
Comparison explanationExecution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:
Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard. Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph). Duration chartsFakeDbCommand (.NET Framework 4.8)gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (75ms) : 71, 80
master - mean (75ms) : 71, 79
section Bailout
This PR (8576) - mean (78ms) : 74, 82
master - mean (78ms) : 75, 80
section CallTarget+Inlining+NGEN
This PR (8576) - mean (1,135ms) : 1094, 1176
master - mean (1,134ms) : 1079, 1190
FakeDbCommand (.NET Core 3.1)gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (114ms) : 110, 117
master - mean (114ms) : 110, 119
section Bailout
This PR (8576) - mean (116ms) : 113, 119
master - mean (118ms) : 112, 124
section CallTarget+Inlining+NGEN
This PR (8576) - mean (813ms) : 785, 840
master - mean (814ms) : 785, 843
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (101ms) : 97, 104
master - mean (102ms) : 99, 106
section Bailout
This PR (8576) - mean (104ms) : 97, 110
master - mean (106ms) : 101, 111
section CallTarget+Inlining+NGEN
This PR (8576) - mean (945ms) : 899, 991
master - mean (950ms) : 914, 986
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (103ms) : 97, 108
master - mean (100ms) : 96, 105
section Bailout
This PR (8576) - mean (102ms) : 100, 105
master - mean (102ms) : 98, 107
section CallTarget+Inlining+NGEN
This PR (8576) - mean (849ms) : 772, 925
master - mean (844ms) : 776, 913
HttpMessageHandler (.NET Framework 4.8)gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (213ms) : 193, 233
master - mean (211ms) : 196, 225
section Bailout
This PR (8576) - mean (216ms) : 199, 233
master - mean (218ms) : 200, 236
section CallTarget+Inlining+NGEN
This PR (8576) - mean (1,317ms) : 1266, 1368
master - mean (1,328ms) : 1257, 1400
HttpMessageHandler (.NET Core 3.1)gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (311ms) : 280, 342
master - mean (314ms) : 272, 356
section Bailout
This PR (8576) - mean (311ms) : 281, 342
master - mean (313ms) : 280, 347
section CallTarget+Inlining+NGEN
This PR (8576) - mean (1,044ms) : 1012, 1075
master - mean (1,054ms) : 1005, 1102
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (302ms) : 274, 331
master - mean (305ms) : 276, 333
section Bailout
This PR (8576) - mean (301ms) : 278, 324
master - mean (304ms) : 277, 331
section CallTarget+Inlining+NGEN
This PR (8576) - mean (1,195ms) : 1151, 1238
master - mean (1,202ms) : 1136, 1267
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8576) - mean (295ms) : 279, 310
master - mean (294ms) : 270, 319
section Bailout
This PR (8576) - mean (294ms) : 275, 314
master - mean (298ms) : 269, 327
section CallTarget+Inlining+NGEN
This PR (8576) - mean (1,098ms) : 996, 1200
master - mean (1,109ms) : 1006, 1211
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Summary of changes
Don't auto-close closed-
ActivityrelatedScopewhich have been closed for < 1 minuteReason for change
In #8549, we moved the "CloseActivitySlow" reconciliation step when an
Activityis closed but we somehow "missed" theStopActivity()call into a background job. We don't have a known mechanism for how that would happen today, and so this seemed reasonable.There's a non-ideal aspect to this in terms of
AsyncLocal<T>and execution context flow, in that we're now closing theScopefrom a background task, that's off the originalasynccontext that created it. This will theoretically mean that theActiveScopeflow doesn't work correctly (needs confirming, but it's plausible).This is mostly "OK" given we don't have a known mechanism where we would hit this path however, we also introduced a race condition, where a given
Activityis closed, and is in the process of callingStopActivity, when our background loop executes. In that case we preemptively close it from the background thread.Implementation details
As a workaround, this PR simply adds a 1 minute cutoff before we start closing the associated
Scope, on the basis that this should be plenty of time for our inline handler to run if it's going to. This isn't ideal, as it's somewhat of a hacky workaround, but then, so is the CloseActivitySlow process anyway 😅The other option is that we move the reconciliation back into the hot path, but that doesn't seem worth the trade off to me, especially as we consider this to be an unknown edge case anyway, and it's more there for safety than anything else.
Test coverage
Added a test to confirm that a "freshly" closed
Activityis ignored, and it's only an "old" closedActivitythat gets sweptOther details
Related to https://datadoghq.atlassian.net/browse/APMS-19316.