Skip to content

[OTEL] OTLP Logs API Support#7680

Merged
link04 merged 11 commits intomasterfrom
maximo/otel-logs-api-support
Oct 22, 2025
Merged

[OTEL] OTLP Logs API Support#7680
link04 merged 11 commits intomasterfrom
maximo/otel-logs-api-support

Conversation

@link04
Copy link
Contributor

@link04 link04 commented Oct 21, 2025

Summary of changes

This PR implements OTLP Logs export for ILogger as part of the OpenTelemetry Logs RFC Key additions:

  • Custom OTLP Serializer: Protobuf writer using vendored OpenTelemetry utilities (no SDK dependency)
  • Multi-Protocol Support: gRPC transports and HTTP/protobuf
  • Auto-Instrumentation: Zero-touch enablement via DD_LOGS_OTEL_ENABLED=true
  • Configurations: Full support for OTEL_EXPORTER_OTLP_* environment variables

Reason for change

The [RFC] OpenTelemetry Logs API support enables customers using OpenTelemetry standards to migrate to Datadog SDK with minimal friction while allowing customers to continue to receive their logs as expected.

Implementation details

✅ Core Components:

  • OtlpLogsSerializer - Custom protobuf writer using vendored OTLP field constants (no external dependencies)
  • OtlpExporter - Multi-protocol exporter (HTTP/protobuf and gRPC) with configurable endpoint/headers/timeout
  • OtlpSubmissionLogSink - Batching sink that integrates with existing Direct Log Submission pipeline
  • LogPoint - Internal data model representing OTLP log records with trace/span IDs and attributes

✅ Vendored OpenTelemetry Components:

  • ProtobufSerializer - Low-level protobuf writer
  • ProtobufOtlpLogFieldNumberConstants - Official OTLP field numbers
  • OtlpHttpExportClient - HTTP/protobuf transport client

✅ Integration:

  • DirectSubmissionLogger auto-instrumentation detects OtlpSubmissionLogSinkand creates LogPoint objects
  • When OTLP logs are enabled, they take precedence over Datadog Direct Log Submission to send logs over OTLP instead.

Test coverage

Unit Tests:

  • OtlpSinkTests - Validates batching, trace context injection, attribute handling, severity mapping
  • TracerSettingsTests - Configuration parsing (protocol, endpoint, headers, timeout fallbacks)

Integration Tests:

  • OpenTelemetrySdkTests.SubmitsOtlpLogs - End-to-end validation with snapshot testing
  • Verifies OTLP payload structure and resource attributes
  • Confirms trace-log correlation with active spans

@link04 link04 requested review from a team as code owners October 21, 2025 00:05
@link04 link04 requested a review from anna-git October 21, 2025 00:05
@datadog-datadog-prod-us1

This comment has been minimized.

@dd-trace-dotnet-ci-bot
Copy link

dd-trace-dotnet-ci-bot bot commented Oct 21, 2025

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.8) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (74ms)  : 73, 76
     .   : milestone, 74,
    master - mean (73ms)  : 72, 74
     .   : milestone, 73,

    section Baseline
    This PR (7680) - mean (70ms)  : 68, 72
     .   : milestone, 70,
    master - mean (69ms)  : 68, 71
     .   : milestone, 69,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (1,073ms)  : 999, 1146
     .   : milestone, 1073,
    master - mean (1,068ms)  : 1007, 1130
     .   : milestone, 1068,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (111ms)  : 108, 114
     .   : milestone, 111,
    master - mean (112ms)  : 104, 121
     .   : milestone, 112,

    section Baseline
    This PR (7680) - mean (108ms)  : 106, 111
     .   : milestone, 108,
    master - mean (107ms)  : 104, 111
     .   : milestone, 107,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (756ms)  : 734, 779
     .   : milestone, 756,
    master - mean (756ms)  : 723, 789
     .   : milestone, 756,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (98ms)  : 96, 100
     .   : milestone, 98,
    master - mean (98ms)  : 97, 100
     .   : milestone, 98,

    section Baseline
    This PR (7680) - mean (97ms)  : 94, 100
     .   : milestone, 97,
    master - mean (98ms)  : 95, 100
     .   : milestone, 98,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (716ms)  : 685, 748
     .   : milestone, 716,
    master - mean (721ms)  : 689, 754
     .   : milestone, 721,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 8) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (96ms)  : 93, 99
     .   : milestone, 96,
    master - mean (97ms)  : 95, 99
     .   : milestone, 97,

    section Baseline
    This PR (7680) - mean (95ms)  : 92, 99
     .   : milestone, 95,
    master - mean (97ms)  : 95, 99
     .   : milestone, 97,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (668ms)  : 653, 683
     .   : milestone, 668,
    master - mean (677ms)  : 653, 701
     .   : milestone, 677,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.8) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (198ms)  : 192, 203
     .   : milestone, 198,
    master - mean (196ms)  : 193, 198
     .   : milestone, 196,

    section Baseline
    This PR (7680) - mean (193ms)  : 189, 197
     .   : milestone, 193,
    master - mean (193ms)  : 188, 197
     .   : milestone, 193,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (1,168ms)  : 1106, 1230
     .   : milestone, 1168,
    master - mean (1,170ms)  : 1103, 1237
     .   : milestone, 1170,

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

    section Baseline
    This PR (7680) - mean (277ms)  : 272, 282
     .   : milestone, 277,
    master - mean (277ms)  : 270, 283
     .   : milestone, 277,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (943ms)  : 903, 984
     .   : milestone, 943,
    master - mean (942ms)  : 905, 980
     .   : milestone, 942,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (270ms)  : 266, 274
     .   : milestone, 270,
    master - mean (269ms)  : 266, 272
     .   : milestone, 269,

    section Baseline
    This PR (7680) - mean (272ms)  : 266, 277
     .   : milestone, 272,
    master - mean (269ms)  : 266, 273
     .   : milestone, 269,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (937ms)  : 879, 995
     .   : milestone, 937,
    master - mean (933ms)  : 874, 992
     .   : milestone, 933,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Bailout
    This PR (7680) - mean (269ms)  : 266, 271
     .   : milestone, 269,
    master - mean (269ms)  : 266, 272
     .   : milestone, 269,

    section Baseline
    This PR (7680) - mean (270ms)  : 264, 275
     .   : milestone, 270,
    master - mean (269ms)  : 264, 274
     .   : milestone, 269,

    section CallTarget+Inlining+NGEN
    This PR (7680) - mean (854ms)  : 834, 874
     .   : milestone, 854,
    master - mean (856ms)  : 840, 872
     .   : milestone, 856,

Loading

@pr-commenter
Copy link

pr-commenter bot commented Oct 21, 2025

Benchmarks

Benchmarks Report for benchmark platform 🐌

Benchmarks for #7680 compared to master:

  • 1 benchmarks are slower, with geometric mean 2.497
  • 5 benchmarks have fewer allocations
  • 12 benchmarks have more 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 ✔️ More allocations ⚠️

More allocations ⚠️ in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑net472 6.02 KB 6.09 KB 72 B 1.20%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 10.1μs 37.4ns 140ns 0 0 0 5.52 KB
master StartStopWithChild netcoreapp3.1 13.3μs 67.2ns 300ns 0 0 0 5.71 KB
master StartStopWithChild net472 21.9μs 108ns 618ns 1.03 0.343 0.114 6.02 KB
#7680 StartStopWithChild net6.0 10.3μs 57.9ns 384ns 0 0 0 5.51 KB
#7680 StartStopWithChild netcoreapp3.1 13μs 68.6ns 363ns 0 0 0 5.7 KB
#7680 StartStopWithChild net472 22.2μs 122ns 781ns 0.911 0.228 0 6.09 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 949μs 304ns 1.14μs 0 0 0 2.71 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 1.02ms 208ns 750ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 1.19ms 88.7ns 320ns 0 0 0 3.31 KB
#7680 WriteAndFlushEnrichedTraces net6.0 940μs 249ns 963ns 0 0 0 2.7 KB
#7680 WriteAndFlushEnrichedTraces netcoreapp3.1 1.03ms 346ns 1.34μs 0 0 0 2.7 KB
#7680 WriteAndFlushEnrichedTraces net472 1.2ms 1.56μs 5.85μs 0 0 0 3.31 KB
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑net6.0 179.56 KB 186.08 KB 6.51 KB 3.63%
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net6.0 183.08 KB 189.6 KB 6.51 KB 3.56%
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑netcoreapp3.1 185.32 KB 191.8 KB 6.48 KB 3.50%
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑netcoreapp3.1 188.75 KB 195.23 KB 6.48 KB 3.43%
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleSimpleBody‑net472 205.41 KB 208.12 KB 2.71 KB 1.32%
Benchmarks.Trace.Asm.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 208.94 KB 211.66 KB 2.72 KB 1.30%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 354μs 167ns 625ns 0 0 0 179.56 KB
master AllCycleSimpleBody netcoreapp3.1 505μs 831ns 3.32μs 0 0 0 185.32 KB
master AllCycleSimpleBody net472 466μs 119ns 446ns 32.4 0 0 205.41 KB
master AllCycleMoreComplexBody net6.0 363μs 380ns 1.47μs 0 0 0 183.08 KB
master AllCycleMoreComplexBody netcoreapp3.1 535μs 1.39μs 5.4μs 0 0 0 188.75 KB
master AllCycleMoreComplexBody net472 480μs 121ns 470ns 31.2 0 0 208.94 KB
master ObjectExtractorSimpleBody net6.0 317ns 1.76ns 10.7ns 0 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 396ns 2.19ns 13.5ns 0 0 0 272 B
master ObjectExtractorSimpleBody net472 297ns 0.017ns 0.0613ns 0.0434 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 6.27μs 23.6ns 91.2ns 0 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 7.81μs 36.5ns 146ns 0 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 6.73μs 4.25ns 16.5ns 0.571 0 0 3.8 KB
#7680 AllCycleSimpleBody net6.0 361μs 1.07μs 4.13μs 0 0 0 186.08 KB
#7680 AllCycleSimpleBody netcoreapp3.1 530μs 1.41μs 5.46μs 0 0 0 191.8 KB
#7680 AllCycleSimpleBody net472 477μs 92.9ns 348ns 32.4 0 0 208.12 KB
#7680 AllCycleMoreComplexBody net6.0 372μs 115ns 446ns 0 0 0 189.6 KB
#7680 AllCycleMoreComplexBody netcoreapp3.1 529μs 1.32μs 5.12μs 0 0 0 195.23 KB
#7680 AllCycleMoreComplexBody net472 485μs 101ns 390ns 31.2 0 0 211.66 KB
#7680 ObjectExtractorSimpleBody net6.0 314ns 1.81ns 13.4ns 0 0 0 280 B
#7680 ObjectExtractorSimpleBody netcoreapp3.1 396ns 2.24ns 14.8ns 0 0 0 272 B
#7680 ObjectExtractorSimpleBody net472 300ns 0.05ns 0.194ns 0.0443 0 0 281 B
#7680 ObjectExtractorMoreComplexBody net6.0 6.25μs 33.6ns 178ns 0 0 0 3.78 KB
#7680 ObjectExtractorMoreComplexBody netcoreapp3.1 7.69μs 36.2ns 145ns 0 0 0 3.69 KB
#7680 ObjectExtractorMoreComplexBody net472 6.74μs 2.99ns 11.6ns 0.573 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.5μs 213ns 826ns 0 0 0 32.4 KB
master EncodeArgs netcoreapp3.1 97μs 58.8ns 220ns 0 0 0 32.4 KB
master EncodeArgs net472 111μs 61.9ns 240ns 5.01 0 0 32.51 KB
master EncodeLegacyArgs net6.0 146μs 53ns 198ns 0 0 0 2.15 KB
master EncodeLegacyArgs netcoreapp3.1 197μs 180ns 696ns 0 0 0 2.14 KB
master EncodeLegacyArgs net472 262μs 130ns 505ns 0 0 0 2.16 KB
#7680 EncodeArgs net6.0 76.5μs 18.6ns 69.6ns 0 0 0 32.4 KB
#7680 EncodeArgs netcoreapp3.1 96.7μs 223ns 862ns 0 0 0 32.4 KB
#7680 EncodeArgs net472 109μs 45.8ns 171ns 4.91 0 0 32.51 KB
#7680 EncodeLegacyArgs net6.0 145μs 10.8ns 38.8ns 0 0 0 2.14 KB
#7680 EncodeLegacyArgs netcoreapp3.1 198μs 140ns 541ns 0 0 0 2.14 KB
#7680 EncodeLegacyArgs net472 261μs 27.5ns 106ns 0 0 0 2.16 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #7680

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Asm.AppSecWafBenchmark.RunWafRealisticBenchmarkWithAttack‑netcoreapp3.1 2.497 294,660.34 735,684.00

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWafRealisticBenchmark net6.0 390μs 55ns 206ns 0 0 0 4.56 KB
master RunWafRealisticBenchmark netcoreapp3.1 414μs 81.3ns 315ns 0 0 0 4.48 KB
master RunWafRealisticBenchmark net472 428μs 42.5ns 165ns 0 0 0 4.66 KB
master RunWafRealisticBenchmarkWithAttack net6.0 286μs 39ns 151ns 0 0 0 2.24 KB
master RunWafRealisticBenchmarkWithAttack netcoreapp3.1 295μs 113ns 421ns 0 0 0 2.22 KB
master RunWafRealisticBenchmarkWithAttack net472 310μs 26.7ns 99.8ns 0 0 0 2.29 KB
#7680 RunWafRealisticBenchmark net6.0 394μs 164ns 612ns 0 0 0 4.55 KB
#7680 RunWafRealisticBenchmark netcoreapp3.1 419μs 466ns 1.8μs 0 0 0 4.48 KB
#7680 RunWafRealisticBenchmark net472 427μs 60.9ns 228ns 0 0 0 4.66 KB
#7680 RunWafRealisticBenchmarkWithAttack net6.0 288μs 32.6ns 122ns 0 0 0 2.24 KB
#7680 RunWafRealisticBenchmarkWithAttack netcoreapp3.1 679μs 12.8μs 128μs 0 0 0 2.22 KB
#7680 RunWafRealisticBenchmarkWithAttack net472 309μs 45ns 174ns 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 61μs 137ns 512ns 0 0 0 14.52 KB
master SendRequest netcoreapp3.1 72μs 55.1ns 199ns 0 0 0 17.42 KB
master SendRequest net472 0.00321ns 0.00135ns 0.00525ns 0 0 0 0 b
#7680 SendRequest net6.0 61.5μs 78.6ns 283ns 0 0 0 14.52 KB
#7680 SendRequest netcoreapp3.1 71.2μs 145ns 523ns 0 0 0 17.42 KB
#7680 SendRequest net472 0.00152ns 0.00122ns 0.00457ns 0 0 0 0 b
Benchmarks.Trace.CharSliceBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net472 0 b 73 B 73 B
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net472 0 b 47 B 47 B
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSlice‑net6.0 4 B 6 B 2 B 50.00%

Fewer allocations 🎉 in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool‑net6.0 2 B 1 B -1 B -50.00%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master OriginalCharSlice net6.0 1.89ms 507ns 1.83μs 0 0 0 640.01 KB
master OriginalCharSlice netcoreapp3.1 2.11ms 8.17μs 31.7μs 0 0 0 640 KB
master OriginalCharSlice net472 2.66ms 155ns 579ns 100 0 0 641.95 KB
master OptimizedCharSlice net6.0 1.37ms 250ns 970ns 0 0 0 4 B
master OptimizedCharSlice netcoreapp3.1 1.68ms 356ns 1.38μs 0 0 0 1 B
master OptimizedCharSlice net472 2ms 421ns 1.63μs 0 0 0 0 b
master OptimizedCharSliceWithPool net6.0 832μs 10.9ns 37.9ns 0 0 0 2 B
master OptimizedCharSliceWithPool netcoreapp3.1 816μs 203ns 758ns 0 0 0 0 b
master OptimizedCharSliceWithPool net472 1.13ms 97.7ns 365ns 0 0 0 0 b
#7680 OriginalCharSlice net6.0 2.05ms 1.25μs 4.69μs 0 0 0 640.01 KB
#7680 OriginalCharSlice netcoreapp3.1 2.05ms 7.81μs 28.2μs 0 0 0 640 KB
#7680 OriginalCharSlice net472 2.67ms 508ns 1.97μs 100 0 0 641.95 KB
#7680 OptimizedCharSlice net6.0 1.34ms 216ns 837ns 0 0 0 6 B
#7680 OptimizedCharSlice netcoreapp3.1 1.73ms 776ns 3.01μs 0 0 0 1 B
#7680 OptimizedCharSlice net472 1.99ms 316ns 1.18μs 0 0 0 73 B
#7680 OptimizedCharSliceWithPool net6.0 803μs 66.1ns 256ns 0 0 0 1 B
#7680 OptimizedCharSliceWithPool netcoreapp3.1 871μs 53.4ns 207ns 0 0 0 0 b
#7680 OptimizedCharSliceWithPool net472 1.15ms 111ns 429ns 0 0 0 47 B
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑netcoreapp3.1 41.91 KB 42.7 KB 796 B 1.90%

Fewer allocations 🎉 in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0 42.57 KB 41.7 KB -870 B -2.04%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 657μs 613ns 2.21μs 0 0 0 42.57 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 686μs 3.9μs 30.2μs 0 0 0 41.91 KB
master WriteAndFlushEnrichedTraces net472 902μs 4.34μs 17.4μs 8.33 0 0 56.39 KB
#7680 WriteAndFlushEnrichedTraces net6.0 646μs 2.11μs 8.17μs 0 0 0 41.7 KB
#7680 WriteAndFlushEnrichedTraces netcoreapp3.1 711μs 5.39μs 53.3μs 0 0 0 42.7 KB
#7680 WriteAndFlushEnrichedTraces net472 856μs 4.19μs 17.8μs 8.33 0 0 56.39 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.9μs 2.87ns 10.7ns 0 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 2.51μs 1.39ns 5.01ns 0 0 0 1.02 KB
master ExecuteNonQuery net472 2.89μs 3.45ns 12.4ns 0.144 0.0144 0 987 B
#7680 ExecuteNonQuery net6.0 1.9μs 9.47ns 42.3ns 0 0 0 1.02 KB
#7680 ExecuteNonQuery netcoreapp3.1 2.71μs 9.37ns 36.3ns 0 0 0 1.02 KB
#7680 ExecuteNonQuery net472 2.73μs 2.85ns 11ns 0.149 0.0136 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.84μs 8.84ns 34.2ns 0 0 0 1.03 KB
master CallElasticsearch netcoreapp3.1 2.23μs 11ns 43.8ns 0 0 0 1.03 KB
master CallElasticsearch net472 3.62μs 1.62ns 6.05ns 0.163 0 0 1.04 KB
master CallElasticsearchAsync net6.0 1.86μs 9.8ns 50ns 0 0 0 1.01 KB
master CallElasticsearchAsync netcoreapp3.1 2.34μs 9.05ns 35ns 0 0 0 1.08 KB
master CallElasticsearchAsync net472 3.8μs 6.01ns 23.3ns 0.17 0 0 1.1 KB
#7680 CallElasticsearch net6.0 1.69μs 8.59ns 42.1ns 0 0 0 1.03 KB
#7680 CallElasticsearch netcoreapp3.1 2.29μs 9.87ns 38.2ns 0 0 0 1.03 KB
#7680 CallElasticsearch net472 3.53μs 2.91ns 11.3ns 0.159 0 0 1.04 KB
#7680 CallElasticsearchAsync net6.0 1.81μs 8.25ns 30.9ns 0 0 0 1.01 KB
#7680 CallElasticsearchAsync netcoreapp3.1 2.43μs 4.51ns 16.9ns 0 0 0 1.08 KB
#7680 CallElasticsearchAsync net472 3.7μs 2.8ns 10.9ns 0.166 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.83μs 2.75ns 10.7ns 0 0 0 952 B
master ExecuteAsync netcoreapp3.1 2.35μs 4.03ns 15.6ns 0 0 0 952 B
master ExecuteAsync net472 2.56μs 4.02ns 15.6ns 0.141 0 0 915 B
#7680 ExecuteAsync net6.0 1.79μs 4.46ns 17.3ns 0 0 0 952 B
#7680 ExecuteAsync netcoreapp3.1 2.33μs 0.826ns 3.09ns 0 0 0 952 B
#7680 ExecuteAsync net472 2.66μs 4.47ns 17.3ns 0.134 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 6.85μs 3.06ns 11.8ns 0 0 0 2.36 KB
master SendAsync netcoreapp3.1 8.41μs 21ns 81.5ns 0 0 0 2.9 KB
master SendAsync net472 12.7μs 9.9ns 38.3ns 0.444 0 0 3.18 KB
#7680 SendAsync net6.0 6.82μs 23.5ns 84.7ns 0 0 0 2.36 KB
#7680 SendAsync netcoreapp3.1 8.53μs 34.8ns 135ns 0 0 0 2.9 KB
#7680 SendAsync net472 12.5μs 11.3ns 43.9ns 0.498 0 0 3.18 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net472 279.92 KB 286.72 KB 6.8 KB 2.43%

Fewer allocations 🎉 in #7680

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑netcoreapp3.1 43.23 KB 42.69 KB -544 B -1.26%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 258.08 KB 249.47 KB -8.61 KB -3.34%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0 45.61 KB 43.87 KB -1.74 KB -3.81%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark net6.0 45.4μs 282ns 2.63μs 0 0 0 45.61 KB
master StringConcatBenchmark netcoreapp3.1 49.7μs 289ns 2.33μs 0 0 0 43.23 KB
master StringConcatBenchmark net472 56.5μs 293ns 1.44μs 0 0 0 65.54 KB
master StringConcatAspectBenchmark net6.0 464μs 829ns 2.87μs 0 0 0 258.08 KB
master StringConcatAspectBenchmark netcoreapp3.1 533μs 828ns 2.99μs 0 0 0 276.3 KB
master StringConcatAspectBenchmark net472 401μs 2.01μs 8.76μs 0 0 0 279.92 KB
#7680 StringConcatBenchmark net6.0 41.3μs 163ns 673ns 0 0 0 43.87 KB
#7680 StringConcatBenchmark netcoreapp3.1 47.9μs 271ns 1.82μs 0 0 0 42.69 KB
#7680 StringConcatBenchmark net472 57μs 297ns 1.39μs 0 0 0 65.54 KB
#7680 StringConcatAspectBenchmark net6.0 449μs 1.85μs 8.07μs 0 0 0 249.47 KB
#7680 StringConcatAspectBenchmark netcoreapp3.1 544μs 1.36μs 5.08μs 0 0 0 276.35 KB
#7680 StringConcatAspectBenchmark net472 403μs 2.01μs 8.78μs 0 0 0 286.72 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.51μs 12.6ns 56.1ns 0 0 0 1.7 KB
master EnrichedLog netcoreapp3.1 3.59μs 7.47ns 26.9ns 0 0 0 1.7 KB
master EnrichedLog net472 3.77μs 1.71ns 6.39ns 0.245 0 0 1.64 KB
#7680 EnrichedLog net6.0 2.53μs 0.48ns 1.8ns 0 0 0 1.7 KB
#7680 EnrichedLog netcoreapp3.1 3.57μs 16.4ns 65.6ns 0 0 0 1.7 KB
#7680 EnrichedLog net472 3.87μs 7.51ns 29.1ns 0.253 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 122μs 32.8ns 123ns 0 0 0 4.31 KB
master EnrichedLog netcoreapp3.1 128μs 145ns 523ns 0 0 0 4.31 KB
master EnrichedLog net472 166μs 44.4ns 172ns 0 0 0 4.51 KB
#7680 EnrichedLog net6.0 121μs 30.2ns 109ns 0 0 0 4.31 KB
#7680 EnrichedLog netcoreapp3.1 127μs 55.2ns 199ns 0 0 0 4.31 KB
#7680 EnrichedLog net472 167μs 32.4ns 125ns 0 0 0 4.51 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.22μs 17.2ns 66.4ns 0 0 0 2.26 KB
master EnrichedLog netcoreapp3.1 6.73μs 4.53ns 16.9ns 0 0 0 2.26 KB
master EnrichedLog net472 7.73μs 4.39ns 15.8ns 0.308 0 0 2.08 KB
#7680 EnrichedLog net6.0 5.01μs 23.8ns 92.1ns 0 0 0 2.26 KB
#7680 EnrichedLog netcoreapp3.1 6.93μs 6.4ns 24.8ns 0 0 0 2.26 KB
#7680 EnrichedLog net472 7.47μs 4.54ns 17.6ns 0.297 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.95μs 1.44ns 5.57ns 0 0 0 1.2 KB
master SendReceive netcoreapp3.1 2.62μs 9.59ns 37.1ns 0 0 0 1.2 KB
master SendReceive net472 3.25μs 5.62ns 21.8ns 0.178 0 0 1.2 KB
#7680 SendReceive net6.0 2.05μs 10.8ns 55.3ns 0 0 0 1.2 KB
#7680 SendReceive netcoreapp3.1 2.61μs 12.6ns 52.1ns 0 0 0 1.2 KB
#7680 SendReceive net472 3.13μs 2.64ns 10.2ns 0.187 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.37μs 6.22ns 24.1ns 0 0 0 1.58 KB
master EnrichedLog netcoreapp3.1 5.6μs 13.4ns 51.9ns 0 0 0 1.63 KB
master EnrichedLog net472 6.5μs 5.63ns 21.8ns 0.292 0 0 2.03 KB
#7680 EnrichedLog net6.0 4.43μs 16.4ns 63.5ns 0 0 0 1.58 KB
#7680 EnrichedLog netcoreapp3.1 5.59μs 13.3ns 51.7ns 0 0 0 1.63 KB
#7680 EnrichedLog net472 6.82μs 6.38ns 24.7ns 0.305 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 751ns 1.18ns 4.57ns 0 0 0 576 B
master StartFinishSpan netcoreapp3.1 952ns 4.83ns 23.7ns 0 0 0 576 B
master StartFinishSpan net472 913ns 0.48ns 1.86ns 0.0874 0 0 578 B
master StartFinishScope net6.0 911ns 4.67ns 22.9ns 0 0 0 696 B
master StartFinishScope netcoreapp3.1 1.16μs 6.05ns 27.7ns 0 0 0 696 B
master StartFinishScope net472 1.14μs 1.13ns 4.38ns 0.103 0 0 658 B
#7680 StartFinishSpan net6.0 759ns 3.87ns 18.1ns 0 0 0 576 B
#7680 StartFinishSpan netcoreapp3.1 964ns 0.393ns 1.52ns 0 0 0 576 B
#7680 StartFinishSpan net472 932ns 0.124ns 0.43ns 0.0889 0 0 578 B
#7680 StartFinishScope net6.0 896ns 4.58ns 24.2ns 0 0 0 696 B
#7680 StartFinishScope netcoreapp3.1 1.18μs 6.04ns 28.9ns 0 0 0 696 B
#7680 StartFinishScope net472 1.12μs 0.509ns 1.97ns 0.101 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.02μs 5.62ns 34.2ns 0 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 1.42μs 7.19ns 33ns 0 0 0 696 B
master RunOnMethodBegin net472 1.41μs 2.97ns 11.5ns 0.0991 0 0 658 B
#7680 RunOnMethodBegin net6.0 1.03μs 0.87ns 3.37ns 0 0 0 696 B
#7680 RunOnMethodBegin netcoreapp3.1 1.44μs 5.94ns 23ns 0 0 0 696 B
#7680 RunOnMethodBegin net472 1.46μs 3.88ns 15ns 0.101 0 0 658 B

{
}

public void BufferExceededMaxSize(string signalType, int bufferSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

This file will be good for implementing telemetry metrics, though this is a central place for all signals not just Logs or not just Metrics 🤔

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.

Nice work, I think there's various cleanup we can do but overall, if it works! 😄

Comment on lines +240 to +243
<type fullname="System.Diagnostics.Activity" />
<type fullname="System.Diagnostics.ActivityIdFormat" />
<type fullname="System.Diagnostics.ActivitySpanId" />
<type fullname="System.Diagnostics.ActivityTraceId" />
Copy link
Member

Choose a reason for hiding this comment

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

I'm kind of surprised we don't reference these already, and it suggests to me we probably are doing something wrong here, but I don't know enough about it off hand 🤔 I expect @zacharycmontoya can shed light

Copy link
Contributor

Choose a reason for hiding this comment

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

In the metrics PR Maximo recently did, there was no use of Activity. In this PR we are accessing the current trace-id and span-id from Activity.Current (since this is running only on netcoreapp3.1+) and this is the first time we're calling it directly. I too was surprised seeing this.

My advice is to use our own active Trace ID rather than the Activity one, or at least prefer our own Trace ID then fall back to Activity, since we're likely using our tracing integration as well

Comment on lines +26 to +29
#if NETCOREAPP3_1_OR_GREATER
public LogPoint? OtlpLog { get; set; }
#endif

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm, ok, this is making me wonder if we should restructure this entirely 🤔

Currently you're using the LoggerDirectSubmissionLogEvent to "smuggle" this LogPoint into the sink. But really LogPoint and LoggerDirectSubmissionLogEvent are kind of the two different types of event I think?

Which makes me wonder if we should refactor the abstractions in general, but looking at it right now, I'm not exactly sure how to make that change/introduce that seam. I think the answer is probably that it should be in DirectSubmissionLogger - we should have two different types, and they should just use two different implementations. But again, I think that's something we can safely improve/refactor later

writePosition = WriteResourceAttribute(buffer, writePosition, "deployment.environment", settings.Environment!);
}

if (settings.GlobalTags.Count > 0)
Copy link
Member

Choose a reason for hiding this comment

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

PSA, these can change at runtime so we will need to handle that soon with MutableSettings

internal const DirectSubmissionLogLevel OtlpMinimumLevel = DirectSubmissionLogLevel.Verbose;
internal const int OtlpBatchSizeLimit = 512; // OTEL_BLRP_MAX_EXPORT_BATCH_SIZE
internal const int OtlpQueueSizeLimit = 2048; // OTEL_BLRP_MAX_QUEUE_SIZE
internal const int OtlpBatchPeriodSeconds = 1; // OTEL_BLRP_SCHEDULE_DELAY
Copy link
Contributor

Choose a reason for hiding this comment

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

Note for later: OTEL_BLRP_SCHEDULE_DELAY is in milliseconds, whereas our previous configuration was in seconds. We will want to look into updating the previous config to accept milliseconds so these two settings are more interoperable

Copy link
Contributor

@zacharycmontoya zacharycmontoya left a comment

Choose a reason for hiding this comment

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

Looking through the PR, I left some comments throughout but the most important for me are the comments regarding testing. I'd like to resolve those and other parts can be refined later

@link04 link04 force-pushed the maximo/otel-logs-api-support branch from 25e4bf4 to e9b9a4c Compare October 21, 2025 21:24
Copy link
Contributor

@zacharycmontoya zacharycmontoya left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@link04 link04 merged commit 042cf47 into master Oct 22, 2025
152 checks passed
@link04 link04 deleted the maximo/otel-logs-api-support branch October 22, 2025 02:45
@github-actions github-actions bot added this to the vNext-v3 milestone Oct 22, 2025
@andrewlock andrewlock added area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) type:new-feature area:opentelemetry OpenTelemetry support labels Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:opentelemetry OpenTelemetry support area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) type:new-feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants