Skip to content

Data Streams Monitoring support in Kinesis#6428

Merged
lucaspimentel merged 10 commits into
masterfrom
roisin.luddyhughes/dsm-kinesis-support
Dec 17, 2024
Merged

Data Streams Monitoring support in Kinesis#6428
lucaspimentel merged 10 commits into
masterfrom
roisin.luddyhughes/dsm-kinesis-support

Conversation

@roisinlh

Copy link
Copy Markdown
Contributor

Summary of changes

  • Added Data Streams Monitoring checkpoints to existing autoinstrumentation of Kinesis PutRecord[s][Async]
  • Added autoinstrumentation to Kinesis GetRecords[Async]

Reason for change

Data Streams Monitoring was not supported for Kinesis, this adds that functionality.

Implementation details

The existing producer instrumentation only works when StreamName is specified, not when StreamARN is specified. These changes leave that behavior unchanged at present.

The new consumer instrumentation is able to infer a StreamName from the [mandatory] StreamARN so that the producer and consumer can use the same naming system. The reverse would not be possible, and changing producer instrumentation to use ARNs instead would be a potentially-breaking change to existing users of the functionality so is outside the scope of this feature addition.

Test coverage

Other details

@roisinlh
roisinlh force-pushed the roisin.luddyhughes/dsm-kinesis-support branch from e4ef173 to 6d146a2 Compare December 12, 2024 09:53
@datadog-ddstaging

datadog-ddstaging Bot commented Dec 12, 2024

Copy link
Copy Markdown

Datadog Report

Branch report: roisin.luddyhughes/dsm-kinesis-support
Commit report: d6fd237
Test service: dd-trace-dotnet

✅ 0 Failed, 464472 Passed, 3674 Skipped, 32h 59m 38.8s Total Time

@andrewlock

andrewlock commented Dec 12, 2024

Copy link
Copy Markdown
Member

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 (6428) - mean (68ms)  : 66, 71
     .   : milestone, 68,
    master - mean (68ms)  : 65, 71
     .   : milestone, 68,

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (978ms)  : 952, 1003
     .   : milestone, 978,
    master - mean (980ms)  : 952, 1008
     .   : milestone, 980,

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

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (679ms)  : 664, 694
     .   : milestone, 679,
    master - mean (679ms)  : 663, 695
     .   : milestone, 679,

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

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (631ms)  : 614, 648
     .   : milestone, 631,
    master - mean (633ms)  : 616, 650
     .   : milestone, 633,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6428) - mean (193ms)  : 189, 198
     .   : milestone, 193,
    master - mean (193ms)  : 188, 198
     .   : milestone, 193,

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (1,100ms)  : 1073, 1127
     .   : milestone, 1100,
    master - mean (1,098ms)  : 1072, 1123
     .   : milestone, 1098,

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

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (869ms)  : 846, 891
     .   : milestone, 869,
    master - mean (868ms)  : 840, 895
     .   : milestone, 868,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6428) - mean (266ms)  : 261, 271
     .   : milestone, 266,
    master - mean (266ms)  : 262, 271
     .   : milestone, 266,

    section CallTarget+Inlining+NGEN
    This PR (6428) - mean (847ms)  : 808, 886
     .   : milestone, 847,
    master - mean (853ms)  : 824, 881
     .   : milestone, 853,

Loading

@andrewlock

andrewlock commented Dec 12, 2024

Copy link
Copy Markdown
Member

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 (6428) (11.069M)   : 0, 11068775
    master (11.244M)   : 0, 11243896
    benchmarks/2.9.0 (11.033M)   : 0, 11032866

    section Automatic
    This PR (6428) (7.340M)   : 0, 7339967
    master (7.201M)   : 0, 7201119
    benchmarks/2.9.0 (7.786M)   : 0, 7785853

    section Trace stats
    master (7.576M)   : 0, 7576229

    section Manual
    master (11.196M)   : 0, 11196081

    section Manual + Automatic
    This PR (6428) (6.726M)   : 0, 6726459
    master (6.638M)   : 0, 6638437

    section DD_TRACE_ENABLED=0
    master (10.422M)   : 0, 10421912

Loading
gantt
    title Throughput Linux arm64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (6428) (9.259M)   : 0, 9258827
    master (9.372M)   : 0, 9372216
    benchmarks/2.9.0 (9.495M)   : 0, 9494821

    section Automatic
    This PR (6428) (6.320M)   : 0, 6320356
    master (6.384M)   : 0, 6383601

    section Trace stats
    master (6.655M)   : 0, 6655008

    section Manual
    master (9.413M)   : 0, 9413276

    section Manual + Automatic
    This PR (6428) (5.968M)   : 0, 5967935
    master (5.896M)   : 0, 5895709

    section DD_TRACE_ENABLED=0
    master (8.890M)   : 0, 8890260

Loading
gantt
    title Throughput Windows x64 (Total requests) 
    dateFormat  X
    axisFormat %s
    section Baseline
    This PR (6428) (9.721M)   : 0, 9720629
    master (9.902M)   : 0, 9901561
    benchmarks/2.9.0 (10.020M)   : 0, 10019592

    section Automatic
    This PR (6428) (6.261M)   : crit ,0, 6260570
    master (6.645M)   : 0, 6645144
    benchmarks/2.9.0 (7.255M)   : 0, 7255257

    section Trace stats
    master (7.167M)   : 0, 7167171

    section Manual
    master (10.054M)   : 0, 10054191

    section Manual + Automatic
    This PR (6428) (5.850M)   : 0, 5850441
    master (6.071M)   : 0, 6070705

    section DD_TRACE_ENABLED=0
    master (9.440M)   : 0, 9439995

Loading

@andrewlock

andrewlock commented Dec 12, 2024

Copy link
Copy Markdown
Member

Benchmarks Report for tracer 🐌

Benchmarks for #6428 compared to master:

  • 1 benchmarks are slower, with geometric mean 1.130
  • 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 8μs 41.5ns 208ns 0.012 0.00399 0 5.62 KB
master StartStopWithChild netcoreapp3.1 10.2μs 53.7ns 289ns 0.0198 0.00496 0 5.81 KB
master StartStopWithChild net472 16.4μs 57.3ns 222ns 1.04 0.306 0.0911 6.21 KB
#6428 StartStopWithChild net6.0 7.69μs 33.6ns 121ns 0.0153 0.00765 0 5.61 KB
#6428 StartStopWithChild netcoreapp3.1 10.2μs 57.7ns 387ns 0.0148 0.00493 0 5.8 KB
#6428 StartStopWithChild net472 16.6μs 63.3ns 245ns 1.03 0.3 0.0832 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 498μs 227ns 850ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 663μs 509ns 1.91μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 855μs 1.05μs 4.07μs 0.431 0 0 3.3 KB
#6428 WriteAndFlushEnrichedTraces net6.0 482μs 426ns 1.6μs 0 0 0 2.7 KB
#6428 WriteAndFlushEnrichedTraces netcoreapp3.1 648μs 445ns 1.72μs 0 0 0 2.7 KB
#6428 WriteAndFlushEnrichedTraces net472 856μs 736ns 2.85μs 0.425 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 154μs 898ns 8.47μs 0.145 0 0 14.47 KB
master SendRequest netcoreapp3.1 176μs 1.57μs 15.4μs 0.191 0 0 17.27 KB
master SendRequest net472 0.00771ns 0.00183ns 0.0071ns 0 0 0 0 b
#6428 SendRequest net6.0 160μs 1.15μs 11.4μs 0.153 0 0 14.47 KB
#6428 SendRequest netcoreapp3.1 176μs 1.1μs 10.9μs 0.166 0 0 17.27 KB
#6428 SendRequest net472 0.0045ns 0.0012ns 0.00464ns 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 607μs 3.42μs 24μs 0.563 0 0 41.89 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 652μs 3.03μs 11.7μs 0.314 0 0 41.73 KB
master WriteAndFlushEnrichedTraces net472 859μs 3.98μs 15.4μs 8.04 2.23 0.446 53.27 KB
#6428 WriteAndFlushEnrichedTraces net6.0 602μs 3.39μs 25.4μs 0.553 0 0 41.68 KB
#6428 WriteAndFlushEnrichedTraces netcoreapp3.1 660μs 3.53μs 19.3μs 0.327 0 0 41.69 KB
#6428 WriteAndFlushEnrichedTraces net472 850μs 3.87μs 15μs 8.33 2.5 0.417 53.25 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.32μs 1.32ns 5.13ns 0.014 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 1.74μs 2.6ns 10.1ns 0.0131 0 0 1.02 KB
master ExecuteNonQuery net472 2.08μs 1.6ns 5.98ns 0.156 0.00103 0 987 B
#6428 ExecuteNonQuery net6.0 1.35μs 1.56ns 5.85ns 0.0144 0 0 1.02 KB
#6428 ExecuteNonQuery netcoreapp3.1 1.78μs 2.08ns 8.05ns 0.0132 0 0 1.02 KB
#6428 ExecuteNonQuery net472 2.13μs 2.92ns 11.3ns 0.156 0.00106 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.17μs 0.748ns 2.8ns 0.014 0 0 976 B
master CallElasticsearch netcoreapp3.1 1.53μs 1.71ns 6.61ns 0.0132 0 0 976 B
master CallElasticsearch net472 2.6μs 2.59ns 10ns 0.158 0 0 995 B
master CallElasticsearchAsync net6.0 1.4μs 1.02ns 3.81ns 0.0133 0 0 952 B
master CallElasticsearchAsync netcoreapp3.1 1.64μs 1.16ns 4.5ns 0.014 0 0 1.02 KB
master CallElasticsearchAsync net472 2.69μs 1.66ns 6.44ns 0.167 0 0 1.05 KB
#6428 CallElasticsearch net6.0 1.29μs 0.993ns 3.72ns 0.0134 0 0 976 B
#6428 CallElasticsearch netcoreapp3.1 1.55μs 0.977ns 3.66ns 0.0131 0 0 976 B
#6428 CallElasticsearch net472 2.52μs 1.67ns 6.25ns 0.158 0 0 995 B
#6428 CallElasticsearchAsync net6.0 1.37μs 1.3ns 5.05ns 0.0136 0 0 952 B
#6428 CallElasticsearchAsync netcoreapp3.1 1.64μs 1.31ns 5.06ns 0.0133 0 0 1.02 KB
#6428 CallElasticsearchAsync net472 2.7μs 1.71ns 6.15ns 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.32μs 0.363ns 1.41ns 0.0132 0 0 952 B
master ExecuteAsync netcoreapp3.1 1.63μs 0.754ns 2.92ns 0.013 0 0 952 B
master ExecuteAsync net472 1.83μs 0.44ns 1.7ns 0.145 0 0 915 B
#6428 ExecuteAsync net6.0 1.21μs 0.473ns 1.77ns 0.0133 0 0 952 B
#6428 ExecuteAsync netcoreapp3.1 1.63μs 2.08ns 7.78ns 0.0128 0 0 952 B
#6428 ExecuteAsync net472 1.85μs 0.681ns 2.55ns 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.48μs 1.8ns 6.72ns 0.0314 0 0 2.31 KB
master SendAsync netcoreapp3.1 5.34μs 2.38ns 8.92ns 0.0375 0 0 2.85 KB
master SendAsync net472 7.4μs 1.4ns 5.04ns 0.496 0 0 3.12 KB
#6428 SendAsync net6.0 4.46μs 2.04ns 7.62ns 0.0312 0 0 2.31 KB
#6428 SendAsync netcoreapp3.1 5.29μs 1.35ns 5.04ns 0.0373 0 0 2.85 KB
#6428 SendAsync net472 7.37μs 2.7ns 10.5ns 0.496 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.45μs 1.23ns 4.61ns 0.0234 0 0 1.64 KB
master EnrichedLog netcoreapp3.1 2.3μs 1.16ns 4.33ns 0.0219 0 0 1.64 KB
master EnrichedLog net472 2.78μs 2.36ns 9.15ns 0.25 0 0 1.57 KB
#6428 EnrichedLog net6.0 1.61μs 0.986ns 3.82ns 0.0231 0 0 1.64 KB
#6428 EnrichedLog netcoreapp3.1 2.12μs 0.918ns 3.44ns 0.0222 0 0 1.64 KB
#6428 EnrichedLog net472 2.65μs 1.6ns 6.2ns 0.25 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 116μs 225ns 870ns 0 0 0 4.28 KB
master EnrichedLog netcoreapp3.1 121μs 148ns 555ns 0.061 0 0 4.28 KB
master EnrichedLog net472 150μs 100ns 387ns 0.678 0.226 0 4.46 KB
#6428 EnrichedLog net6.0 119μs 323ns 1.25μs 0.0599 0 0 4.28 KB
#6428 EnrichedLog netcoreapp3.1 122μs 215ns 831ns 0 0 0 4.28 KB
#6428 EnrichedLog net472 151μs 176ns 636ns 0.69 0.23 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.95μs 1.06ns 3.83ns 0.0309 0 0 2.2 KB
master EnrichedLog netcoreapp3.1 4.23μs 1.67ns 6.48ns 0.0302 0 0 2.2 KB
master EnrichedLog net472 4.96μs 1.56ns 6.04ns 0.32 0 0 2.02 KB
#6428 EnrichedLog net6.0 2.98μs 1.52ns 5.87ns 0.0313 0 0 2.2 KB
#6428 EnrichedLog netcoreapp3.1 4.02μs 1.67ns 6.48ns 0.0282 0 0 2.2 KB
#6428 EnrichedLog net472 4.98μs 1.57ns 6.1ns 0.32 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.28μs 0.456ns 1.77ns 0.016 0 0 1.14 KB
master SendReceive netcoreapp3.1 1.84μs 2.17ns 8.39ns 0.0148 0 0 1.14 KB
master SendReceive net472 2.11μs 2.14ns 8.29ns 0.184 0 0 1.16 KB
#6428 SendReceive net6.0 1.37μs 0.801ns 3.1ns 0.0163 0 0 1.14 KB
#6428 SendReceive netcoreapp3.1 1.83μs 1.24ns 4.8ns 0.0156 0 0 1.14 KB
#6428 SendReceive net472 2.14μs 1.42ns 5.51ns 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.82μs 1.28ns 4.79ns 0.0226 0 0 1.6 KB
master EnrichedLog netcoreapp3.1 4.06μs 13.7ns 53ns 0.0216 0 0 1.65 KB
master EnrichedLog net472 4.38μs 13.1ns 50.6ns 0.322 0 0 2.04 KB
#6428 EnrichedLog net6.0 2.71μs 0.846ns 3.28ns 0.0218 0 0 1.6 KB
#6428 EnrichedLog netcoreapp3.1 4.01μs 1.49ns 5.56ns 0.022 0 0 1.65 KB
#6428 EnrichedLog net472 4.37μs 3.89ns 15.1ns 0.323 0 0 2.04 KB
Benchmarks.Trace.SpanBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #6428

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net6.0 1.130 480.46 542.70

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 417ns 0.297ns 1.15ns 0.00801 0 0 576 B
master StartFinishSpan netcoreapp3.1 610ns 0.354ns 1.37ns 0.00765 0 0 576 B
master StartFinishSpan net472 635ns 0.369ns 1.43ns 0.0916 0 0 578 B
master StartFinishScope net6.0 481ns 0.364ns 1.41ns 0.00962 0 0 696 B
master StartFinishScope netcoreapp3.1 735ns 0.449ns 1.74ns 0.00924 0 0 696 B
master StartFinishScope net472 880ns 0.576ns 2.23ns 0.104 0 0 658 B
#6428 StartFinishSpan net6.0 421ns 0.195ns 0.753ns 0.00806 0 0 576 B
#6428 StartFinishSpan netcoreapp3.1 558ns 0.51ns 1.98ns 0.0079 0 0 576 B
#6428 StartFinishSpan net472 643ns 0.377ns 1.46ns 0.0918 0 0 578 B
#6428 StartFinishScope net6.0 543ns 0.172ns 0.645ns 0.00979 0 0 696 B
#6428 StartFinishScope netcoreapp3.1 747ns 0.636ns 2.46ns 0.00975 0 0 696 B
#6428 StartFinishScope net472 850ns 0.551ns 2.14ns 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 619ns 0.27ns 1.04ns 0.00987 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 942ns 0.798ns 3.09ns 0.00934 0 0 696 B
master RunOnMethodBegin net472 1.11μs 0.544ns 2.04ns 0.104 0 0 658 B
#6428 RunOnMethodBegin net6.0 615ns 0.371ns 1.39ns 0.00984 0 0 696 B
#6428 RunOnMethodBegin netcoreapp3.1 930ns 0.628ns 2.35ns 0.0092 0 0 696 B
#6428 RunOnMethodBegin net472 1.07μs 0.569ns 2.2ns 0.104 0 0 658 B

@roisinlh
roisinlh force-pushed the roisin.luddyhughes/dsm-kinesis-support branch from 3e8e01e to afff658 Compare December 12, 2024 15:03
* Added DSM checkpoints to PutRecord/PutRecords
* Added instrumentation to GetRecords
@roisinlh
roisinlh force-pushed the roisin.luddyhughes/dsm-kinesis-support branch from afff658 to 391fcce Compare December 12, 2024 15:50
@roisinlh
roisinlh marked this pull request as ready for review December 12, 2024 17:12
@roisinlh
roisinlh requested review from a team as code owners December 12, 2024 17:12
@roisinlh

Copy link
Copy Markdown
Contributor Author

The test failures look unrelated and are failing for most other recent changes in the repo as well -- windows integ test occasionally and system_tests and friends from going past the 60-minute limit.

The unit tests and non-windows integration tests all succeeded and there is nothing platform-specific in these changes, so I do not expect these failing tests have missed coverage for anything significant.

@roisinlh

Copy link
Copy Markdown
Contributor Author

The CI run after the minor changes following up on Igor's comments passed all integ tests and had one failure in Linux unit tests, neither of which should have been impacted by the small changes in that commit, which makes me more confident that the test failures here are not a result of this change.

@vandonr

vandonr commented Dec 16, 2024

Copy link
Copy Markdown
Contributor

changing producer instrumentation to use ARNs instead would be a potentially-breaking change

I haven't reviewed the whole change yet, but I don't get why we don't do the ARN parsing for the producer too 🤔
Do you mean that it'd be potentially a breaking change to add a stream name tag where there was none before ? I don't think that's the kind of breaking change we're worried about... (but this can be tackled in a future PR)

var dataStreamsManager = Tracer.Instance.TracerManager.DataStreamsManager;
if (dataStreamsManager != null && dataStreamsManager.IsEnabled)
{
var edgeTags = new[] { "direction:out", $"topic:{streamName}", "type:kinesis" };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If streamName is nullable, shouldn't we add it only if it has a value ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is inside an outer block of if (scope?.Span.Context != null && !string.IsNullOrEmpty(streamName)) so it shouldn't get here if streamName has no value.

@roisinlh

roisinlh commented Dec 16, 2024

Copy link
Copy Markdown
Contributor Author

changing producer instrumentation to use ARNs instead would be a potentially-breaking change

I haven't reviewed the whole change yet, but I don't get why we don't do the ARN parsing for the producer too 🤔 Do you mean that it'd be potentially a breaking change to add a stream name tag where there was none before ? I don't think that's the kind of breaking change we're worried about... (but this can be tackled in a future PR)

The existing producer instrumentation supports only name, unlike other languages (like java) which support only ARN. The dotnet API allows either on producer, although ARN is preferred. This PR doesn't change that producer behavior (which would be the potentially-breaking change I refer to) and uses stream name as the DSM node name.

The consumer API allows only ARN, so the newly-added consumer has to support ARN. In order to be compatible with the dotnet producer instrumentation, the new consumer instrumentation extracts stream name from the ARN and uses that as the DSM node name.


return retval;
// Convert to Dictionary<string, object> to satisfy IHeadersCollection
return headers.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

btw I was wondering how often is this called ? Would it make sense to directly have a dict of <string, object> and make the casts when we need to modify the list ? This would allow us to avoid making a copy of the dictionary here...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The main path for this will be to create the adapter, add a small (<10) number of single entries, use it once, and destroy it.

The DSM manager is built around the expectation of some persistent headers that it can manipulate through the adapter interface, but because kinesis doesn't have headers or metadata this class is just wrapping a one-off that doesn't persist beyond one scope.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, this could be a (small) performance issue if it's used in every Kinesis call. Not only is it allocating a new dictionary every time, but it's doing it using a LINQ call (IEnumerable<KeyValuePair<string, List<string>>>.ToDictionary) which will itself probably allocate an enumerator as well and cause the dictionary to grow as needed, which is wasteful.

If nothing else, I would at least remove the LINQ code and pre-initialize the new dictionary to the required size. Something like:

var result = new Dictionary<string, object>(capacity: headers.Count);

foreach (var kvp in headers)
{
    result[kvp.Key] = kvp.Value;
}

return result;

It would be even better if the result was cacheable, or if it returned a sort of wrapper around headers instead of an entirely new object.

@bouwkast bouwkast left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could we add integrations tests for enabling Data Streams Monitoring for Kinesis?

Right now the testing of this seems to be a bit light.

For example:

@vandonr vandonr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM minus the tests, I gotta agree with Steven that we should have a test for Kinesis with DSM enabled.
It could be just an extra parameter to AwsKinesisTests maybe ?

@roisinlh
roisinlh requested a review from a team as a code owner December 17, 2024 18:53
return null;
}

var arnComponents = arn!.Split('/');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[performance] Not necessarily a blocker (we could come back and clean it up in a separate PR later), but if this code is in the app's hot path, we should do this in a way that doesn't allocate the arnComponents string array.

One approach could be to use IndexOf('/') twice. We also have a string.SplitIntoSpans() helper that splits a string into Span<char> tokens and enumerate over them.

Here's an example that uses both methods:

foreach (var pair in header.SplitIntoSpans(PairSeparator))
{
var span = pair.AsSpan();
// only the first `=` character is considered the separator.
// if there are multiple `=` characters, the rest are part of the value.
var separatorPosition = span.IndexOf(KeyAndValueSeparator);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added this to DSMON-490 tracking followup improvements, planned to be a fast-follow after the freeze.

@bouwkast bouwkast left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

As long as the tests pass LGTM


var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Consumer, null, out var tags);

string? streamName = AwsKinesisCommon.StreamNameFromARN(request.StreamARN);

@lucaspimentel lucaspimentel Dec 17, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not a blocker for this PR, but I think we can skip this call if the integration is disabled. (if scope or tags is null)


var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);

string? streamName = AwsKinesisCommon.StreamNameFromARN(request.StreamARN);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same comment as above about skipping AwsKinesisCommon.StreamNameFromARN() is not needed.

return Convert.FromBase64String(value[value.Count - 1]);
}

return new byte[0];

@lucaspimentel lucaspimentel Dec 17, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We aggressively try to avoid heap allocations. This returns the same array on every call instead of creating a new one:

Suggested change
return new byte[0];
return Array.Empty<byte>();

But C# these days has a newer syntax that will do the right thing:

Suggested change
return new byte[0];
return [];

@lucaspimentel lucaspimentel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM aside from a few non-blocking comments regarding heap allocations.

@roisinlh

Copy link
Copy Markdown
Contributor Author
  • installer_smoke_tests failed due to running longer than the 45-minute limit
  • integration_tests_windows and integration_tests_windows_iis failed on a couple seemingly-unrelated tests (followed by iis timing out. I am not sure if these failures are related to the same root cause referenced in [IAST] Skip failing tests #6455 but other platforms all succeeded.
    • Datadog.Trace.ClrProfiler.IntegrationTests.CI.PipesXUnitEvpTests.SubmitTraces for windows
    • Datadog.Trace.ClrProfiler.IntegrationTests.AspNetMvc4TestsCallTargetClassic.SubmitsTraces for iis

@lucaspimentel
lucaspimentel merged commit 4ed8511 into master Dec 17, 2024
@lucaspimentel
lucaspimentel deleted the roisin.luddyhughes/dsm-kinesis-support branch December 17, 2024 21:26
@github-actions github-actions Bot added this to the vNext-v3 milestone Dec 17, 2024
@andrewlock andrewlock added type:new-feature area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) area:data-streams-monitoring labels Dec 18, 2024
chojomok pushed a commit that referenced this pull request Jul 15, 2025
## Summary of changes

* Added Data Streams Monitoring checkpoints to existing
autoinstrumentation of Kinesis PutRecord[s][Async]
* Added autoinstrumentation to Kinesis GetRecords[Async]

## Reason for change

Data Streams Monitoring was not supported for Kinesis, this adds that
functionality.

## Implementation details

The existing producer instrumentation only works when StreamName is
specified, not when StreamARN is specified. These changes leave that
behavior unchanged at present.

The new consumer instrumentation is able to infer a StreamName from the
[mandatory] StreamARN so that the producer and consumer can use the same
naming system. The reverse would not be possible, and changing producer
instrumentation to use ARNs instead would be a potentially-breaking
change to existing users of the functionality so is outside the scope of
this feature addition.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) area:data-streams-monitoring type:new-feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants