-
Notifications
You must be signed in to change notification settings - Fork 150
[OTEL] Metrics API Support - Configurations & Telemetry #7420
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
Conversation
Signed-off-by: Maximo Bautista <[email protected]>
Signed-off-by: Maximo Bautista <[email protected]>
Signed-off-by: Maximo Bautista <[email protected]>
Signed-off-by: Maximo Bautista <[email protected]>
df4a8f7 to
1748358
Compare
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing the following branches/commits: Execution-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 shown 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). gantt
title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (71ms) : 71, 72
. : milestone, 71,
master - mean (72ms) : 71, 73
. : milestone, 72,
section Baseline
This PR (7420) - mean (69ms) : 64, 74
. : milestone, 69,
master - mean (69ms) : 63, 75
. : milestone, 69,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (992ms) : 968, 1016
. : milestone, 992,
master - mean (991ms) : 961, 1020
. : milestone, 991,
gantt
title Execution time (ms) FakeDbCommand (.NET Core 3.1)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (107ms) : 105, 108
. : milestone, 107,
master - mean (106ms) : 105, 107
. : milestone, 106,
section Baseline
This PR (7420) - mean (105ms) : 103, 108
. : milestone, 105,
master - mean (105ms) : 103, 107
. : milestone, 105,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (702ms) : 682, 721
. : milestone, 702,
master - mean (698ms) : 678, 718
. : milestone, 698,
gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (94ms) : 92, 95
. : milestone, 94,
master - mean (94ms) : 93, 95
. : milestone, 94,
section Baseline
This PR (7420) - mean (93ms) : 91, 95
. : milestone, 93,
master - mean (93ms) : 91, 95
. : milestone, 93,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (662ms) : 642, 682
. : milestone, 662,
master - mean (652ms) : 635, 669
. : milestone, 652,
gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (93ms) : 91, 94
. : milestone, 93,
master - mean (92ms) : 91, 94
. : milestone, 92,
section Baseline
This PR (7420) - mean (92ms) : 89, 95
. : milestone, 92,
master - mean (92ms) : 90, 94
. : milestone, 92,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (595ms) : 584, 606
. : milestone, 595,
master - mean (595ms) : 583, 608
. : milestone, 595,
gantt
title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (204ms) : 199, 210
. : milestone, 204,
master - mean (199ms) : 194, 204
. : milestone, 199,
section Baseline
This PR (7420) - mean (196ms) : 188, 204
. : milestone, 196,
master - mean (197ms) : 193, 202
. : milestone, 197,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (1,129ms) : 1095, 1162
. : milestone, 1129,
master - mean (1,119ms) : 1070, 1167
. : milestone, 1119,
gantt
title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (282ms) : 278, 286
. : milestone, 282,
master - mean (286ms) : 279, 292
. : milestone, 286,
section Baseline
This PR (7420) - mean (282ms) : 276, 288
. : milestone, 282,
master - mean (283ms) : 276, 290
. : milestone, 283,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (914ms) : 882, 946
. : milestone, 914,
master - mean (910ms) : 877, 943
. : milestone, 910,
gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (275ms) : 270, 279
. : milestone, 275,
master - mean (275ms) : 270, 280
. : milestone, 275,
section Baseline
This PR (7420) - mean (275ms) : 268, 283
. : milestone, 275,
master - mean (275ms) : 269, 280
. : milestone, 275,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (899ms) : 859, 938
. : milestone, 899,
master - mean (894ms) : 856, 932
. : milestone, 894,
gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat X
axisFormat %s
todayMarker off
section Bailout
This PR (7420) - mean (274ms) : 269, 279
. : milestone, 274,
master - mean (277ms) : 272, 282
. : milestone, 277,
section Baseline
This PR (7420) - mean (272ms) : 268, 276
. : milestone, 272,
master - mean (275ms) : 270, 280
. : milestone, 275,
section CallTarget+Inlining+NGEN
This PR (7420) - mean (812ms) : 780, 845
. : milestone, 812,
master - mean (812ms) : 785, 839
. : milestone, 812,
|
BenchmarksBenchmarks Report for benchmark platform 🐌Benchmarks for #7420 compared to master:
The following thresholds were used for comparing the benchmark speeds:
Allocation changes below 0.5% are ignored. Benchmark detailsBenchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ More allocations
|
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑net472 | 195.46 KB | 199.81 KB | 4.34 KB | 2.22% |
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 | 198.98 KB | 203.32 KB | 4.34 KB | 2.18% |
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑netcoreapp3.1 | 174.18 KB | 177.77 KB | 3.58 KB | 2.06% |
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑net6.0 | 172.07 KB | 175.6 KB | 3.52 KB | 2.05% |
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑netcoreapp3.1 | 177.6 KB | 181.18 KB | 3.58 KB | 2.02% |
| Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net6.0 | 175.58 KB | 179.1 KB | 3.52 KB | 2.01% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | AllCycleSimpleBody |
net6.0 | 325μs | 1.43μs | 5.53μs | 0 | 0 | 0 | 172.07 KB |
| master | AllCycleSimpleBody |
netcoreapp3.1 | 461μs | 1.27μs | 4.93μs | 0 | 0 | 0 | 174.18 KB |
| master | AllCycleSimpleBody |
net472 | 430μs | 124ns | 445ns | 30.2 | 0 | 0 | 195.46 KB |
| master | AllCycleMoreComplexBody |
net6.0 | 329μs | 105ns | 392ns | 0 | 0 | 0 | 175.58 KB |
| master | AllCycleMoreComplexBody |
netcoreapp3.1 | 502μs | 318ns | 1.23μs | 0 | 0 | 0 | 177.6 KB |
| master | AllCycleMoreComplexBody |
net472 | 437μs | 106ns | 398ns | 30.2 | 0 | 0 | 198.98 KB |
| master | ObjectExtractorSimpleBody |
net6.0 | 323ns | 0.146ns | 0.547ns | 0 | 0 | 0 | 280 B |
| master | ObjectExtractorSimpleBody |
netcoreapp3.1 | 420ns | 2.37ns | 15.7ns | 0 | 0 | 0 | 272 B |
| master | ObjectExtractorSimpleBody |
net472 | 299ns | 0.0328ns | 0.123ns | 0.0436 | 0 | 0 | 281 B |
| master | ObjectExtractorMoreComplexBody |
net6.0 | 6.36μs | 32.9ns | 171ns | 0 | 0 | 0 | 3.78 KB |
| master | ObjectExtractorMoreComplexBody |
netcoreapp3.1 | 7.82μs | 15.8ns | 61.1ns | 0 | 0 | 0 | 3.69 KB |
| master | ObjectExtractorMoreComplexBody |
net472 | 6.75μs | 4.47ns | 17.3ns | 0.572 | 0 | 0 | 3.8 KB |
| #7420 | AllCycleSimpleBody |
net6.0 | 333μs | 190ns | 735ns | 0 | 0 | 0 | 175.6 KB |
| #7420 | AllCycleSimpleBody |
netcoreapp3.1 | 488μs | 639ns | 2.47μs | 0 | 0 | 0 | 177.77 KB |
| #7420 | AllCycleSimpleBody |
net472 | 444μs | 205ns | 768ns | 30.2 | 0 | 0 | 199.81 KB |
| #7420 | AllCycleMoreComplexBody |
net6.0 | 337μs | 288ns | 1.04μs | 0 | 0 | 0 | 179.1 KB |
| #7420 | AllCycleMoreComplexBody |
netcoreapp3.1 | 509μs | 1.34μs | 5.19μs | 0 | 0 | 0 | 181.18 KB |
| #7420 | AllCycleMoreComplexBody |
net472 | 454μs | 218ns | 816ns | 31.2 | 0 | 0 | 203.32 KB |
| #7420 | ObjectExtractorSimpleBody |
net6.0 | 328ns | 0.332ns | 1.29ns | 0 | 0 | 0 | 280 B |
| #7420 | ObjectExtractorSimpleBody |
netcoreapp3.1 | 400ns | 1.95ns | 8.29ns | 0 | 0 | 0 | 272 B |
| #7420 | ObjectExtractorSimpleBody |
net472 | 301ns | 0.034ns | 0.131ns | 0.0439 | 0 | 0 | 281 B |
| #7420 | ObjectExtractorMoreComplexBody |
net6.0 | 6.28μs | 13.9ns | 53.9ns | 0 | 0 | 0 | 3.78 KB |
| #7420 | ObjectExtractorMoreComplexBody |
netcoreapp3.1 | 7.66μs | 34.7ns | 134ns | 0 | 0 | 0 | 3.69 KB |
| #7420 | ObjectExtractorMoreComplexBody |
net472 | 6.69μs | 5.13ns | 19.9ns | 0.601 | 0 | 0 | 3.8 KB |
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EncodeArgs |
net6.0 | 76.4μs | 173ns | 669ns | 0 | 0 | 0 | 32.4 KB |
| master | EncodeArgs |
netcoreapp3.1 | 95.6μs | 279ns | 1.08μs | 0 | 0 | 0 | 32.4 KB |
| master | EncodeArgs |
net472 | 117μs | 9.04ns | 35ns | 4.69 | 0 | 0 | 32.51 KB |
| master | EncodeLegacyArgs |
net6.0 | 143μs | 25.5ns | 95.3ns | 0 | 0 | 0 | 2.15 KB |
| master | EncodeLegacyArgs |
netcoreapp3.1 | 198μs | 215ns | 831ns | 0 | 0 | 0 | 2.14 KB |
| master | EncodeLegacyArgs |
net472 | 263μs | 183ns | 710ns | 0 | 0 | 0 | 2.16 KB |
| #7420 | EncodeArgs |
net6.0 | 78.1μs | 168ns | 649ns | 0 | 0 | 0 | 32.4 KB |
| #7420 | EncodeArgs |
netcoreapp3.1 | 96.8μs | 302ns | 1.17μs | 0 | 0 | 0 | 32.4 KB |
| #7420 | EncodeArgs |
net472 | 109μs | 8.77ns | 31.6ns | 4.89 | 0 | 0 | 32.51 KB |
| #7420 | EncodeLegacyArgs |
net6.0 | 146μs | 25.9ns | 93.5ns | 0 | 0 | 0 | 2.14 KB |
| #7420 | EncodeLegacyArgs |
netcoreapp3.1 | 198μs | 192ns | 745ns | 0 | 0 | 0 | 2.14 KB |
| #7420 | EncodeLegacyArgs |
net472 | 262μs | 34.3ns | 133ns | 0 | 0 | 0 | 2.16 KB |
Benchmarks.Trace.Asm.AppSecWafBenchmark - Faster 🎉 Same allocations ✔️
Faster 🎉 in #7420
Benchmark
base/diff
Base Median (ns)
Diff Median (ns)
Modality
Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack‑netcoreapp3.1
2.441
731,759.45
299,805.51
Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark‑netcoreapp3.1
2.049
858,787.30
419,153.75
| Benchmark | base/diff | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack‑netcoreapp3.1 | 2.441 | 731,759.45 | 299,805.51 | |
| Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmark‑netcoreapp3.1 | 2.049 | 858,787.30 | 419,153.75 |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunWafRealisticBenchmark |
net6.0 | 396μs | 100ns | 376ns | 0 | 0 | 0 | 4.55 KB |
| master | RunWafRealisticBenchmark |
netcoreapp3.1 | 800μs | 14μs | 140μs | 0 | 0 | 0 | 4.48 KB |
| master | RunWafRealisticBenchmark |
net472 | 431μs | 66.3ns | 257ns | 0 | 0 | 0 | 4.66 KB |
| master | RunWafRealisticBenchmarkWithAttack |
net6.0 | 295μs | 79.1ns | 306ns | 0 | 0 | 0 | 2.24 KB |
| master | RunWafRealisticBenchmarkWithAttack |
netcoreapp3.1 | 691μs | 9.27μs | 92.7μs | 0 | 0 | 0 | 2.22 KB |
| master | RunWafRealisticBenchmarkWithAttack |
net472 | 312μs | 70.5ns | 273ns | 0 | 0 | 0 | 2.29 KB |
| #7420 | RunWafRealisticBenchmark |
net6.0 | 403μs | 84.7ns | 317ns | 0 | 0 | 0 | 4.56 KB |
| #7420 | RunWafRealisticBenchmark |
netcoreapp3.1 | 419μs | 136ns | 470ns | 0 | 0 | 0 | 4.48 KB |
| #7420 | RunWafRealisticBenchmark |
net472 | 437μs | 43ns | 166ns | 0 | 0 | 0 | 4.66 KB |
| #7420 | RunWafRealisticBenchmarkWithAttack |
net6.0 | 294μs | 42.6ns | 165ns | 0 | 0 | 0 | 2.24 KB |
| #7420 | RunWafRealisticBenchmarkWithAttack |
netcoreapp3.1 | 300μs | 202ns | 756ns | 0 | 0 | 0 | 2.22 KB |
| #7420 | RunWafRealisticBenchmarkWithAttack |
net472 | 316μs | 69.8ns | 270ns | 0 | 0 | 0 | 2.29 KB |
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendRequest |
net6.0 | 62μs | 33.2ns | 124ns | 0 | 0 | 0 | 14.52 KB |
| master | SendRequest |
netcoreapp3.1 | 70.3μs | 170ns | 636ns | 0 | 0 | 0 | 17.42 KB |
| master | SendRequest |
net472 | 0.00994ns | 0.00342ns | 0.0133ns | 0 | 0 | 0 | 0 b |
| #7420 | SendRequest |
net6.0 | 60.3μs | 23.8ns | 82.5ns | 0 | 0 | 0 | 14.52 KB |
| #7420 | SendRequest |
netcoreapp3.1 | 72.6μs | 89ns | 345ns | 0 | 0 | 0 | 17.42 KB |
| #7420 | SendRequest |
net472 | 0.00876ns | 0.00168ns | 0.00651ns | 0 | 0 | 0 | 0 b |
Benchmarks.Trace.CharSliceBenchmark - Slower ⚠️ Fewer allocations 🎉
Slower ⚠️ in #7420
Benchmark
diff/base
Base Median (ns)
Diff Median (ns)
Modality
Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice‑netcoreapp3.1
1.177
2,108,410.16
2,482,366.88
Fewer allocations 🎉 in #7420
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net6.0
7 B
2 B
-5 B
-71.43%
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net6.0
4 B
1 B
-3 B
-75.00%
| Benchmark | diff/base | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice‑netcoreapp3.1 | 1.177 | 2,108,410.16 | 2,482,366.88 |
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net6.0 | 7 B | 2 B | -5 B | -71.43% |
| Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net6.0 | 4 B | 1 B | -3 B | -75.00% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | OriginalCharSlice |
net6.0 | 1.95ms | 431ns | 1.67μs | 0 | 0 | 0 | 640.01 KB |
| master | OriginalCharSlice |
netcoreapp3.1 | 2.13ms | 9.42μs | 36.5μs | 0 | 0 | 0 | 640 KB |
| master | OriginalCharSlice |
net472 | 2.62ms | 784ns | 2.93μs | 100 | 0 | 0 | 641.95 KB |
| master | OptimizedCharSlice |
net6.0 | 1.37ms | 188ns | 726ns | 0 | 0 | 0 | 7 B |
| master | OptimizedCharSlice |
netcoreapp3.1 | 1.67ms | 354ns | 1.37μs | 0 | 0 | 0 | 1 B |
| master | OptimizedCharSlice |
net472 | 1.98ms | 606ns | 2.35μs | 0 | 0 | 0 | 0 b |
| master | OptimizedCharSliceWithPool |
net6.0 | 823μs | 48.6ns | 188ns | 0 | 0 | 0 | 4 B |
| master | OptimizedCharSliceWithPool |
netcoreapp3.1 | 833μs | 56.8ns | 213ns | 0 | 0 | 0 | 0 b |
| master | OptimizedCharSliceWithPool |
net472 | 1.15ms | 49.5ns | 192ns | 0 | 0 | 0 | 0 b |
| #7420 | OriginalCharSlice |
net6.0 | 1.93ms | 615ns | 2.3μs | 0 | 0 | 0 | 640.01 KB |
| #7420 | OriginalCharSlice |
netcoreapp3.1 | 2.48ms | 4.55μs | 17μs | 0 | 0 | 0 | 640 KB |
| #7420 | OriginalCharSlice |
net472 | 2.67ms | 1.38μs | 4.97μs | 100 | 0 | 0 | 641.95 KB |
| #7420 | OptimizedCharSlice |
net6.0 | 1.36ms | 368ns | 1.43μs | 0 | 0 | 0 | 2 B |
| #7420 | OptimizedCharSlice |
netcoreapp3.1 | 1.67ms | 332ns | 1.24μs | 0 | 0 | 0 | 1 B |
| #7420 | OptimizedCharSlice |
net472 | 1.93ms | 434ns | 1.68μs | 0 | 0 | 0 | 0 b |
| #7420 | OptimizedCharSliceWithPool |
net6.0 | 795μs | 34.3ns | 133ns | 0 | 0 | 0 | 1 B |
| #7420 | OptimizedCharSliceWithPool |
netcoreapp3.1 | 840μs | 90.1ns | 337ns | 0 | 0 | 0 | 0 b |
| #7420 | OptimizedCharSliceWithPool |
net472 | 1.16ms | 40ns | 150ns | 0 | 0 | 0 | 0 b |
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ Fewer allocations 🎉
Fewer allocations 🎉 in #7420
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net472
56.46 KB
56.15 KB
-307 B
-0.54%
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net472 | 56.46 KB | 56.15 KB | -307 B | -0.54% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | WriteAndFlushEnrichedTraces |
net6.0 | 728μs | 3.63μs | 15.4μs | 0 | 0 | 0 | 41.59 KB |
| master | WriteAndFlushEnrichedTraces |
netcoreapp3.1 | 672μs | 3.76μs | 26.6μs | 0 | 0 | 0 | 42.08 KB |
| master | WriteAndFlushEnrichedTraces |
net472 | 877μs | 1.65μs | 6.16μs | 8.33 | 0 | 0 | 56.46 KB |
| #7420 | WriteAndFlushEnrichedTraces |
net6.0 | 719μs | 961ns | 3.72μs | 0 | 0 | 0 | 41.78 KB |
| #7420 | WriteAndFlushEnrichedTraces |
netcoreapp3.1 | 651μs | 3.02μs | 19.8μs | 0 | 0 | 0 | 41.92 KB |
| #7420 | WriteAndFlushEnrichedTraces |
net472 | 896μs | 3.37μs | 13.1μs | 8.33 | 0 | 0 | 56.15 KB |
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteNonQuery |
net6.0 | 1.89μs | 5.82ns | 21.8ns | 0 | 0 | 0 | 1.02 KB |
| master | ExecuteNonQuery |
netcoreapp3.1 | 2.48μs | 10.4ns | 39ns | 0 | 0 | 0 | 1.02 KB |
| master | ExecuteNonQuery |
net472 | 2.92μs | 5.69ns | 22ns | 0.144 | 0.0144 | 0 | 987 B |
| #7420 | ExecuteNonQuery |
net6.0 | 1.9μs | 2.98ns | 11.6ns | 0 | 0 | 0 | 1.02 KB |
| #7420 | ExecuteNonQuery |
netcoreapp3.1 | 2.5μs | 10.4ns | 36.1ns | 0 | 0 | 0 | 1.02 KB |
| #7420 | ExecuteNonQuery |
net472 | 2.8μs | 3.22ns | 12.5ns | 0.152 | 0.0138 | 0 | 987 B |
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | CallElasticsearch |
net6.0 | 1.73μs | 8.8ns | 39.4ns | 0 | 0 | 0 | 1.03 KB |
| master | CallElasticsearch |
netcoreapp3.1 | 2.25μs | 10.6ns | 41.2ns | 0 | 0 | 0 | 1.03 KB |
| master | CallElasticsearch |
net472 | 3.63μs | 1.45ns | 5.43ns | 0.163 | 0 | 0 | 1.04 KB |
| master | CallElasticsearchAsync |
net6.0 | 1.85μs | 6.28ns | 22.6ns | 0 | 0 | 0 | 1.01 KB |
| master | CallElasticsearchAsync |
netcoreapp3.1 | 2.34μs | 8.78ns | 32.9ns | 0 | 0 | 0 | 1.08 KB |
| master | CallElasticsearchAsync |
net472 | 3.85μs | 4.25ns | 16.5ns | 0.172 | 0 | 0 | 1.1 KB |
| #7420 | CallElasticsearch |
net6.0 | 1.79μs | 5.98ns | 23.2ns | 0 | 0 | 0 | 1.03 KB |
| #7420 | CallElasticsearch |
netcoreapp3.1 | 2.27μs | 11.4ns | 44.3ns | 0 | 0 | 0 | 1.03 KB |
| #7420 | CallElasticsearch |
net472 | 3.65μs | 4.07ns | 15.8ns | 0.164 | 0 | 0 | 1.04 KB |
| #7420 | CallElasticsearchAsync |
net6.0 | 1.77μs | 8.34ns | 31.2ns | 0 | 0 | 0 | 1.01 KB |
| #7420 | CallElasticsearchAsync |
netcoreapp3.1 | 2.42μs | 9.79ns | 37.9ns | 0 | 0 | 0 | 1.08 KB |
| #7420 | CallElasticsearchAsync |
net472 | 3.71μs | 4.26ns | 16.5ns | 0.167 | 0 | 0 | 1.1 KB |
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteAsync |
net6.0 | 1.86μs | 1.44ns | 5.39ns | 0 | 0 | 0 | 952 B |
| master | ExecuteAsync |
netcoreapp3.1 | 2.28μs | 7.72ns | 29.9ns | 0 | 0 | 0 | 952 B |
| master | ExecuteAsync |
net472 | 2.61μs | 1ns | 3.89ns | 0.144 | 0 | 0 | 915 B |
| #7420 | ExecuteAsync |
net6.0 | 1.87μs | 9.79ns | 45.9ns | 0 | 0 | 0 | 953 B |
| #7420 | ExecuteAsync |
netcoreapp3.1 | 2.29μs | 7.17ns | 27.8ns | 0 | 0 | 0 | 952 B |
| #7420 | ExecuteAsync |
net472 | 2.6μs | 1.05ns | 4.07ns | 0.143 | 0 | 0 | 915 B |
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendAsync |
net6.0 | 7.13μs | 15ns | 58.2ns | 0 | 0 | 0 | 2.36 KB |
| master | SendAsync |
netcoreapp3.1 | 8.3μs | 30.9ns | 120ns | 0 | 0 | 0 | 2.9 KB |
| master | SendAsync |
net472 | 12.5μs | 10.4ns | 40.4ns | 0.503 | 0 | 0 | 3.18 KB |
| #7420 | SendAsync |
net6.0 | 6.97μs | 13.3ns | 51.4ns | 0 | 0 | 0 | 2.36 KB |
| #7420 | SendAsync |
netcoreapp3.1 | 8.53μs | 17.6ns | 68.2ns | 0 | 0 | 0 | 2.9 KB |
| #7420 | SendAsync |
net472 | 12.5μs | 7.9ns | 30.6ns | 0.499 | 0 | 0 | 3.18 KB |
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed ✔️ More allocations ⚠️
More allocations ⚠️ in #7420
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0
259.42 KB
278.42 KB
18.99 KB
7.32%
Fewer allocations 🎉 in #7420
Benchmark
Base Allocated
Diff Allocated
Change
Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0
44.61 KB
43.73 KB
-880 B
-1.97%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1
277.95 KB
248.51 KB
-29.44 KB
-10.59%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net472
65.54 KB
57.34 KB
-8.19 KB
-12.50%
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 | 259.42 KB | 278.42 KB | 18.99 KB | 7.32% |
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0 | 44.61 KB | 43.73 KB | -880 B | -1.97% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 | 277.95 KB | 248.51 KB | -29.44 KB | -10.59% |
| Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net472 | 65.54 KB | 57.34 KB | -8.19 KB | -12.50% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StringConcatBenchmark |
net6.0 | 52.3μs | 693ns | 6.89μs | 0 | 0 | 0 | 44.61 KB |
| master | StringConcatBenchmark |
netcoreapp3.1 | 56μs | 775ns | 7.67μs | 0 | 0 | 0 | 43.04 KB |
| master | StringConcatBenchmark |
net472 | 57.2μs | 241ns | 934ns | 0 | 0 | 0 | 65.54 KB |
| master | StringConcatAspectBenchmark |
net6.0 | 449μs | 1.6μs | 5.55μs | 0 | 0 | 0 | 259.42 KB |
| master | StringConcatAspectBenchmark |
netcoreapp3.1 | 512μs | 1.88μs | 6.52μs | 0 | 0 | 0 | 277.95 KB |
| master | StringConcatAspectBenchmark |
net472 | 403μs | 2.2μs | 13μs | 0 | 0 | 0 | 278.53 KB |
| #7420 | StringConcatBenchmark |
net6.0 | 48.9μs | 269ns | 1.57μs | 0 | 0 | 0 | 43.73 KB |
| #7420 | StringConcatBenchmark |
netcoreapp3.1 | 48.4μs | 232ns | 1.83μs | 0 | 0 | 0 | 43.05 KB |
| #7420 | StringConcatBenchmark |
net472 | 57.4μs | 286ns | 1.31μs | 0 | 0 | 0 | 57.34 KB |
| #7420 | StringConcatAspectBenchmark |
net6.0 | 487μs | 952ns | 4.76μs | 0 | 0 | 0 | 278.42 KB |
| #7420 | StringConcatAspectBenchmark |
netcoreapp3.1 | 490μs | 2.11μs | 7.9μs | 0 | 0 | 0 | 248.51 KB |
| #7420 | StringConcatAspectBenchmark |
net472 | 405μs | 2.33μs | 18.7μs | 0 | 0 | 0 | 278.53 KB |
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 2.58μs | 12.2ns | 50.2ns | 0 | 0 | 0 | 1.7 KB |
| master | EnrichedLog |
netcoreapp3.1 | 3.42μs | 1.49ns | 5.59ns | 0 | 0 | 0 | 1.7 KB |
| master | EnrichedLog |
net472 | 4.09μs | 5.8ns | 22.5ns | 0.244 | 0 | 0 | 1.64 KB |
| #7420 | EnrichedLog |
net6.0 | 2.62μs | 1.39ns | 5.19ns | 0 | 0 | 0 | 1.7 KB |
| #7420 | EnrichedLog |
netcoreapp3.1 | 3.48μs | 17.9ns | 81.8ns | 0 | 0 | 0 | 1.7 KB |
| #7420 | EnrichedLog |
net472 | 3.97μs | 4.14ns | 16ns | 0.257 | 0 | 0 | 1.64 KB |
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 124μs | 159ns | 575ns | 0 | 0 | 0 | 4.31 KB |
| master | EnrichedLog |
netcoreapp3.1 | 127μs | 165ns | 594ns | 0 | 0 | 0 | 4.31 KB |
| master | EnrichedLog |
net472 | 167μs | 30.3ns | 114ns | 0 | 0 | 0 | 4.52 KB |
| #7420 | EnrichedLog |
net6.0 | 122μs | 49.3ns | 184ns | 0 | 0 | 0 | 4.31 KB |
| #7420 | EnrichedLog |
netcoreapp3.1 | 128μs | 198ns | 715ns | 0 | 0 | 0 | 4.31 KB |
| #7420 | EnrichedLog |
net472 | 168μs | 69.8ns | 252ns | 0 | 0 | 0 | 4.52 KB |
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 5.03μs | 14.3ns | 55.4ns | 0 | 0 | 0 | 2.26 KB |
| master | EnrichedLog |
netcoreapp3.1 | 6.65μs | 15.2ns | 58.8ns | 0 | 0 | 0 | 2.26 KB |
| master | EnrichedLog |
net472 | 7.43μs | 10ns | 38.8ns | 0.296 | 0 | 0 | 2.08 KB |
| #7420 | EnrichedLog |
net6.0 | 5.21μs | 11.8ns | 44ns | 0 | 0 | 0 | 2.26 KB |
| #7420 | EnrichedLog |
netcoreapp3.1 | 6.78μs | 5.69ns | 21.3ns | 0 | 0 | 0 | 2.26 KB |
| #7420 | EnrichedLog |
net472 | 7.63μs | 11ns | 42.7ns | 0.304 | 0 | 0 | 2.08 KB |
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendReceive |
net6.0 | 1.98μs | 6.17ns | 23.9ns | 0 | 0 | 0 | 1.2 KB |
| master | SendReceive |
netcoreapp3.1 | 2.57μs | 13.1ns | 58.5ns | 0 | 0 | 0 | 1.2 KB |
| master | SendReceive |
net472 | 3.17μs | 2.09ns | 8.1ns | 0.19 | 0 | 0 | 1.2 KB |
| #7420 | SendReceive |
net6.0 | 1.98μs | 9.04ns | 36.2ns | 0 | 0 | 0 | 1.2 KB |
| #7420 | SendReceive |
netcoreapp3.1 | 2.64μs | 3.91ns | 15.1ns | 0 | 0 | 0 | 1.2 KB |
| #7420 | SendReceive |
net472 | 3.26μs | 3.3ns | 12.8ns | 0.177 | 0 | 0 | 1.2 KB |
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net6.0 | 4.15μs | 5.83ns | 22.6ns | 0 | 0 | 0 | 1.58 KB |
| master | EnrichedLog |
netcoreapp3.1 | 5.95μs | 13.2ns | 51ns | 0 | 0 | 0 | 1.63 KB |
| master | EnrichedLog |
net472 | 6.88μs | 9.54ns | 37ns | 0.312 | 0 | 0 | 2.03 KB |
| #7420 | EnrichedLog |
net6.0 | 4.11μs | 1.81ns | 7ns | 0 | 0 | 0 | 1.58 KB |
| #7420 | EnrichedLog |
netcoreapp3.1 | 5.55μs | 15.7ns | 60.6ns | 0 | 0 | 0 | 1.63 KB |
| #7420 | EnrichedLog |
net472 | 6.8μs | 4.82ns | 18ns | 0.309 | 0 | 0 | 2.03 KB |
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StartFinishSpan |
net6.0 | 744ns | 3.76ns | 16.4ns | 0 | 0 | 0 | 576 B |
| master | StartFinishSpan |
netcoreapp3.1 | 946ns | 4.47ns | 17.9ns | 0 | 0 | 0 | 576 B |
| master | StartFinishSpan |
net472 | 894ns | 0.243ns | 0.91ns | 0.0916 | 0 | 0 | 578 B |
| master | StartFinishScope |
net6.0 | 923ns | 4.59ns | 20ns | 0 | 0 | 0 | 696 B |
| master | StartFinishScope |
netcoreapp3.1 | 1.11μs | 5.37ns | 21.5ns | 0 | 0 | 0 | 696 B |
| master | StartFinishScope |
net472 | 1.11μs | 0.248ns | 0.962ns | 0.0996 | 0 | 0 | 658 B |
| #7420 | StartFinishSpan |
net6.0 | 734ns | 2.7ns | 10.5ns | 0 | 0 | 0 | 576 B |
| #7420 | StartFinishSpan |
netcoreapp3.1 | 942ns | 3.83ns | 16.7ns | 0 | 0 | 0 | 576 B |
| #7420 | StartFinishSpan |
net472 | 902ns | 0.627ns | 2.35ns | 0.0895 | 0 | 0 | 578 B |
| #7420 | StartFinishScope |
net6.0 | 879ns | 4.72ns | 24.1ns | 0 | 0 | 0 | 696 B |
| #7420 | StartFinishScope |
netcoreapp3.1 | 1.18μs | 6.29ns | 32.7ns | 0 | 0 | 0 | 696 B |
| #7420 | StartFinishScope |
net472 | 1.1μs | 2.2ns | 8.5ns | 0.103 | 0 | 0 | 658 B |
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunOnMethodBegin |
net6.0 | 1.05μs | 5.09ns | 20.4ns | 0 | 0 | 0 | 696 B |
| master | RunOnMethodBegin |
netcoreapp3.1 | 1.36μs | 6.47ns | 25.1ns | 0 | 0 | 0 | 696 B |
| master | RunOnMethodBegin |
net472 | 1.38μs | 0.233ns | 0.902ns | 0.0979 | 0 | 0 | 658 B |
| #7420 | RunOnMethodBegin |
net6.0 | 1.01μs | 5.22ns | 24.5ns | 0 | 0 | 0 | 697 B |
| #7420 | RunOnMethodBegin |
netcoreapp3.1 | 1.39μs | 7.18ns | 33.7ns | 0 | 0 | 0 | 696 B |
| #7420 | RunOnMethodBegin |
net472 | 1.4μs | 1.92ns | 7.43ns | 0.104 | 0 | 0 | 658 B |
andrewlock
left a comment
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.
Nice, some great documentation for the public APIs 👍 Most of the comments are just tiny nits, but there's some things we'll need to address with the ordering in the telemetry I think
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Outdated
Show resolved
Hide resolved
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Show resolved
Hide resolved
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Show resolved
Hide resolved
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Show resolved
Hide resolved
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Outdated
Show resolved
Hide resolved
tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs
Outdated
Show resolved
Hide resolved
tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.OpenTelemetry.cs
Outdated
Show resolved
Hide resolved
tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs
Outdated
Show resolved
Hide resolved
tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs
Outdated
Show resolved
Hide resolved
) ## Summary of changes - Fix `ClassConfigurationResultWithKey.WithDefault()` to take a `DefaultResult<T>` - Don't allow creating arbitrary `StructConfigurationResultWithKey` - Remove (inline) buggy `RecordTelemetry<>` method ## Reason for change When reviewing #7420, I noticed there was an incorrect usage of `WithDefault()` due to limitations in the type system, so this tries to close that gap. Unfortunately, that required more changes than I would like, due to limitations in generics and constraints. ## Implementation details - Inline the `RecordTelemetry<T>` method - Explicitly limit the types of `StructConfigurationResultWithKey<T>` that may be created by using static factory methods and a `private` ctor - Fix `ClassConfigurationResultWithKey.WithDefault()` to take a `DefaultResult<T>` so that we always have a telemetry value to record. This will be slightly clunky if you try to do it with `string`, but we can close that gap later if we need to ## Test coverage Added a couple of small unit tests ## Other details Spotted when reviewing - #7420 <!--⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. -->
## Summary of changes Add missing `GetDictionary()` method to `ConfigurationBuilder` ## Reason for change We were missing a method that allows providing a default instance for a dictionary up-front. This was forcing using other overloads that are suboptimal for telemetry. ## Implementation details Add the missing helper that allows providing a default value. I allowed passing a null value in here, as it avoids unnecessary allocations if you don't actually need the dictionary. A good example was the fixed usage in `InitializeHeaderTags` which was creating an empty dictionary instead of taking the fast-path `null` route (and potentially actually giving _incorrect_ settings in the `DynamicSettings` I think ## Test coverage Meh ## Other details Spotted when reviewing - #7420 <!--⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. -->
…DataDog/dd-trace-dotnet into maximo/otel-metrics-api-configs
zacharycmontoya
left a comment
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 have one blocking concern with the weird interaction between OTEL_METRICS_EXPORTER and the runtime metrics config. Otherwise, just left some comments for smaller tweaks
Applying nits and updating tests
f571fb5 to
cd45d81
Compare
zacharycmontoya
left a comment
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.
After the configuration changes, it looks like we're reporting the correct default values and setting runtime metrics enabled correctly. Thanks for following up on all the feedback!
## Summary of changes This PR implements the metrics collection foundation for OpenTelemetry Metrics API supportKey additions include: - MetricReader: Component for collecting instrument measurements and aggregating them - MetricReaderHandler: High-performance measurement processing with proper aggregation (Sum, Last Value, Histogram) - MetricPoint: Thread-safe data structure for metric aggregation with histogram bucket support - Testing: Unit test covering all 7 instrument types (4 sync + 3 async) with exact OTLP value verification This is the second of a series of 3 PRs to complete the OpenTelemetry Metrics API support. 1. [[OTEL] Metrics API Support - Configurations & Telemetry #7420](#7420) 2. [[OTEL] Metrics API Support - Collection Implementation #7511](#7511) <- You are here. 3. [[OTEL] Metrics API Support - Metrics Reader & OTLP Exporter #7514](#7514) ## Reason for change The [RFC] OpenTelemetry Metrics API support requires implementing metrics collection that's compatible with the OpenTelemetry data model. This PR provides the collection foundation that will enable customers to use .NET's `System.Diagnostics.Metrics` API with Datadog as a drop-in replacement for the OpenTelemetry SDK. Business Impact: Enables the collection phase of OpenTelemetry Metrics API support, laying the groundwork for OTLP export in the next PR. ## Implementation details ✅ Metrics Collection Components: - MetricReader - RFC-compliant component for initialization and async collection - MetricReaderHandler - Measurement processing and aggregation - MetricPoint - Aggregation data structure with histogram bucket support ✅ Aggregation Mapping: - Counter/Asynchronous Counter → Sum Aggregation → Sum Metric Point ✅ - UpDownCounter/Asynchronous UpDownCounter → Sum Aggregation → Sum Metric Point ✅ - Gauge/Asynchronous Gauge → Last Value Aggregation → Gauge Metric Point ✅ - Histogram → Explicit Bucket Histogram Aggregation → Histogram Metric Point ✅ ## Test coverage Added unit test `MeterListenerCapturesAllMetrics()` that verifies: - All 7 instrument types (Counter, Histogram, Gauge, UpDownCounter + 3 Async variants) - Value verification matching OTLP snapshot expectations Histogram bucket logic verification - Sync + Async instrument collection - Tag capture and temporality settings ## Other details Jira: [APMAPI-1572](https://datadoghq.atlassian.net/browse/APMAPI-1572) <!-- Fixes #{issue} --> <!--⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. --> [APMAPI-1572]: https://datadoghq.atlassian.net/browse/APMAPI-1572?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
## Summary of changes This PR implements the OTLP Metrics Exporter for OpenTelemetry Metrics API support, completing the final piece of the RFC implementation. Key additions include: - OTLP Metrics Exporter: Implemented `MetricExporter` abstract class and `OtlpExporter` concrete implementation initially with only ` HTTP/protobuf` transport support ATM. - Performance Optimizations: Custom protobuf serialization without external dependencies, async operations with ConfigureAwait(false) - Retry Logic: Exponential backoff with Retry-After header handling for HTTP 429, 502, 503, 504 responses - Telemetry Metrics: Internal metrics tracking (`metrics_export_attempts`, `metrics_export_successes`, `metrics_export_failures`) with protocol tag - Sample App Integration: Enhanced Samples.OpenTelemetrySdk to support both DD and OTel SDK approaches for comparative snapshot testing This completes the series of 3 PRs for OpenTelemetry Metrics API support. 1. [[OTEL] Metrics API Support - Configurations & Telemetry #7420](#7420) 2. [[OTEL] Metrics API Support - Collection Implementation #7511](#7511) 3. [[OTEL] Metrics API Support - Metrics Reader & OTLP Exporter #7514](#7514) <- You are here. ## Reason for change The [RFC] OpenTelemetry Metrics API support requires the .NET tracer to act as a drop-in replacement for the OpenTelemetry SDK. This PR implements the OTLP export functionality, enabling customers to migrate from OTel SDK to Datadog SDK with zero friction. Business Impact: Enables customers using OpenTelemetry Metrics API to switch to Datadog without code changes, supporting our strategic initiative to be OTel-native. ## Implementation details :white_check_mark: OTLP Metrics Exporter Components: - MetricExporter - Abstract base class defining export contract - OtlpExporter - Concrete implementation with HTTP/protobuf transport - OtlpMetricsSerializer - Custom protobuf serialization for performance - MetricReader - Updated to use the new exporter architecture :white_check_mark: Key Features: - HTTP/protobuf transport support - Resource attribute precedence following RFC (DD_* → OTEL_* → defaults) - Retry logic with exponential backoff and proper HTTP status handling - Telemetry metrics with protocol tags (protocol:http/protobuf, protocol:grpc, protocol:http/json) - Performance optimizations with async operations and custom serialization :white_check_mark: Sample App Enhancements: - Conditional OTel SDK exporter via OTEL_METRICS_EXPORTER_ENABLED environment variable for testing - Comparative testing between DD and OTel SDK approaches - Proper MeterProvider lifecycle management with disposal ## Test coverage Added comprehensive integration test `SubmitsOtlpMetrics` that: - Tests both approaches: DD enabled/OTel disabled vs DD disabled/OTel enabled - Verifies identical results: Both approaches produce the same OTLP metric requests - Cross-version testing: Runs across all OpenTelemetry package versions - Snapshot verification: Ensures RFC compliance and data model compatibility **NOTE**: Hoping to add Grpc and HTTP/Json tests along with the current `SubmitsOtlpMetrics` protobuf one and also benchmarks if possible to compare OTEL vs Datadog overhead. ## Other details <!-- Fixes #{issue} --> Jira: [APMAPI-1573](https://datadoghq.atlassian.net/browse/APMAPI-1573) <!--⚠️ Note: Where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. MergeQueue is NOT enabled in this repository. If you have write access to the repo, the PR has 1-2 approvals (see above), and all of the required checks have passed, you can use the Squash and Merge button to merge the PR. If you don't have write access, or you need help, reach out in the #apm-dotnet channel in Slack. --> [APMAPI-1573]: https://datadoghq.atlassian.net/browse/APMAPI-1573?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
Summary of changes
This PR implements configuration parsing needed for OpenTelemetry OTLP Metrics Collecting and Exporting as part of the broader OpenTelemetry Metrics API support RFC. Key additions include:
This is the first of a series of 3 PRs I hope to put together to complete this work.
Reason for change
The [RFC] OpenTelemetry Metrics API support requires the .NET tracer to act as a drop-in replacement for the OpenTelemetry SDK, allowing customers to migrate from OTel SDK to Datadog SDK with zero friction. This requires supporting all standard OpenTelemetry configuration environment variables for metrics export.
Business Impact: Enables customers using OpenTelemetry Metrics API to switch to Datadog without code changes, supporting our strategic initiative to be OTel-native.
Implementation details
Added the configurations below, for some I needed to add both metrics configs and fallbacks also tracer settings, for others I needed to add only testing and to telemetry. ✅ Added | 🟣 Updated | 🟦 Untouched
Datadog SDK Configurations (2/2):
1. DD_METRICS_OTEL_ENABLED- 🟣2. DD_TAGS- 🟦OpenTelemetry Metrics SDK Configurations (4/4):
1. OTEL_RESOURCE_ATTRIBUTES- 🟦2. OTEL_METRICS_EXPORTER- 🟣3. OTEL_METRIC_EXPORT_INTERVAL- ✅4. OTEL_METRIC_EXPORT_TIMEOUT- ✅OTLP Exporter Configurations (9/9):
1. OTEL_EXPORTER_OTLP_METRICS_PROTOCOL- ✅2. OTEL_EXPORTER_OTLP_METRICS_ENDPOINT- ✅3. OTEL_EXPORTER_OTLP_METRICS_HEADERS- ✅4. OTEL_EXPORTER_OTLP_METRICS_TIMEOUT- ✅5. OTEL_EXPORTER_OTLP_PROTOCOL (fallback)- ✅6. OTEL_EXPORTER_OTLP_ENDPOINT (fallback)- ✅7. OTEL_EXPORTER_OTLP_HEADERS (fallback)- ✅8. OTEL_EXPORTER_OTLP_TIMEOUT (fallback)- ✅9. OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE- ✅Test coverage
Added to TracerSettingsTests different tests for each configuration combos and fallbacks expected behavior, also accounting for customers adding invalid/unsupported inputs for the multiple choice configs.
(Will add/update the tests as the other PRs are coming to completion).
Other details
Jira: APMAPI-1571