dd-trace-dotnet icon indicating copy to clipboard operation
dd-trace-dotnet copied to clipboard

Fix null enumerator in W3CTraceContextPropagator

Open datadog-datadog-prod-us1[bot] opened this issue 1 month ago • 3 comments

Open Bits Dev Session

You can ask for changes by mentioning @datadog in a comment.

Feedback (especially what can be better) welcome in #code-gen-feedback!


Summary of changes

Fixed a NullReferenceException in W3CTraceContextPropagator.TryGetSingleRare that occurs when GetEnumerator() returns null.

Reason for change

The tracer was throwing a NullReferenceException during trace context extraction when encountering a poorly-implemented IEnumerable<string?> that returns null from GetEnumerator(). While this violates best practices, the tracer should handle this edge case gracefully rather than crashing.

Implementation details

Modified W3CTraceContextPropagator.TryGetSingleRare to:

  1. Store the result of GetEnumerator() in a variable before attempting to use it
  2. Check if the enumerator is null and return false if so
  3. Use a traditional using block instead of using var to ensure proper disposal after the null check

Test coverage

Added unit test TryGetSingleRare_ShouldReturnFalse_WhenGetEnumeratorReturnsNull that verifies the method returns false and doesn't throw when GetEnumerator() returns null.

Other details

Error Details:

Stack Trace
System.NullReferenceException
   at Datadog.Trace.Propagators.W3CTraceContextPropagator.TryGetSingleRare(IEnumerable`1 values, String& value)
   at Datadog.Trace.Propagators.W3CTraceContextPropagator.TryExtract[TCarrier,TCarrierGetter](TCarrier carrier, TCarrierGetter carrierGetter, PropagationContext& context)
   at Datadog.Trace.Propagators.SpanContextPropagator.Extract[TCarrier,TCarrierGetter](TCarrier carrier, TCarrierGetter carrierGetter)
   at Datadog.Trace.SpanContextExtractor.ExtractInternal[TCarrier](TCarrier carrier, Func`3 getter, String messageType, String source)

NOTE: some AI-generated links and images were removed to ensure safety.

Bits AI Dev Agent Status: ✅ Done [Fix CI Errors]

Status History (1 entries)
2025-11-14 15:46:39 UTC ⚠️ Attempted to fix CI failures, no code changes

You can ask for changes by mentioning @datadog in a comment.

datadog-official[bot] avatar Nov 14 '25 14:11 datadog-official[bot]

Benchmarks

Benchmarks Report for benchmark platform :snail:

Benchmarks for #7820 compared to master:

  • All benchmarks have the same speed
  • 3 benchmarks have fewer allocations
  • 6 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 :heavy_check_mark: More allocations :warning:

More allocations :warning: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑netcoreapp3.1 5.64 KB 5.73 KB 91 B 1.61%

Fewer allocations :tada: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑net472 6.06 KB 6 KB -57 B -0.94%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 10.8μs 56.8ns 284ns 0 0 0 5.5 KB
master StartStopWithChild netcoreapp3.1 14.1μs 68.2ns 273ns 0 0 0 5.64 KB
master StartStopWithChild net472 22.8μs 124ns 688ns 1.03 0.31 0.103 6.06 KB
#7820 StartStopWithChild net6.0 10.7μs 59.3ns 365ns 0 0 0 5.48 KB
#7820 StartStopWithChild netcoreapp3.1 13.7μs 66.7ns 291ns 0 0 0 5.73 KB
#7820 StartStopWithChild net472 22.6μs 126ns 778ns 1.01 0.45 0.113 6 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 931μs 137ns 493ns 0 0 0 2.71 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 1.04ms 292ns 1.09μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 1.21ms 836ns 3.13μs 0 0 0 3.31 KB
#7820 WriteAndFlushEnrichedTraces net6.0 946μs 101ns 363ns 0 0 0 2.7 KB
#7820 WriteAndFlushEnrichedTraces netcoreapp3.1 1.05ms 2.88μs 10.4μs 0 0 0 2.7 KB
#7820 WriteAndFlushEnrichedTraces net472 1.2ms 762ns 2.95μs 0 0 0 3.31 KB
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 1.07μs 6ns 38.4ns 0 0 0 1.22 KB
master AllCycleSimpleBody netcoreapp3.1 1.4μs 7.78ns 44ns 0 0 0 1.2 KB
master AllCycleSimpleBody net472 1.04μs 0.458ns 1.71ns 0.191 0 0 1.23 KB
master AllCycleMoreComplexBody net6.0 7.24μs 35.2ns 149ns 0 0 0 4.72 KB
master AllCycleMoreComplexBody netcoreapp3.1 8.87μs 45.4ns 208ns 0 0 0 4.62 KB
master AllCycleMoreComplexBody net472 7.76μs 2.61ns 9.77ns 0.741 0 0 4.74 KB
master ObjectExtractorSimpleBody net6.0 319ns 1.58ns 7.26ns 0 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 400ns 2.08ns 10ns 0 0 0 272 B
master ObjectExtractorSimpleBody net472 297ns 0.0475ns 0.184ns 0.044 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 6.37μs 7.77ns 30.1ns 0 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 7.83μs 37.6ns 145ns 0 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 6.68μs 2.07ns 8ns 0.603 0 0 3.8 KB
#7820 AllCycleSimpleBody net6.0 1.07μs 0.76ns 2.84ns 0 0 0 1.22 KB
#7820 AllCycleSimpleBody netcoreapp3.1 1.4μs 7.44ns 38.7ns 0 0 0 1.2 KB
#7820 AllCycleSimpleBody net472 1.03μs 0.55ns 2.06ns 0.195 0 0 1.23 KB
#7820 AllCycleMoreComplexBody net6.0 7.05μs 33.9ns 148ns 0 0 0 4.72 KB
#7820 AllCycleMoreComplexBody netcoreapp3.1 9.03μs 5.13ns 19.9ns 0 0 0 4.62 KB
#7820 AllCycleMoreComplexBody net472 7.83μs 21.2ns 82.2ns 0.736 0 0 4.74 KB
#7820 ObjectExtractorSimpleBody net6.0 317ns 1.64ns 7.34ns 0 0 0 280 B
#7820 ObjectExtractorSimpleBody netcoreapp3.1 398ns 2.17ns 12.7ns 0 0 0 272 B
#7820 ObjectExtractorSimpleBody net472 296ns 0.0318ns 0.119ns 0.0432 0 0 281 B
#7820 ObjectExtractorMoreComplexBody net6.0 6.28μs 29.8ns 119ns 0 0 0 3.78 KB
#7820 ObjectExtractorMoreComplexBody netcoreapp3.1 7.81μs 34.7ns 139ns 0 0 0 3.69 KB
#7820 ObjectExtractorMoreComplexBody net472 6.67μs 0.501ns 1.74ns 0.601 0 0 3.8 KB
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EncodeArgs net6.0 76.6μs 162ns 628ns 0 0 0 32.4 KB
master EncodeArgs netcoreapp3.1 96.9μs 283ns 1.1μs 0 0 0 32.4 KB
master EncodeArgs net472 109μs 49.3ns 191ns 4.92 0 0 32.51 KB
master EncodeLegacyArgs net6.0 146μs 53.5ns 207ns 0 0 0 2.15 KB
master EncodeLegacyArgs netcoreapp3.1 197μs 208ns 806ns 0 0 0 2.14 KB
master EncodeLegacyArgs net472 262μs 119ns 460ns 0 0 0 2.16 KB
#7820 EncodeArgs net6.0 76.5μs 179ns 692ns 0 0 0 32.4 KB
#7820 EncodeArgs netcoreapp3.1 97.7μs 123ns 458ns 0 0 0 32.4 KB
#7820 EncodeArgs net472 109μs 72.2ns 280ns 4.92 0 0 32.5 KB
#7820 EncodeLegacyArgs net6.0 146μs 50.8ns 183ns 0 0 0 2.15 KB
#7820 EncodeLegacyArgs netcoreapp3.1 199μs 123ns 426ns 0 0 0 2.14 KB
#7820 EncodeLegacyArgs net472 264μs 90.3ns 350ns 0 0 0 2.16 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWafRealisticBenchmark net6.0 392μs 38.3ns 148ns 0 0 0 4.55 KB
master RunWafRealisticBenchmark netcoreapp3.1 850μs 3.84μs 14.9μs 0 0 0 4.48 KB
master RunWafRealisticBenchmark net472 433μs 64.1ns 240ns 0 0 0 4.66 KB
master RunWafRealisticBenchmarkWithAttack net6.0 283μs 11ns 41.3ns 0 0 0 2.24 KB
master RunWafRealisticBenchmarkWithAttack netcoreapp3.1 295μs 124ns 429ns 0 0 0 2.22 KB
master RunWafRealisticBenchmarkWithAttack net472 309μs 29.6ns 115ns 0 0 0 2.29 KB
#7820 RunWafRealisticBenchmark net6.0 403μs 87.4ns 339ns 0 0 0 4.55 KB
#7820 RunWafRealisticBenchmark netcoreapp3.1 832μs 12.2μs 119μs 0 0 0 4.48 KB
#7820 RunWafRealisticBenchmark net472 428μs 52ns 201ns 0 0 0 4.66 KB
#7820 RunWafRealisticBenchmarkWithAttack net6.0 283μs 26.6ns 103ns 0 0 0 2.24 KB
#7820 RunWafRealisticBenchmarkWithAttack netcoreapp3.1 302μs 141ns 546ns 0 0 0 2.22 KB
#7820 RunWafRealisticBenchmarkWithAttack net472 314μs 31.2ns 117ns 0 0 0 2.29 KB
Benchmarks.Trace.AspNetCoreBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net6.0 61.5μs 71.3ns 267ns 0 0 0 14.52 KB
master SendRequest netcoreapp3.1 72.3μs 67.8ns 254ns 0 0 0 17.42 KB
master SendRequest net472 0.00183ns 0.00127ns 0.00491ns 0 0 0 0 b
#7820 SendRequest net6.0 60.4μs 32.8ns 127ns 0 0 0 14.55 KB
#7820 SendRequest netcoreapp3.1 71μs 41.1ns 148ns 0 0 0 17.42 KB
#7820 SendRequest net472 0.00505ns 0.00195ns 0.00756ns 0 0 0 0 b
Benchmarks.Trace.CharSliceBenchmark - Same speed :heavy_check_mark: More allocations :warning:

More allocations :warning: in #7820

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

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master OriginalCharSlice net6.0 1.88ms 3.05μs 11.8μs 0 0 0 640.01 KB
master OriginalCharSlice netcoreapp3.1 2.11ms 4.21μs 16.3μs 0 0 0 640 KB
master OriginalCharSlice net472 2.68ms 272ns 1.05μs 100 0 0 641.95 KB
master OptimizedCharSlice net6.0 1.37ms 135ns 507ns 0 0 0 4 B
master OptimizedCharSlice netcoreapp3.1 1.69ms 399ns 1.54μs 0 0 0 1 B
master OptimizedCharSlice net472 1.95ms 233ns 903ns 0 0 0 0 b
master OptimizedCharSliceWithPool net6.0 874μs 69.5ns 260ns 0 0 0 1 B
master OptimizedCharSliceWithPool netcoreapp3.1 829μs 71.1ns 256ns 0 0 0 0 b
master OptimizedCharSliceWithPool net472 1.2ms 280ns 1.08μs 0 0 0 0 b
#7820 OriginalCharSlice net6.0 1.94ms 252ns 942ns 0 0 0 640.01 KB
#7820 OriginalCharSlice netcoreapp3.1 2.11ms 6μs 21.6μs 0 0 0 640 KB
#7820 OriginalCharSlice net472 2.66ms 1.3μs 4.85μs 100 0 0 641.95 KB
#7820 OptimizedCharSlice net6.0 1.4ms 125ns 449ns 0 0 0 4 B
#7820 OptimizedCharSlice netcoreapp3.1 1.7ms 754ns 2.82μs 0 0 0 1 B
#7820 OptimizedCharSlice net472 1.97ms 325ns 1.26μs 0 0 0 0 b
#7820 OptimizedCharSliceWithPool net6.0 866μs 40ns 155ns 0 0 0 3 B
#7820 OptimizedCharSliceWithPool netcoreapp3.1 858μs 48.1ns 186ns 0 0 0 0 b
#7820 OptimizedCharSliceWithPool net472 1.16ms 138ns 535ns 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed :heavy_check_mark: More allocations :warning:

More allocations :warning: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑netcoreapp3.1 41.88 KB 42.16 KB 278 B 0.66%

Fewer allocations :tada: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0 42.38 KB 41.69 KB -696 B -1.64%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 765μs 3.49μs 13μs 0 0 0 42.38 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 676μs 2.61μs 19.2μs 0 0 0 41.88 KB
master WriteAndFlushEnrichedTraces net472 957μs 4.68μs 20.9μs 4.81 0 0 56.3 KB
#7820 WriteAndFlushEnrichedTraces net6.0 680μs 3.65μs 18.9μs 0 0 0 41.69 KB
#7820 WriteAndFlushEnrichedTraces netcoreapp3.1 745μs 4.3μs 33.9μs 0 0 0 42.16 KB
#7820 WriteAndFlushEnrichedTraces net472 995μs 3.25μs 12.6μs 4.81 0 0 56.42 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net6.0 2μs 2.23ns 8.33ns 0 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 2.7μs 4.29ns 16.1ns 0 0 0 1.02 KB
master ExecuteNonQuery net472 2.81μs 3.78ns 14.6ns 0.155 0.0141 0 987 B
#7820 ExecuteNonQuery net6.0 2.01μs 0.863ns 3.34ns 0 0 0 1.02 KB
#7820 ExecuteNonQuery netcoreapp3.1 2.66μs 7.86ns 30.4ns 0 0 0 1.02 KB
#7820 ExecuteNonQuery net472 2.8μs 2.92ns 11.3ns 0.155 0.0141 0 987 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net6.0 1.67μs 9.01ns 49.3ns 0 0 0 1.03 KB
master CallElasticsearch netcoreapp3.1 2.27μs 1.34ns 5ns 0 0 0 1.03 KB
master CallElasticsearch net472 3.47μs 3.16ns 12.3ns 0.156 0 0 1.04 KB
master CallElasticsearchAsync net6.0 1.88μs 6.98ns 27ns 0 0 0 1.01 KB
master CallElasticsearchAsync netcoreapp3.1 2.45μs 11ns 42.6ns 0 0 0 1.08 KB
master CallElasticsearchAsync net472 3.69μs 1.72ns 6.44ns 0.166 0 0 1.1 KB
#7820 CallElasticsearch net6.0 1.8μs 1.49ns 5.57ns 0 0 0 1.03 KB
#7820 CallElasticsearch netcoreapp3.1 2.32μs 10.8ns 41.8ns 0 0 0 1.03 KB
#7820 CallElasticsearch net472 3.41μs 5.64ns 21.8ns 0.154 0 0 1.04 KB
#7820 CallElasticsearchAsync net6.0 1.81μs 7.14ns 25.8ns 0 0 0 1.01 KB
#7820 CallElasticsearchAsync netcoreapp3.1 2.52μs 7.23ns 28ns 0 0 0 1.08 KB
#7820 CallElasticsearchAsync net472 3.64μs 1.94ns 7.26ns 0.166 0 0 1.1 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net6.0 1.85μs 9.2ns 41.2ns 0 0 0 952 B
master ExecuteAsync netcoreapp3.1 2.5μs 9.47ns 36.7ns 0 0 0 952 B
master ExecuteAsync net472 2.7μs 4.34ns 16.8ns 0.135 0 0 915 B
#7820 ExecuteAsync net6.0 1.89μs 0.971ns 3.5ns 0 0 0 952 B
#7820 ExecuteAsync netcoreapp3.1 2.57μs 10.3ns 40ns 0 0 0 952 B
#7820 ExecuteAsync net472 2.67μs 2.05ns 7.94ns 0.133 0 0 915 B
Benchmarks.Trace.HttpClientBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net6.0 6.69μs 14.9ns 57.8ns 0 0 0 2.36 KB
master SendAsync netcoreapp3.1 8.71μs 23.7ns 82.2ns 0 0 0 2.9 KB
master SendAsync net472 12.5μs 12.9ns 49.9ns 0.498 0 0 3.18 KB
#7820 SendAsync net6.0 6.83μs 7.53ns 29.2ns 0 0 0 2.36 KB
#7820 SendAsync netcoreapp3.1 8.74μs 23.8ns 89.2ns 0 0 0 2.9 KB
#7820 SendAsync net472 12.4μs 8.85ns 34.3ns 0.492 0 0 3.18 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed :heavy_check_mark: More allocations :warning:

More allocations :warning: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net472 278.53 KB 286.72 KB 8.19 KB 2.94%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net6.0 43.14 KB 43.76 KB 616 B 1.43%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 254.57 KB 256.21 KB 1.64 KB 0.64%

Fewer allocations :tada: in #7820

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 276.5 KB 255.7 KB -20.81 KB -7.53%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark net6.0 42.1μs 210ns 864ns 0 0 0 43.14 KB
master StringConcatBenchmark netcoreapp3.1 50.3μs 287ns 2.58μs 0 0 0 42.64 KB
master StringConcatBenchmark net472 56.5μs 270ns 1.04μs 0 0 0 57.34 KB
master StringConcatAspectBenchmark net6.0 477μs 1.51μs 5.46μs 0 0 0 276.5 KB
master StringConcatAspectBenchmark netcoreapp3.1 494μs 1.68μs 6.04μs 0 0 0 254.57 KB
master StringConcatAspectBenchmark net472 407μs 2.13μs 10.8μs 0 0 0 278.53 KB
#7820 StringConcatBenchmark net6.0 44μs 245ns 1.51μs 0 0 0 43.76 KB
#7820 StringConcatBenchmark netcoreapp3.1 48.6μs 278ns 1.92μs 0 0 0 42.64 KB
#7820 StringConcatBenchmark net472 56.7μs 226ns 814ns 0 0 0 57.34 KB
#7820 StringConcatAspectBenchmark net6.0 438μs 1.56μs 5.84μs 0 0 0 255.7 KB
#7820 StringConcatAspectBenchmark netcoreapp3.1 505μs 2.17μs 8.67μs 0 0 0 256.21 KB
#7820 StringConcatAspectBenchmark net472 400μs 1.94μs 8.47μs 0 0 0 286.72 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.64μs 10.9ns 42ns 0 0 0 1.7 KB
master EnrichedLog netcoreapp3.1 3.64μs 16ns 62.1ns 0 0 0 1.7 KB
master EnrichedLog net472 3.87μs 4.3ns 16.6ns 0.252 0 0 1.64 KB
#7820 EnrichedLog net6.0 2.64μs 12ns 48.2ns 0 0 0 1.7 KB
#7820 EnrichedLog netcoreapp3.1 3.63μs 17.6ns 76.6ns 0 0 0 1.7 KB
#7820 EnrichedLog net472 3.85μs 2.92ns 10.9ns 0.25 0 0 1.64 KB
Benchmarks.Trace.Log4netBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 124μs 70ns 262ns 0 0 0 4.31 KB
master EnrichedLog netcoreapp3.1 127μs 213ns 738ns 0 0 0 4.31 KB
master EnrichedLog net472 169μs 55.1ns 206ns 0 0 0 4.52 KB
#7820 EnrichedLog net6.0 127μs 316ns 1.22μs 0 0 0 4.31 KB
#7820 EnrichedLog netcoreapp3.1 133μs 447ns 1.73μs 0 0 0 4.31 KB
#7820 EnrichedLog net472 166μs 26.8ns 104ns 0 0 0 4.52 KB
Benchmarks.Trace.NLogBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 5.09μs 20ns 77.3ns 0 0 0 2.26 KB
master EnrichedLog netcoreapp3.1 6.88μs 18.3ns 71ns 0 0 0 2.26 KB
master EnrichedLog net472 7.52μs 7.8ns 30.2ns 0.3 0 0 2.08 KB
#7820 EnrichedLog net6.0 5.04μs 4.19ns 15.7ns 0 0 0 2.26 KB
#7820 EnrichedLog netcoreapp3.1 7μs 31.1ns 121ns 0 0 0 2.26 KB
#7820 EnrichedLog net472 7.54μs 6.68ns 25.9ns 0.3 0 0 2.08 KB
Benchmarks.Trace.RedisBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 2.08μs 8.84ns 34.2ns 0 0 0 1.2 KB
master SendReceive netcoreapp3.1 2.62μs 12.2ns 47.2ns 0 0 0 1.2 KB
master SendReceive net472 3.01μs 4.12ns 16ns 0.181 0 0 1.2 KB
#7820 SendReceive net6.0 2.05μs 6.31ns 22.7ns 0 0 0 1.2 KB
#7820 SendReceive netcoreapp3.1 2.61μs 11.4ns 44.3ns 0 0 0 1.2 KB
#7820 SendReceive net472 3.13μs 3.58ns 13.9ns 0.187 0 0 1.2 KB
Benchmarks.Trace.SerilogBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 4.35μs 11.9ns 46ns 0 0 0 1.58 KB
master EnrichedLog netcoreapp3.1 5.76μs 3.84ns 14.4ns 0 0 0 1.63 KB
master EnrichedLog net472 6.66μs 11.9ns 46ns 0.301 0 0 2.03 KB
#7820 EnrichedLog net6.0 4.14μs 8.65ns 33.5ns 0 0 0 1.58 KB
#7820 EnrichedLog netcoreapp3.1 5.77μs 10.7ns 40.2ns 0 0 0 1.63 KB
#7820 EnrichedLog net472 6.75μs 6.8ns 24.5ns 0.305 0 0 2.03 KB
Benchmarks.Trace.SpanBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 777ns 0.35ns 1.31ns 0 0 0 576 B
master StartFinishSpan netcoreapp3.1 1.01μs 0.635ns 2.46ns 0 0 0 576 B
master StartFinishSpan net472 964ns 0.266ns 1.03ns 0.0917 0 0 578 B
master StartFinishScope net6.0 967ns 0.271ns 1.05ns 0 0 0 696 B
master StartFinishScope netcoreapp3.1 1.21μs 1.71ns 6.64ns 0 0 0 696 B
master StartFinishScope net472 1.14μs 0.618ns 2.39ns 0.103 0 0 658 B
#7820 StartFinishSpan net6.0 778ns 3.99ns 18.7ns 0 0 0 576 B
#7820 StartFinishSpan netcoreapp3.1 992ns 5.14ns 24.6ns 0 0 0 576 B
#7820 StartFinishSpan net472 947ns 0.115ns 0.431ns 0.0904 0 0 578 B
#7820 StartFinishScope net6.0 917ns 0.248ns 0.895ns 0 0 0 696 B
#7820 StartFinishScope netcoreapp3.1 1.22μs 5.86ns 24.2ns 0 0 0 696 B
#7820 StartFinishScope net472 1.12μs 0.276ns 1.03ns 0.102 0 0 658 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed :heavy_check_mark: Same allocations :heavy_check_mark:

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 1.06μs 4.72ns 18.3ns 0 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 1.4μs 7.28ns 35.6ns 0 0 0 696 B
master RunOnMethodBegin net472 1.49μs 1.05ns 4.07ns 0.104 0 0 658 B
#7820 RunOnMethodBegin net6.0 1.07μs 1.44ns 5.2ns 0 0 0 696 B
#7820 RunOnMethodBegin netcoreapp3.1 1.46μs 6.92ns 27.7ns 0 0 0 696 B
#7820 RunOnMethodBegin net472 1.43μs 0.662ns 2.56ns 0.101 0 0 658 B

pr-commenter[bot] avatar Nov 14 '25 15:11 pr-commenter[bot]

Execution-Time Benchmarks Report :stopwatch:

Execution-time results for samples comparing This PR (7820) and master.

✅ No regressions detected - check the details below

Full Metrics Comparison

FakeDbCommand

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration75.22 ± (75.15 - 75.86) ms74.90 ± (75.00 - 75.72) ms-0.4%
.NET Framework 4.8 - Bailout
duration80.06 ± (79.58 - 80.22) ms80.24 ± (80.10 - 80.72) ms+0.2%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1118.43 ± (1129.24 - 1142.19) ms1127.59 ± (1131.02 - 1142.81) ms+0.8%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms22.96 ± (22.88 - 23.03) ms23.30 ± (23.22 - 23.37) ms+1.5%✅⬆️
process.time_to_main_ms87.75 ± (87.42 - 88.08) ms89.84 ± (89.40 - 90.28) ms+2.4%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.92 ± (10.91 - 10.92) MB10.93 ± (10.92 - 10.93) MB+0.1%✅⬆️
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms22.70 ± (22.63 - 22.76) ms23.05 ± (22.97 - 23.13) ms+1.5%✅⬆️
process.time_to_main_ms87.84 ± (87.47 - 88.21) ms89.80 ± (89.40 - 90.20) ms+2.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.95 ± (10.95 - 10.95) MB10.96 ± (10.96 - 10.97) MB+0.1%✅⬆️
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms221.55 ± (220.20 - 222.90) ms222.03 ± (220.62 - 223.44) ms+0.2%✅⬆️
process.time_to_main_ms547.70 ± (546.57 - 548.84) ms556.24 ± (555.03 - 557.46) ms+1.6%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed52.43 ± (52.41 - 52.45) MB52.64 ± (52.62 - 52.66) MB+0.4%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.2%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms21.78 ± (21.70 - 21.86) ms22.13 ± (22.05 - 22.20) ms+1.6%✅⬆️
process.time_to_main_ms75.98 ± (75.61 - 76.35) ms77.44 ± (77.12 - 77.77) ms+1.9%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.61 ± (10.61 - 10.62) MB10.65 ± (10.65 - 10.65) MB+0.4%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms21.72 ± (21.66 - 21.79) ms22.11 ± (22.04 - 22.17) ms+1.8%✅⬆️
process.time_to_main_ms76.85 ± (76.54 - 77.16) ms78.28 ± (77.95 - 78.61) ms+1.9%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.70 ± (10.69 - 10.70) MB10.69 ± (10.68 - 10.69) MB-0.1%
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms207.66 ± (206.41 - 208.92) ms208.69 ± (207.22 - 210.16) ms+0.5%✅⬆️
process.time_to_main_ms515.64 ± (514.46 - 516.83) ms521.37 ± (520.38 - 522.37) ms+1.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed51.66 ± (51.63 - 51.68) MB51.73 ± (51.70 - 51.75) MB+0.1%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)-0.0%
.NET 8 - Baseline
process.internal_duration_ms19.94 ± (19.86 - 20.01) ms20.08 ± (20.00 - 20.16) ms+0.7%✅⬆️
process.time_to_main_ms75.03 ± (74.71 - 75.35) ms75.53 ± (75.19 - 75.88) ms+0.7%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.68 ± (7.68 - 7.69) MB7.67 ± (7.66 - 7.68) MB-0.2%
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms20.16 ± (20.09 - 20.23) ms20.10 ± (20.04 - 20.16) ms-0.3%
process.time_to_main_ms77.82 ± (77.44 - 78.20) ms77.28 ± (76.93 - 77.64) ms-0.7%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.72 ± (7.71 - 7.72) MB7.73 ± (7.72 - 7.74) MB+0.2%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms191.08 ± (190.09 - 192.07) ms192.07 ± (191.23 - 192.92) ms+0.5%✅⬆️
process.time_to_main_ms492.25 ± (491.28 - 493.22) ms492.87 ± (491.68 - 494.06) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed38.90 ± (38.86 - 38.94) MB39.00 ± (38.95 - 39.04) MB+0.3%✅⬆️
runtime.dotnet.threads.count27 ± (27 - 27)27 ± (27 - 27)+0.2%✅⬆️

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration192.93 ± (193.01 - 194.10) ms192.96 ± (192.91 - 193.92) ms+0.0%✅⬆️
.NET Framework 4.8 - Bailout
duration196.04 ± (195.90 - 196.63) ms197.15 ± (196.86 - 197.75) ms+0.6%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1170.86 ± (1172.20 - 1181.14) ms1165.97 ± (1168.60 - 1176.77) ms-0.4%
.NET Core 3.1 - Baseline
process.internal_duration_ms187.48 ± (187.12 - 187.85) ms187.70 ± (187.36 - 188.04) ms+0.1%✅⬆️
process.time_to_main_ms80.37 ± (80.13 - 80.61) ms80.79 ± (80.57 - 81.02) ms+0.5%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.05 ± (16.02 - 16.08) MB16.04 ± (16.02 - 16.07) MB-0.0%
runtime.dotnet.threads.count20 ± (19 - 20)20 ± (19 - 20)+0.2%✅⬆️
.NET Core 3.1 - Bailout
process.internal_duration_ms187.18 ± (186.82 - 187.53) ms187.64 ± (187.33 - 187.95) ms+0.2%✅⬆️
process.time_to_main_ms81.78 ± (81.64 - 81.93) ms81.82 ± (81.68 - 81.95) ms+0.0%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.15 ± (16.12 - 16.18) MB16.16 ± (16.13 - 16.19) MB+0.0%✅⬆️
runtime.dotnet.threads.count21 ± (20 - 21)21 ± (21 - 21)+0.7%✅⬆️
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms396.14 ± (393.55 - 398.72) ms389.93 ± (387.54 - 392.32) ms-1.6%
process.time_to_main_ms517.42 ± (516.75 - 518.10) ms517.45 ± (516.81 - 518.09) ms+0.0%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed62.90 ± (62.74 - 63.05) MB62.42 ± (62.26 - 62.58) MB-0.8%
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)-0.1%
.NET 6 - Baseline
process.internal_duration_ms192.11 ± (191.66 - 192.55) ms191.86 ± (191.53 - 192.19) ms-0.1%
process.time_to_main_ms69.98 ± (69.81 - 70.16) ms69.68 ± (69.55 - 69.82) ms-0.4%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.05 ± (15.90 - 16.20) MB16.00 ± (15.84 - 16.15) MB-0.3%
runtime.dotnet.threads.count18 ± (18 - 19)18 ± (18 - 18)-0.8%
.NET 6 - Bailout
process.internal_duration_ms191.29 ± (190.95 - 191.63) ms191.65 ± (191.26 - 192.03) ms+0.2%✅⬆️
process.time_to_main_ms70.72 ± (70.62 - 70.82) ms70.69 ± (70.56 - 70.81) ms-0.0%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.25 ± (16.13 - 16.37) MB16.20 ± (16.06 - 16.33) MB-0.3%
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)+0.1%✅⬆️
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms408.11 ± (405.28 - 410.93) ms408.94 ± (405.99 - 411.88) ms+0.2%✅⬆️
process.time_to_main_ms487.36 ± (486.69 - 488.02) ms487.63 ± (487.05 - 488.20) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed62.02 ± (61.87 - 62.17) MB62.08 ± (61.94 - 62.22) MB+0.1%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 30)29 ± (29 - 29)-0.2%
.NET 8 - Baseline
process.internal_duration_ms189.62 ± (189.27 - 189.97) ms190.83 ± (190.41 - 191.25) ms+0.6%✅⬆️
process.time_to_main_ms69.06 ± (68.87 - 69.25) ms69.30 ± (69.12 - 69.49) ms+0.4%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.77 ± (11.75 - 11.80) MB11.77 ± (11.74 - 11.80) MB-0.0%
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)+0.8%✅⬆️
.NET 8 - Bailout
process.internal_duration_ms188.77 ± (188.56 - 188.98) ms189.87 ± (189.58 - 190.16) ms+0.6%✅⬆️
process.time_to_main_ms70.00 ± (69.90 - 70.09) ms70.27 ± (70.15 - 70.39) ms+0.4%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.83 ± (11.78 - 11.88) MB11.81 ± (11.78 - 11.84) MB-0.1%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)+0.5%✅⬆️
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms361.65 ± (360.22 - 363.07) ms359.97 ± (358.42 - 361.51) ms-0.5%
process.time_to_main_ms466.05 ± (465.35 - 466.75) ms461.30 ± (460.72 - 461.88) ms-1.0%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed50.26 ± (50.21 - 50.30) MB50.35 ± (50.31 - 50.39) MB+0.2%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)+0.1%✅⬆️
Comparison explanation

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 highlighted 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).

Duration charts
FakeDbCommand (.NET Framework 4.8)
gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (75ms)  : 70, 81
    master - mean (76ms)  : 70, 81

    section Bailout
    This PR (7820) - mean (80ms)  : 76, 85
    master - mean (80ms)  : 75, 85

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (1,137ms)  : 1049, 1225
    master - mean (1,136ms)  : 1035, 1237

FakeDbCommand (.NET Core 3.1)
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (121ms)  : 113, 129
    master - mean (118ms)  : 112, 125

    section Bailout
    This PR (7820) - mean (121ms)  : 113, 128
    master - mean (118ms)  : 111, 124

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (821ms)  : 780, 863
    master - mean (806ms)  : 769, 842

FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (107ms)  : 101, 113
    master - mean (105ms)  : 96, 113

    section Bailout
    This PR (7820) - mean (108ms)  : 102, 113
    master - mean (105ms)  : 100, 111

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (770ms)  : 720, 821
    master - mean (755ms)  : 715, 795

FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (104ms)  : 97, 111
    master - mean (103ms)  : 98, 109

    section Bailout
    This PR (7820) - mean (106ms)  : 100, 112
    master - mean (107ms)  : 99, 114

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (724ms)  : 687, 762
    master - mean (717ms)  : 690, 743

HttpMessageHandler (.NET Framework 4.8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (193ms)  : 188, 198
    master - mean (194ms)  : 187, 200

    section Bailout
    This PR (7820) - mean (197ms)  : 193, 202
    master - mean (196ms)  : 193, 200

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (1,173ms)  : 1114, 1232
    master - mean (1,177ms)  : 1113, 1240

HttpMessageHandler (.NET Core 3.1)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (277ms)  : 272, 282
    master - mean (276ms)  : 271, 281

    section Bailout
    This PR (7820) - mean (277ms)  : 274, 281
    master - mean (277ms)  : 273, 281

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (939ms)  : 892, 985
    master - mean (943ms)  : 895, 992

HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (270ms)  : 266, 273
    master - mean (270ms)  : 264, 276

    section Bailout
    This PR (7820) - mean (270ms)  : 266, 274
    master - mean (270ms)  : 266, 274

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (931ms)  : 874, 988
    master - mean (926ms)  : 872, 981

HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7820) - mean (270ms)  : 262, 277
    master - mean (268ms)  : 264, 273

    section Bailout
    This PR (7820) - mean (269ms)  : 265, 273
    master - mean (268ms)  : 265, 271

    section CallTarget+Inlining+NGEN
    This PR (7820) - mean (852ms)  : 834, 870
    master - mean (860ms)  : 838, 882

We have guards for this elsewhere, pretty sure this doesn't make sense

andrewlock avatar Dec 24 '25 14:12 andrewlock