[Opentelemetry] Prevent OTLP array attribute stack overflow on cyclic/deep arrays#8707
Conversation
BenchmarksBenchmark execution time: 2026-05-29 20:59:33 Comparing candidate commit a196e92 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 72 metrics, 0 unstable metrics, 60 known flaky benchmarks, 66 flaky benchmarks without significant changes.
|
This comment has been minimized.
This comment has been minimized.
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! ℹ️ 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". |
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (8707) 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 (8707) - mean (75ms) : 71, 79
master - mean (75ms) : 71, 79
section Bailout
This PR (8707) - mean (77ms) : 75, 80
master - mean (77ms) : 76, 79
section CallTarget+Inlining+NGEN
This PR (8707) - mean (1,111ms) : 1056, 1167
master - mean (1,111ms) : 1054, 1169
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 (8707) - mean (115ms) : 110, 120
master - mean (116ms) : 111, 121
section Bailout
This PR (8707) - mean (116ms) : 113, 119
master - mean (115ms) : 111, 119
section CallTarget+Inlining+NGEN
This PR (8707) - mean (796ms) : 764, 828
master - mean (795ms) : 772, 818
FakeDbCommand (.NET 6)gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8707) - mean (103ms) : 99, 107
master - mean (105ms) : 99, 111
section Bailout
This PR (8707) - mean (103ms) : 99, 106
master - mean (105ms) : 100, 110
section CallTarget+Inlining+NGEN
This PR (8707) - mean (955ms) : 910, 999
master - mean (960ms) : 918, 1002
FakeDbCommand (.NET 8)gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8707) - mean (103ms) : 97, 108
master - mean (101ms) : 96, 106
section Bailout
This PR (8707) - mean (102ms) : 98, 105
master - mean (105ms) : 99, 110
section CallTarget+Inlining+NGEN
This PR (8707) - mean (825ms) : 782, 869
master - mean (822ms) : 785, 858
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 (8707) - mean (198ms) : 190, 206
master - mean (199ms) : 191, 207
section Bailout
This PR (8707) - mean (201ms) : 194, 209
master - mean (201ms) : 195, 207
section CallTarget+Inlining+NGEN
This PR (8707) - mean (1,198ms) : 1155, 1242
master - mean (1,197ms) : 1158, 1236
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 (8707) - mean (287ms) : 279, 294
master - mean (286ms) : 279, 294
section Bailout
This PR (8707) - mean (288ms) : 281, 295
master - mean (286ms) : 279, 294
section CallTarget+Inlining+NGEN
This PR (8707) - mean (962ms) : 944, 980
master - mean (961ms) : 943, 980
HttpMessageHandler (.NET 6)gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8707) - mean (278ms) : 272, 284
master - mean (278ms) : 270, 287
section Bailout
This PR (8707) - mean (278ms) : 272, 284
master - mean (278ms) : 273, 284
section CallTarget+Inlining+NGEN
This PR (8707) - mean (1,157ms) : 1119, 1194
master - mean (1,155ms) : 1110, 1200
HttpMessageHandler (.NET 8)gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (8707) - mean (276ms) : 269, 283
master - mean (278ms) : 271, 286
section Bailout
This PR (8707) - mean (277ms) : 269, 285
master - mean (279ms) : 272, 285
section CallTarget+Inlining+NGEN
This PR (8707) - mean (1,039ms) : 990, 1087
master - mean (1,038ms) : 995, 1080
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
andrewlock
left a comment
There was a problem hiding this comment.
Agree with the other comments here - good in principal, but
- We can probably remove the duplication by adding an
expandArraysargument - We should let
ulongfall through to being astring
bouwkast
left a comment
There was a problem hiding this comment.
Thanks! I think the snapshots need to be updated (probably just the command to download them as it is the linux integration tests). They look right to me so I think just a UpdateSnapshotsFromBuild --build-id 202498 (I think)
"stringValue": "System.String[]"
instead of
"stringValue": "arr1_val1"
Snapshots difference summaryThe following differences have been observed in committed snapshots. It is meant to help the reviewer. 2 occurrences of : - "arrayValue": {
- "values": [
- {
- "stringValue": "arr1_val1"
- }
- ]
- }
+ "stringValue": "System.String[]"
[...]
- "arrayValue": {
- "values": [
- {
- "stringValue": "arr2_val1"
- }
- ]
- }
+ "stringValue": "System.String[]"
|
Summary of changes
Both OTLP trace serializers (
OtlpTracesProtobufSerializerandOtlpTracesJsonSerializer) now serialize eachAnyValuearray element by callingWriteAnyValuewithexpandArrays: falseinstead of recursing with array expansion enabled. Adds regression tests covering self-referential, deeply nested, nestedobject[], and nestedbyte[]inputs in both serializers.Reason for change
WriteAnyValuetakes a newbool expandArraysparameter (defaulttrue). Whenfalse— the value passed for each array element — thebyte[]andArraycasesgoto default;and stringify viaConvert.ToString(value, CultureInfo.InvariantCulture)instead of recursing. This caps recursion depth at 1 by construction (no cycle tracker or depth limit needed) and mirrors OTel .NET SDK'sTagWriter.WriteToArrayTypeChecked, whose per-element writer also has nobyte[]/Arraycase. Top-level dispatch is unchanged, so only nested-array semantics shift and the shift aligns dd-trace's output with the OTel SDK. Also splitsulongout of the JSON integer cases so it stringifies (it overflows OTLPintValue/int64), matching the protobuf serializer and the OTel SDK.Implementation details
WriteAnyValuetakes a newbool expandArraysparameter (defaulttrue). Whenfalse— the value passed for each array element — thebyte[]andArraycasesgoto default;and stringify viaConvert.ToString(value, CultureInfo.InvariantCulture)instead of recursing. This caps recursion depth at 1 by construction (no cycle tracker or depth limit needed) and mirrors OTel .NET SDK'sTagWriter.WriteToArrayTypeChecked, whose per-element writer also has nobyte[]/Arraycase. Top-level dispatch is unchanged, so only nested-array semantics shift and the shift aligns dd-trace's output with the OTel SDK. Also splitsulongout of the JSON integer cases so it stringifies (it overflows OTLPintValue/int64), matching the protobuf serializer and the OTel SDK.Test coverage
Four regression tests per serializer:
SelfReferentialObjectArray_IsBoundedAtOneLevel(a[0] = ano longer recurses),DeeplyNestedArray_IsBoundedAtOneLevel(5 000-deep array serializes in constant stack),NestedObjectArray_StringifiesInsteadOfArrayValue, andNestedByteArray_StringifiesInsteadOfBytesValue, plus a JSONWriteAnyValue_Ulong_EmitsStringValuetest for theulongchange. All existing flat-array tests and theOpenTelemetrySdkTests.SubmitsOtlpTracesintegration test pass unchanged.