Skip to content
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

Switch .NET tracer to injecting both base64 & binary headers #6257

Open
wants to merge 30 commits into
base: master
Choose a base branch
from

Conversation

veerbia
Copy link

@veerbia veerbia commented Nov 7, 2024

Summary of changes

  • Switch .NET tracer to injecting both base64 & binary headers
  • Binary headers can be disabled via a config variable: DD_DATA_STREAMS_LEGACY_HEADERS=false (defaults to true)
  • .NET tracer, when extracting the context from headers looks at both base64 & binary headers

Reason for change

Data Streams previously used binary encoding in Kafka headers. This was causing issues in cross language communication because of the difference in negative byte handling. That’s why we switched to base64 encoding.
Today, .NET is the only remaining tracer using binary encoding for Kafka, SQS & RabbitMQ.

This is causing 3 issues:

  • Communication between .NET & Java breaks, since Java doesn’t support negative bytes in Kafka headers
  • Manual instrumentation breaks between .NET and any other language, since manual instrumentation uses base64 encoding
  • .NET can’t consume payloads from any other tracers, since the other tracers encode in base64

Also, byte headers are causing a crash of the .NET application (not reproduced yet).

Implementation details

  • Injects base64-encoded headers by default to ensure cross-language compatibility.
  • Binary headers are injected only if DD_DATA_STREAMS_LEGACY_HEADERS (default: true) is enabled for backward compatibility.
  • Prefers base64 headers for extraction. If base64 is unavailable or malformed, it falls back to binary headers when legacy headers are enabled.
  • A new configuration setting DD_DATA_STREAMS_LEGACY_HEADERS controls whether binary headers are included.

Test coverage

I've added tests for the following cases:

  • Inject_WhenLegacyHeadersDisabled_DoesNotIncludeBinaryHeader

    • Ensures that when legacy headers are disabled, the binary header is not included in the injected headers.
  • Extract_WhenBothHeadersPresent_PrefersBase64Header

    • Confirms that when both Base64 and binary headers are present, the Base64 header is preferred for extraction.
  • InjectedHeaders_HaveCorrectFormat

    • Validates that injected headers are in the correct format, especially checking if the Base64-encoded header is valid and correctly decoded.
  • InjectHeaders_WhenLegacyHeadersDisabled_DoesNotIncludeLegacyHeader

    • Ensures that legacy headers are excluded when legacy header support is disabled.
  • Inject_WhenLegacyHeadersEnabled_IncludesBothHeaders

    • Confirms that both Base64 and binary headers are injected when legacy header support is enabled.
  • Extract_WhenBase64HeaderIsMalformed_ReturnsFallbackToBinary

    • Verifies that if the Base64 header is malformed, the system falls back to using the binary header for extraction.

Other details

@datadog-ddstaging
Copy link

datadog-ddstaging bot commented Nov 7, 2024

Datadog Report

Branch report: veerbia/base64migration
Commit report: 6e9062a
Test service: dd-trace-dotnet

❌ 1 Failed (0 Known Flaky), 451220 Passed, 2732 Skipped, 18h 26m 13.73s Total Time

❌ Failed Tests (1)

  • NoExceptions - Datadog.Trace.ClrProfiler.IntegrationTests.SmokeTests.AssemblyResolveMscorlibResourcesInfiniteRecursionCrashSmokeTest - Details

    Expand for error
     Expected no errors in smoke test: [createdump] ptrace(ATTACH, 8677) FAILED Operation not permitted
     
     Expected: True
     Actual:   False
    

@andrewlock
Copy link
Member

andrewlock commented Nov 7, 2024

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:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

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.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (72ms)  : 64, 80
     .   : milestone, 72,
    master - mean (71ms)  : 65, 78
     .   : milestone, 71,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (981ms)  : 962, 1000
     .   : milestone, 981,
    master - mean (981ms)  : 960, 1003
     .   : milestone, 981,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (108ms)  : 105, 110
     .   : milestone, 108,
    master - mean (108ms)  : 106, 110
     .   : milestone, 108,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (680ms)  : 660, 699
     .   : milestone, 680,
    master - mean (683ms)  : 665, 702
     .   : milestone, 683,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (92ms)  : 89, 95
     .   : milestone, 92,
    master - mean (92ms)  : 89, 95
     .   : milestone, 92,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (632ms)  : 616, 649
     .   : milestone, 632,
    master - mean (638ms)  : 623, 653
     .   : milestone, 638,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (191ms)  : 185, 196
     .   : milestone, 191,
    master - mean (190ms)  : 186, 194
     .   : milestone, 190,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (1,103ms)  : 1072, 1134
     .   : milestone, 1103,
    master - mean (1,094ms)  : 1072, 1115
     .   : milestone, 1094,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (276ms)  : 272, 281
     .   : milestone, 276,
    master - mean (276ms)  : 272, 279
     .   : milestone, 276,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (877ms)  : 849, 905
     .   : milestone, 877,
    master - mean (875ms)  : 850, 900
     .   : milestone, 875,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6257) - mean (265ms)  : 262, 269
     .   : milestone, 265,
    master - mean (264ms)  : 260, 268
     .   : milestone, 264,

    section CallTarget+Inlining+NGEN
    This PR (6257) - mean (855ms)  : 823, 887
     .   : milestone, 855,
    master - mean (854ms)  : 825, 884
     .   : milestone, 854,

Loading

@andrewlock
Copy link
Member

andrewlock commented Nov 7, 2024

Throughput/Crank Report ⚡

Throughput results for AspNetCoreSimpleController comparing the following branches/commits:

Cases where throughput results for the PR are worse than latest master (5% drop or greater), results are shown in red.

Note that these results are based on a single point-in-time result for each branch. For full results, see one of the many, many dashboards!

gantt
    title Throughput Linux x64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (6257) (11.168M)   : 0, 11167674
    master (11.247M)   : 0, 11246955
    benchmarks/2.9.0 (11.033M)   : 0, 11032866

    section Automatic
    This PR (6257) (7.257M)   : 0, 7256823
    master (7.407M)   : 0, 7406927
    benchmarks/2.9.0 (7.786M)   : 0, 7785853

    section Trace stats
    master (7.695M)   : 0, 7695476

    section Manual
    master (11.240M)   : 0, 11240426

    section Manual + Automatic
    This PR (6257) (6.700M)   : 0, 6700131
    master (6.871M)   : 0, 6870622

    section DD_TRACE_ENABLED=0
    master (10.206M)   : 0, 10206195

Loading
gantt
    title Throughput Linux arm64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (6257) (9.559M)   : 0, 9558760
    master (9.563M)   : 0, 9563014
    benchmarks/2.9.0 (9.495M)   : 0, 9494821

    section Automatic
    This PR (6257) (6.347M)   : 0, 6346842
    master (6.412M)   : 0, 6411572

    section Trace stats
    master (6.703M)   : 0, 6703390

    section Manual
    master (9.369M)   : 0, 9369266

    section Manual + Automatic
    This PR (6257) (5.939M)   : 0, 5939281
    master (5.978M)   : 0, 5977872

    section DD_TRACE_ENABLED=0
    master (8.996M)   : 0, 8996087

Loading
gantt
    title Throughput Windows x64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (6257) (9.004M)   : 0, 9004425
    benchmarks/2.9.0 (10.020M)   : 0, 10019592

    section Automatic
    This PR (6257) (6.012M)   : 0, 6012109
    benchmarks/2.9.0 (7.255M)   : 0, 7255257

    section Manual + Automatic
    This PR (6257) (5.434M)   : 0, 5433882

Loading

@andrewlock
Copy link
Member

andrewlock commented Nov 8, 2024

Benchmarks Report for tracer 🐌

Benchmarks for #6257 compared to master:

  • 2 benchmarks are slower, with geometric mean 1.182
  • All benchmarks have the same allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 7.84μs 42.3ns 247ns 0.0112 0.00372 0 5.61 KB
master StartStopWithChild netcoreapp3.1 10.1μs 52.1ns 244ns 0.0145 0.00482 0 5.8 KB
master StartStopWithChild net472 16.1μs 65.2ns 252ns 1.04 0.3 0.0972 6.21 KB
#6257 StartStopWithChild net6.0 7.91μs 45ns 337ns 0.0186 0.00743 0 5.61 KB
#6257 StartStopWithChild netcoreapp3.1 10.1μs 57.3ns 409ns 0.019 0.00951 0 5.8 KB
#6257 StartStopWithChild net472 16.5μs 46.8ns 181ns 1.05 0.321 0.104 6.21 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 490μs 463ns 1.79μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 652μs 267ns 1μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 838μs 365ns 1.37μs 0.417 0 0 3.3 KB
#6257 WriteAndFlushEnrichedTraces net6.0 515μs 303ns 1.18μs 0 0 0 2.7 KB
#6257 WriteAndFlushEnrichedTraces netcoreapp3.1 663μs 290ns 1.12μs 0 0 0 2.7 KB
#6257 WriteAndFlushEnrichedTraces net472 834μs 297ns 1.11μs 0.417 0 0 3.3 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 150μs 860ns 6.93μs 0.148 0 0 14.47 KB
master SendRequest netcoreapp3.1 169μs 953ns 7.69μs 0.154 0 0 17.27 KB
master SendRequest net472 0.000269ns 0.000209ns 0.000783ns 0 0 0 0 b
#6257 SendRequest net6.0 152μs 854ns 5.73μs 0.147 0 0 14.47 KB
#6257 SendRequest netcoreapp3.1 161μs 833ns 3.91μs 0.16 0 0 17.27 KB
#6257 SendRequest net472 1.52E‑05ns 1.05E‑05ns 4.08E‑05ns 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 586μs 2.86μs 11.8μs 0.553 0 0 41.77 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 673μs 3.4μs 15.2μs 0.331 0 0 41.74 KB
master WriteAndFlushEnrichedTraces net472 873μs 4.48μs 20μs 8.68 2.6 0.434 53.31 KB
#6257 WriteAndFlushEnrichedTraces net6.0 556μs 2.52μs 9.44μs 0.539 0 0 41.71 KB
#6257 WriteAndFlushEnrichedTraces netcoreapp3.1 668μs 3.19μs 12.4μs 0.34 0 0 41.65 KB
#6257 WriteAndFlushEnrichedTraces net472 903μs 4.33μs 18.9μs 8.19 2.59 0.431 53.31 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.34μs 0.985ns 3.69ns 0.0143 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 1.76μs 1.76ns 6.83ns 0.0131 0 0 1.02 KB
master ExecuteNonQuery net472 2.05μs 1.84ns 7.12ns 0.157 0.00103 0 987 B
#6257 ExecuteNonQuery net6.0 1.36μs 0.817ns 3.06ns 0.0142 0 0 1.02 KB
#6257 ExecuteNonQuery netcoreapp3.1 1.75μs 2.11ns 8.19ns 0.0139 0 0 1.02 KB
#6257 ExecuteNonQuery net472 2.06μs 2.16ns 8.36ns 0.157 0.00104 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.27μs 0.534ns 2ns 0.0133 0 0 976 B
master CallElasticsearch netcoreapp3.1 1.55μs 0.877ns 3.28ns 0.0132 0 0 976 B
master CallElasticsearch net472 2.62μs 1.67ns 6.47ns 0.158 0 0 995 B
master CallElasticsearchAsync net6.0 1.29μs 0.46ns 1.78ns 0.0136 0 0 952 B
master CallElasticsearchAsync netcoreapp3.1 1.66μs 0.788ns 2.95ns 0.014 0 0 1.02 KB
master CallElasticsearchAsync net472 2.57μs 1.6ns 5.97ns 0.167 0 0 1.05 KB
#6257 CallElasticsearch net6.0 1.32μs 0.725ns 2.81ns 0.0139 0 0 976 B
#6257 CallElasticsearch netcoreapp3.1 1.61μs 0.727ns 2.81ns 0.0136 0 0 976 B
#6257 CallElasticsearch net472 2.58μs 2.44ns 9.43ns 0.157 0 0 995 B
#6257 CallElasticsearchAsync net6.0 1.24μs 1.2ns 4.47ns 0.0135 0 0 952 B
#6257 CallElasticsearchAsync netcoreapp3.1 1.57μs 0.848ns 3.28ns 0.0141 0 0 1.02 KB
#6257 CallElasticsearchAsync net472 2.74μs 1.53ns 5.93ns 0.167 0 0 1.05 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.24μs 0.418ns 1.56ns 0.0131 0 0 952 B
master ExecuteAsync netcoreapp3.1 1.69μs 0.393ns 1.42ns 0.0127 0 0 952 B
master ExecuteAsync net472 1.85μs 0.57ns 2.21ns 0.145 0 0 915 B
#6257 ExecuteAsync net6.0 1.26μs 0.633ns 2.45ns 0.0133 0 0 952 B
#6257 ExecuteAsync netcoreapp3.1 1.66μs 0.583ns 2.18ns 0.0125 0 0 952 B
#6257 ExecuteAsync net472 1.84μs 0.769ns 2.88ns 0.145 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 4.44μs 2.22ns 8.6ns 0.0311 0 0 2.31 KB
master SendAsync netcoreapp3.1 5.11μs 2.24ns 8.37ns 0.0383 0 0 2.85 KB
master SendAsync net472 7.19μs 2.21ns 8.57ns 0.493 0 0 3.12 KB
#6257 SendAsync net6.0 4.45μs 1.95ns 7.31ns 0.0311 0 0 2.31 KB
#6257 SendAsync netcoreapp3.1 5.33μs 6.26ns 24.2ns 0.0373 0 0 2.85 KB
#6257 SendAsync net472 7.24μs 3.26ns 12.6ns 0.495 0 0 3.12 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 1.55μs 0.814ns 3.04ns 0.0232 0 0 1.64 KB
master EnrichedLog netcoreapp3.1 2.14μs 6.14ns 23.8ns 0.0214 0 0 1.64 KB
master EnrichedLog net472 2.65μs 1.55ns 6.02ns 0.249 0 0 1.57 KB
#6257 EnrichedLog net6.0 1.48μs 1.02ns 3.82ns 0.023 0 0 1.64 KB
#6257 EnrichedLog netcoreapp3.1 2.23μs 1.11ns 4.15ns 0.0222 0 0 1.64 KB
#6257 EnrichedLog net472 2.65μs 1.04ns 3.91ns 0.249 0 0 1.57 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 120μs 115ns 446ns 0.0599 0 0 4.28 KB
master EnrichedLog netcoreapp3.1 124μs 92.3ns 357ns 0 0 0 4.28 KB
master EnrichedLog net472 152μs 137ns 529ns 0.684 0.228 0 4.46 KB
#6257 EnrichedLog net6.0 120μs 122ns 456ns 0 0 0 4.28 KB
#6257 EnrichedLog netcoreapp3.1 124μs 216ns 836ns 0.0623 0 0 4.28 KB
#6257 EnrichedLog net472 151μs 123ns 476ns 0.679 0.226 0 4.46 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 2.99μs 0.917ns 3.55ns 0.0314 0 0 2.2 KB
master EnrichedLog netcoreapp3.1 4.1μs 1.36ns 4.91ns 0.0286 0 0 2.2 KB
master EnrichedLog net472 4.82μs 1.16ns 4.47ns 0.32 0 0 2.02 KB
#6257 EnrichedLog net6.0 2.98μs 1.53ns 5.92ns 0.0299 0 0 2.2 KB
#6257 EnrichedLog netcoreapp3.1 4.11μs 1.23ns 4.77ns 0.0308 0 0 2.2 KB
#6257 EnrichedLog net472 4.94μs 0.726ns 2.81ns 0.319 0 0 2.02 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.35μs 0.38ns 1.42ns 0.0162 0 0 1.14 KB
master SendReceive netcoreapp3.1 1.73μs 0.869ns 3.25ns 0.0156 0 0 1.14 KB
master SendReceive net472 2.06μs 1.19ns 4.44ns 0.183 0 0 1.16 KB
#6257 SendReceive net6.0 1.31μs 0.57ns 2.13ns 0.0157 0 0 1.14 KB
#6257 SendReceive netcoreapp3.1 1.75μs 1.84ns 7.13ns 0.0156 0 0 1.14 KB
#6257 SendReceive net472 2.13μs 1.3ns 5.02ns 0.183 0 0 1.16 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 2.65μs 1.63ns 6.3ns 0.0226 0 0 1.6 KB
master EnrichedLog netcoreapp3.1 3.96μs 2.55ns 9.89ns 0.022 0 0 1.65 KB
master EnrichedLog net472 4.35μs 3.38ns 13.1ns 0.322 0 0 2.04 KB
#6257 EnrichedLog net6.0 2.91μs 1.07ns 3.86ns 0.0218 0 0 1.6 KB
#6257 EnrichedLog netcoreapp3.1 3.79μs 0.934ns 3.62ns 0.0228 0 0 1.65 KB
#6257 EnrichedLog net472 4.37μs 2.71ns 10.5ns 0.322 0 0 2.04 KB
Benchmarks.Trace.SpanBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #6257

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net6.0 1.195 477.52 570.43
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net6.0 1.170 399.48 467.49

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 399ns 0.725ns 2.81ns 0.00807 0 0 576 B
master StartFinishSpan netcoreapp3.1 590ns 1.42ns 5.51ns 0.00775 0 0 576 B
master StartFinishSpan net472 659ns 0.643ns 2.32ns 0.0916 0 0 578 B
master StartFinishScope net6.0 478ns 0.619ns 2.4ns 0.00968 0 0 696 B
master StartFinishScope netcoreapp3.1 705ns 1.06ns 4.1ns 0.0095 0 0 696 B
master StartFinishScope net472 844ns 1.45ns 5.62ns 0.105 0 0 658 B
#6257 StartFinishSpan net6.0 467ns 0.544ns 2.11ns 0.00815 0 0 576 B
#6257 StartFinishSpan netcoreapp3.1 561ns 2.93ns 14.9ns 0.00781 0 0 576 B
#6257 StartFinishSpan net472 669ns 1.35ns 5.23ns 0.0915 0 0 578 B
#6257 StartFinishScope net6.0 570ns 0.721ns 2.79ns 0.0099 0 0 696 B
#6257 StartFinishScope netcoreapp3.1 707ns 3.61ns 16.5ns 0.00951 0 0 696 B
#6257 StartFinishScope net472 877ns 1.47ns 5.71ns 0.104 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 656ns 0.758ns 2.94ns 0.00974 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 903ns 1.41ns 5.45ns 0.00941 0 0 696 B
master RunOnMethodBegin net472 1.06μs 1.46ns 5.66ns 0.105 0 0 658 B
#6257 RunOnMethodBegin net6.0 670ns 1.67ns 6.48ns 0.0097 0 0 696 B
#6257 RunOnMethodBegin netcoreapp3.1 992ns 1.93ns 7.47ns 0.00901 0 0 696 B
#6257 RunOnMethodBegin net472 1.17μs 2.8ns 10.9ns 0.105 0 0 658 B

{
var encodedBytes = PathwayContextEncoder.Encode(context.SpanContext.PathwayContext.Value);
var base64EncodedContext = Convert.ToBase64String(encodedBytes);
sb.AppendFormat("\"{0}\":\"{1}\",", DataStreamsPropagationHeaders.PropagationKeyBase64, base64EncodedContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't use AppendFormat it's much less performant (we can use $"" for the first one because it's embedding a constant so gets handled at compile time)

Suggested change
sb.AppendFormat("\"{0}\":\"{1}\",", DataStreamsPropagationHeaders.PropagationKeyBase64, base64EncodedContext);
sb.Append($"\"{DataStreamsPropagationHeaders.PropagationKeyBase64}\":\"");
.Append(base64EncodedContext)
.Append('"');

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, replaced.

var base64EncodedContext = Convert.ToBase64String(encodedBytes);
sb.AppendFormat("\"{0}\":\"{1}\",", DataStreamsPropagationHeaders.PropagationKeyBase64, base64EncodedContext);

if (Tracer.Instance.Settings.IsDataStreamsLegacyHeadersEnabled)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this has been said elsewhere, but I think we should def try to pass the tracer in from externally, it's not great to have static access to a tracer instance here (apart from anything else, it's going to make your unit tests impossibly flaky 🙁 )

if (Tracer.Instance.Settings.IsDataStreamsLegacyHeadersEnabled)
{
// Both PropagationKeyBase64 and PropagationKey use the Base64 encoded context
sb.AppendFormat("\"{0}\":\"{1}\",", DataStreamsPropagationHeaders.PropagationKey, base64EncodedContext);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't use AppendFormat

Suggested change
sb.AppendFormat("\"{0}\":\"{1}\",", DataStreamsPropagationHeaders.PropagationKey, base64EncodedContext);
```suggestion
sb.Append($"\"{DataStreamsPropagationHeaders.PropagationKey}\":\"");
.Append(base64EncodedContext)
.Append('"');

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, replaced.

Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted the calls to Tracer.Instance into additional overloads, so 🤞 the tests will pass now and not be flaky 🙂

sb.Append($"\"{DataStreamsPropagationHeaders.PropagationKeyBase64}\":\"")
.Append(base64EncodedContext)
.Append('"');
const string ddPathwayCtxBase64 = $"\"{DataStreamsPropagationHeaders.PropagationKeyBase64}\":\"";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This declaration/extraction wasn't necessary, just proves (to me) that it's definitely a const 😄

Comment on lines 45 to 47
Environment.SetEnvironmentVariable("DD_DATA_STREAMS_LEGACY_HEADERS", "false");
try
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in this file are just removing the Environment calls and try-finally, and passing the boolean in directly

{
// Both PropagationKeyBase64 and PropagationKey use the Base64 encoded context
const string ddPathwayCtx = $"\"{DataStreamsPropagationHeaders.PropagationKey}\":\"";
sb.Append(ddPathwayCtx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a comma here, but for some reason adding it in doesn't seem to get picked up locally 😖

The content that this produces is "dd-pathway-ctx-base64":"kjZ85G4hViqe65Xh6mSe65Xh6mQ=""dd-pathway-ctx":"kjZ85G4hViqe65Xh6mSe65Xh6mQ=","dd-pathway-ctx-base64":"a2paODVHNGhWaXFlNjVYaDZtU2U2NVhoNm1RPQ=="

note the missing comma and duplicated key?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into this at the moment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the JSON injection done here

  1. It didn't properly handle comma values between the JSON so it produced Newtonsoft deserialization errors
  2. It doesn't appear to be needed by my testing and was duplicating the headers.

And example of the JSONified headers now

{
    "x-datadog-trace-id": "5758925048254194083",
    "x-datadog-parent-id": "9282207551708089276",
    "x-datadog-sampling-priority": "1",
    "x-datadog-tags": "_dd.p.dm=-0,_dd.p.tid=6741191500000000",
    "traceparent": "00-67411915000000004febcfd1bd4a61a3-80d10696cb024bbc-01",
    "tracestate": "dd=s:1;p:80d10696cb024bbc;t.dm:-0",
    "dd-pathway-ctx-base64": "R0lmbmJPT210ZUd3L2MvazZtU3cvYy9rNm1RPQ==",
    "dd-pathway-ctx": "GIfnbOOmteGw/c/k6mSw/c/k6mQ="
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in be18958


// Internal for testing
internal void Inject<TCarrier>(PathwayContext context, TCarrier headers, bool isDataStreamsLegacyHeadersEnabled)
where TCarrier : IBinaryHeadersCollection
{
if (headers is null) { ThrowHelper.ThrowArgumentNullException(nameof(headers)); }

headers.Add(DataStreamsPropagationHeaders.PropagationKey, PathwayContextEncoder.Encode(context));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this likely needs to be removed, testing locally

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this, as it should be added below when checking isDataStreamsLegacyHeadersEnabled.
However, isDataStreamsLegacyHeadersEnabled was always false, so it appeared to be working as intended.

I fixed isDataStreamsLegacyHeadersEnabled returning false in 47d92fe

Removed this line in f48d1dd

Reviewing the produced JSON it appears accurate to my eyes now

@bouwkast bouwkast self-requested a review November 22, 2024 23:19
This appears to be handled already and doing it
here just dupes the content.

And it didn't add comma's between the JSON
fields which ccause JSON deserialization errors.

Additionally, it was re-encoding the Base64 again.
so that it isn't disabled.
This is added already below, but initially it
wasn't obivous because the legacy data streams
was always false.
Copy link
Contributor

Snapshots difference summary

The following differences have been observed in committed snapshots. It is meant to help the reviewer.
The diff is simplistic, so please check some files anyway while we improve it.

8 occurrences of :

-      aws.queue.name: MyAsyncSQSQueue,
-      aws.queue.url: http://localhost:00000/000000000000/MyAsyncSQSQueue,
+      aws.queue.name: MyAsyncSQSQueue2,
+      aws.queue.url: http://localhost:00000/000000000000/MyAsyncSQSQueue2,

2 occurrences of :

-      http.url: http://localhost:00000/000000000000/MyAsyncSQSQueue,
+      http.url: http://localhost:00000/000000000000/MyAsyncSQSQueue2,
[...]
-      queuename: MyAsyncSQSQueue,
+      queuename: MyAsyncSQSQueue2,

2 occurrences of :

-      queuename: MyAsyncSQSQueue,
+      queuename: MyAsyncSQSQueue2,

2 occurrences of :

-      http.url: http://localhost:00000/000000000000/MyAsyncSQSQueue,
+      http.url: http://localhost:00000/000000000000/MyAsyncSQSQueue2,
[...]
-      peer.service: MyAsyncSQSQueue,
-      queuename: MyAsyncSQSQueue,
+      peer.service: MyAsyncSQSQueue2,
+      queuename: MyAsyncSQSQueue2,

2 occurrences of :

-      peer.service: MyAsyncSQSQueue,
-      queuename: MyAsyncSQSQueue,
+      peer.service: MyAsyncSQSQueue2,
+      queuename: MyAsyncSQSQueue2,

Copy link
Contributor

@bouwkast bouwkast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will follow up on to see if the tests all pass now, but they appear to locally from what I can tell.

I updated snapshots, but it looks like they were initially updated and so I just un-updated them to get them working again.

@bouwkast
Copy link
Contributor

bouwkast commented Nov 23, 2024

I'm not super comfortable approving this and merging now that I have altered the code to the extent that I did :)

Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have someone from DSM re-review it

@@ -138,6 +138,7 @@ internal ImmutableTracerSettings(TracerSettings settings, bool unusedParamNotToU
IsActivityListenerEnabled = settings.IsActivityListenerEnabled;

_isDataStreamsMonitoringEnabled = settings.IsDataStreamsMonitoringEnabled;
IsDataStreamsLegacyHeadersEnabled = settings.IsDataStreamsLegacyHeadersEnabled;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lack of adding this originally feels like it should have been caught by a test 🤔 Feels like we're either missing some generalised testing, or something in this PR?

@@ -370,18 +370,18 @@
Tags: {
aws.agent: dotnet-aws-sdk,
aws.operation: DeleteMessageBatch,
aws.queue.name: MyAsyncSQSQueue,
aws.queue.url: http://localhost:00000/000000000000/MyAsyncSQSQueue,
aws.queue.name: MyAsyncSQSQueue2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand why these have all changed 😕

Copy link
Member

@lucaspimentel lucaspimentel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we need to look into tests (fixing existing ones and adding new ones), so I'm changing my approval for now so this doesn't get merged by accident 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants