[tracing] add support for DiagnosticSource (and Quartz) in .NET Framework#7687
Conversation
This comment has been minimized.
This comment has been minimized.
Execution-Time Benchmarks Report ⏱️Execution-time results for samples comparing This PR (7687) and master.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Metric | Master (Mean ± 95% CI) | Current (Mean ± 95% CI) | Change | Status |
|---|---|---|---|---|
| .NET Framework 4.8 - Baseline | ||||
| duration | 192.99 ± (193.05 - 193.92) ms | 220.29 ± (219.95 - 222.25) ms | +14.1% | ❌⬆️ |
| .NET Framework 4.8 - Bailout | ||||
| duration | 198.21 ± (198.20 - 199.08) ms | 217.58 ± (217.59 - 218.71) ms | +9.8% | ❌⬆️ |
| .NET Framework 4.8 - CallTarget+Inlining+NGEN | ||||
| duration | 1143.86 ± (1146.37 - 1153.34) ms | 1225.11 ± (1225.46 - 1233.47) ms | +7.1% | ❌⬆️ |
Full Metrics Comparison
FakeDbCommand
| Metric | Master (Mean ± 95% CI) | Current (Mean ± 95% CI) | Change | Status |
|---|---|---|---|---|
| .NET Framework 4.8 - Baseline | ||||
| duration | 69.17 ± (69.07 - 69.36) ms | 68.70 ± (68.76 - 69.03) ms | -0.7% | ✅ |
| .NET Framework 4.8 - Bailout | ||||
| duration | 73.41 ± (73.29 - 73.59) ms | 72.28 ± (72.21 - 72.43) ms | -1.5% | ✅ |
| .NET Framework 4.8 - CallTarget+Inlining+NGEN | ||||
| duration | 1038.40 ± (1048.38 - 1059.66) ms | 1038.60 ± (1048.32 - 1058.96) ms | +0.0% | ✅⬆️ |
| .NET Core 3.1 - Baseline | ||||
| process.internal_duration_ms | 21.77 ± (21.74 - 21.80) ms | 21.78 ± (21.75 - 21.81) ms | +0.0% | ✅⬆️ |
| process.time_to_main_ms | 79.33 ± (79.17 - 79.49) ms | 79.54 ± (79.37 - 79.71) ms | +0.3% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 10.90 ± (10.90 - 10.91) MB | 10.92 ± (10.91 - 10.92) MB | +0.1% | ✅⬆️ |
| runtime.dotnet.threads.count | 12 ± (12 - 12) | 12 ± (12 - 12) | +0.0% | ✅ |
| .NET Core 3.1 - Bailout | ||||
| process.internal_duration_ms | 21.72 ± (21.70 - 21.75) ms | 21.74 ± (21.71 - 21.76) ms | +0.1% | ✅⬆️ |
| process.time_to_main_ms | 80.56 ± (80.42 - 80.70) ms | 80.58 ± (80.45 - 80.71) ms | +0.0% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 10.95 ± (10.94 - 10.95) MB | 10.95 ± (10.94 - 10.95) MB | +0.0% | ✅⬆️ |
| runtime.dotnet.threads.count | 13 ± (13 - 13) | 13 ± (13 - 13) | +0.0% | ✅ |
| .NET Core 3.1 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 216.36 ± (215.37 - 217.35) ms | 218.06 ± (216.76 - 219.36) ms | +0.8% | ✅⬆️ |
| process.time_to_main_ms | 467.77 ± (467.30 - 468.24) ms | 516.35 ± (515.29 - 517.42) ms | +10.4% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 47.31 ± (47.29 - 47.34) MB | 48.19 ± (48.15 - 48.22) MB | +1.8% | ✅⬆️ |
| runtime.dotnet.threads.count | 28 ± (28 - 28) | 28 ± (28 - 28) | -0.3% | ✅ |
| .NET 6 - Baseline | ||||
| process.internal_duration_ms | 20.51 ± (20.49 - 20.54) ms | 20.61 ± (20.58 - 20.64) ms | +0.5% | ✅⬆️ |
| process.time_to_main_ms | 68.70 ± (68.57 - 68.84) ms | 69.33 ± (69.16 - 69.50) ms | +0.9% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 10.61 ± (10.61 - 10.61) MB | 10.62 ± (10.62 - 10.63) MB | +0.1% | ✅⬆️ |
| runtime.dotnet.threads.count | 10 ± (10 - 10) | 10 ± (10 - 10) | +0.0% | ✅ |
| .NET 6 - Bailout | ||||
| process.internal_duration_ms | 20.49 ± (20.47 - 20.51) ms | 20.56 ± (20.53 - 20.59) ms | +0.3% | ✅⬆️ |
| process.time_to_main_ms | 69.55 ± (69.44 - 69.66) ms | 70.37 ± (70.24 - 70.51) ms | +1.2% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 10.67 ± (10.66 - 10.67) MB | 10.73 ± (10.73 - 10.74) MB | +0.6% | ✅⬆️ |
| runtime.dotnet.threads.count | 11 ± (11 - 11) | 11 ± (11 - 11) | +0.0% | ✅ |
| .NET 6 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 200.96 ± (198.99 - 202.93) ms | 206.90 ± (205.54 - 208.27) ms | +3.0% | ✅⬆️ |
| process.time_to_main_ms | 468.99 ± (468.33 - 469.65) ms | 516.67 ± (515.42 - 517.92) ms | +10.2% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 48.96 ± (48.89 - 49.02) MB | 50.10 ± (50.07 - 50.14) MB | +2.3% | ✅⬆️ |
| runtime.dotnet.threads.count | 29 ± (29 - 29) | 29 ± (29 - 29) | +0.1% | ✅⬆️ |
| .NET 8 - Baseline | ||||
| process.internal_duration_ms | 18.84 ± (18.81 - 18.88) ms | 18.80 ± (18.78 - 18.83) ms | -0.2% | ✅ |
| process.time_to_main_ms | 68.13 ± (67.99 - 68.27) ms | 68.21 ± (68.09 - 68.33) ms | +0.1% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 7.67 ± (7.66 - 7.67) MB | 7.66 ± (7.66 - 7.66) MB | -0.1% | ✅ |
| runtime.dotnet.threads.count | 10 ± (10 - 10) | 10 ± (10 - 10) | +0.0% | ✅ |
| .NET 8 - Bailout | ||||
| process.internal_duration_ms | 18.79 ± (18.76 - 18.82) ms | 18.80 ± (18.77 - 18.82) ms | +0.0% | ✅⬆️ |
| process.time_to_main_ms | 69.30 ± (69.18 - 69.43) ms | 69.50 ± (69.36 - 69.64) ms | +0.3% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 7.73 ± (7.73 - 7.74) MB | 7.75 ± (7.74 - 7.76) MB | +0.2% | ✅⬆️ |
| runtime.dotnet.threads.count | 11 ± (11 - 11) | 11 ± (11 - 11) | +0.0% | ✅ |
| .NET 8 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 157.58 ± (156.62 - 158.53) ms | 153.57 ± (152.81 - 154.33) ms | -2.5% | ✅ |
| process.time_to_main_ms | 448.33 ± (447.81 - 448.84) ms | 475.71 ± (474.83 - 476.60) ms | +6.1% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 0 ± (0 - 0) | 0 ± (0 - 0) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 36.54 ± (36.52 - 36.56) MB | 36.93 ± (36.90 - 36.95) MB | +1.1% | ✅⬆️ |
| runtime.dotnet.threads.count | 28 ± (28 - 28) | 28 ± (28 - 28) | +0.1% | ✅⬆️ |
HttpMessageHandler
| Metric | Master (Mean ± 95% CI) | Current (Mean ± 95% CI) | Change | Status |
|---|---|---|---|---|
| .NET Framework 4.8 - Baseline | ||||
| duration | 192.99 ± (193.05 - 193.92) ms | 220.29 ± (219.95 - 222.25) ms | +14.1% | ❌⬆️ |
| .NET Framework 4.8 - Bailout | ||||
| duration | 198.21 ± (198.20 - 199.08) ms | 217.58 ± (217.59 - 218.71) ms | +9.8% | ❌⬆️ |
| .NET Framework 4.8 - CallTarget+Inlining+NGEN | ||||
| duration | 1143.86 ± (1146.37 - 1153.34) ms | 1225.11 ± (1225.46 - 1233.47) ms | +7.1% | ❌⬆️ |
| .NET Core 3.1 - Baseline | ||||
| process.internal_duration_ms | 187.52 ± (187.18 - 187.86) ms | 208.06 ± (207.46 - 208.65) ms | +11.0% | ✅⬆️ |
| process.time_to_main_ms | 80.41 ± (80.21 - 80.61) ms | 89.49 ± (89.25 - 89.73) ms | +11.3% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 3 ± (3 - 3) | 3 ± (3 - 3) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 16.15 ± (16.12 - 16.17) MB | 15.92 ± (15.90 - 15.93) MB | -1.4% | ✅ |
| runtime.dotnet.threads.count | 20 ± (20 - 20) | 20 ± (20 - 20) | +1.0% | ✅⬆️ |
| .NET Core 3.1 - Bailout | ||||
| process.internal_duration_ms | 186.79 ± (186.49 - 187.08) ms | 207.82 ± (207.22 - 208.42) ms | +11.3% | ✅⬆️ |
| process.time_to_main_ms | 81.74 ± (81.61 - 81.87) ms | 91.11 ± (90.87 - 91.35) ms | +11.5% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 3 ± (3 - 3) | 3 ± (3 - 3) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 16.21 ± (16.18 - 16.25) MB | 16.01 ± (15.99 - 16.03) MB | -1.3% | ✅ |
| runtime.dotnet.threads.count | 21 ± (20 - 21) | 21 ± (21 - 21) | +1.5% | ✅⬆️ |
| .NET Core 3.1 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 396.34 ± (394.50 - 398.18) ms | 412.55 ± (411.41 - 413.70) ms | +4.1% | ✅⬆️ |
| process.time_to_main_ms | 472.64 ± (472.13 - 473.15) ms | 554.40 ± (553.11 - 555.69) ms | +17.3% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 3 ± (3 - 3) | 3 ± (3 - 3) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 57.66 ± (57.50 - 57.82) MB | 59.07 ± (59.03 - 59.11) MB | +2.4% | ✅⬆️ |
| runtime.dotnet.threads.count | 30 ± (30 - 30) | 30 ± (30 - 30) | +0.2% | ✅⬆️ |
| .NET 6 - Baseline | ||||
| process.internal_duration_ms | 192.44 ± (192.01 - 192.87) ms | 214.08 ± (213.46 - 214.69) ms | +11.2% | ✅⬆️ |
| process.time_to_main_ms | 69.96 ± (69.78 - 70.14) ms | 78.06 ± (77.85 - 78.28) ms | +11.6% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 16.05 ± (15.92 - 16.19) MB | 16.21 ± (16.19 - 16.22) MB | +0.9% | ✅⬆️ |
| runtime.dotnet.threads.count | 19 ± (19 - 19) | 19 ± (19 - 20) | +3.7% | ✅⬆️ |
| .NET 6 - Bailout | ||||
| process.internal_duration_ms | 192.22 ± (191.76 - 192.68) ms | 212.42 ± (211.88 - 212.96) ms | +10.5% | ✅⬆️ |
| process.time_to_main_ms | 71.09 ± (70.93 - 71.25) ms | 79.01 ± (78.82 - 79.21) ms | +11.1% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 16.05 ± (15.90 - 16.21) MB | 16.25 ± (16.23 - 16.27) MB | +1.2% | ✅⬆️ |
| runtime.dotnet.threads.count | 19 ± (19 - 19) | 20 ± (20 - 21) | +6.4% | ✅⬆️ |
| .NET 6 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 428.77 ± (427.15 - 430.40) ms | 442.61 ± (441.01 - 444.20) ms | +3.2% | ✅⬆️ |
| process.time_to_main_ms | 473.98 ± (473.15 - 474.81) ms | 563.71 ± (562.52 - 564.90) ms | +18.9% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 60.25 ± (60.16 - 60.35) MB | 60.85 ± (60.81 - 60.89) MB | +1.0% | ✅⬆️ |
| runtime.dotnet.threads.count | 30 ± (30 - 30) | 31 ± (31 - 31) | +1.8% | ✅⬆️ |
| .NET 8 - Baseline | ||||
| process.internal_duration_ms | 190.28 ± (189.90 - 190.67) ms | 227.38 ± (226.23 - 228.52) ms | +19.5% | ✅⬆️ |
| process.time_to_main_ms | 69.48 ± (69.29 - 69.66) ms | 80.14 ± (79.85 - 80.43) ms | +15.3% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 11.77 ± (11.74 - 11.80) MB | 11.46 ± (11.45 - 11.48) MB | -2.6% | ✅ |
| runtime.dotnet.threads.count | 18 ± (18 - 18) | 19 ± (19 - 19) | +4.5% | ✅⬆️ |
| .NET 8 - Bailout | ||||
| process.internal_duration_ms | 189.20 ± (188.89 - 189.50) ms | 223.21 ± (222.10 - 224.31) ms | +18.0% | ✅⬆️ |
| process.time_to_main_ms | 70.42 ± (70.30 - 70.54) ms | 80.25 ± (79.97 - 80.53) ms | +14.0% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 11.76 ± (11.69 - 11.83) MB | 11.51 ± (11.50 - 11.53) MB | -2.1% | ✅ |
| runtime.dotnet.threads.count | 19 ± (18 - 19) | 20 ± (20 - 20) | +7.2% | ✅⬆️ |
| .NET 8 - CallTarget+Inlining+NGEN | ||||
| process.internal_duration_ms | 352.63 ± (351.38 - 353.88) ms | 465.72 ± (461.51 - 469.94) ms | +32.1% | ✅⬆️ |
| process.time_to_main_ms | 451.07 ± (450.50 - 451.63) ms | 525.11 ± (523.86 - 526.37) ms | +16.4% | ✅⬆️ |
| runtime.dotnet.exceptions.count | 4 ± (4 - 4) | 4 ± (4 - 4) | +0.0% | ✅ |
| runtime.dotnet.mem.committed | 48.54 ± (48.51 - 48.57) MB | 50.74 ± (50.67 - 50.81) MB | +4.5% | ✅⬆️ |
| runtime.dotnet.threads.count | 30 ± (30 - 30) | 30 ± (30 - 30) | +0.7% | ✅⬆️ |
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 (7687) - mean (69ms) : 67, 71
master - mean (69ms) : 67, 71
section Bailout
This PR (7687) - mean (72ms) : 71, 73
master - mean (73ms) : 72, 75
section CallTarget+Inlining+NGEN
This PR (7687) - mean (1,054ms) : 974, 1133
master - mean (1,054ms) : 968, 1140
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 (7687) - mean (107ms) : 104, 110
master - mean (107ms) : 103, 110
section Bailout
This PR (7687) - mean (108ms) : 106, 110
master - mean (108ms) : 106, 110
section CallTarget+Inlining+NGEN
This PR (7687) - mean (773ms) : crit, 752, 793
master - mean (722ms) : 699, 744
FakeDbCommand (.NET 6)
gantt
title Execution time (ms) FakeDbCommand (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (7687) - mean (95ms) : 93, 97
master - mean (94ms) : 91, 98
section Bailout
This PR (7687) - mean (96ms) : 95, 98
master - mean (95ms) : 93, 97
section CallTarget+Inlining+NGEN
This PR (7687) - mean (757ms) : crit, 740, 774
master - mean (699ms) : 648, 749
FakeDbCommand (.NET 8)
gantt
title Execution time (ms) FakeDbCommand (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (7687) - mean (94ms) : 91, 96
master - mean (94ms) : 91, 96
section Bailout
This PR (7687) - mean (95ms) : 93, 97
master - mean (95ms) : 93, 97
section CallTarget+Inlining+NGEN
This PR (7687) - mean (661ms) : 643, 678
master - mean (637ms) : 615, 658
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 (7687) - mean (221ms) : 204, 238
master - mean (193ms) : 189, 198
section Bailout
This PR (7687) - mean (218ms) : crit, 210, 226
master - mean (199ms) : 193, 204
section CallTarget+Inlining+NGEN
This PR (7687) - mean (1,229ms) : crit, 1170, 1289
master - mean (1,150ms) : 1100, 1200
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 (7687) - mean (307ms) : 296, 318
master - mean (276ms) : 272, 281
section Bailout
This PR (7687) - mean (308ms) : crit, 296, 321
master - mean (277ms) : 273, 281
section CallTarget+Inlining+NGEN
This PR (7687) - mean (1,011ms) : crit, 984, 1039
master - mean (900ms) : 865, 936
HttpMessageHandler (.NET 6)
gantt
title Execution time (ms) HttpMessageHandler (.NET 6)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (7687) - mean (302ms) : 289, 314
master - mean (271ms) : 264, 277
section Bailout
This PR (7687) - mean (301ms) : crit, 291, 311
master - mean (272ms) : 266, 277
section CallTarget+Inlining+NGEN
This PR (7687) - mean (1,048ms) : crit, 1012, 1084
master - mean (936ms) : 912, 960
HttpMessageHandler (.NET 8)
gantt
title Execution time (ms) HttpMessageHandler (.NET 8)
dateFormat x
axisFormat %Q
todayMarker off
section Baseline
This PR (7687) - mean (318ms) : 298, 338
master - mean (269ms) : 264, 275
section Bailout
This PR (7687) - mean (315ms) : crit, 295, 334
master - mean (269ms) : 265, 273
section CallTarget+Inlining+NGEN
This PR (7687) - mean (1,029ms) : crit, 956, 1102
master - mean (835ms) : 804, 866
BenchmarksBenchmark execution time: 2026-03-23 20:48:16 Comparing candidate commit 0c86384 in PR branch Found 11 performance improvements and 9 performance regressions! Performance is the same for 252 metrics, 16 unstable metrics.
|
Snapshots difference summaryThe following differences have been observed in committed snapshots. It is meant to help the reviewer. 1 occurrences of : - Name: internal,
- Resource: Quartz.Job.Execute,
+ Name: quartz.job.execute,
+ Resource: execute exceptionJob,
[...]
+ Error: 1,
[...]
+ error.msg: Expected InvalidOperationException thrown,
+ error.stack:
[...]
+ error.type: Quartz.JobExecutionException,
[...]
- job.group: group1,
- job.name: helloJob,
- job.type: QuartzSampleApp.Jobs.HelloJob,
+ job.group: group2,
+ job.name: exceptionJob,
+ job.type: QuartzSampleApp.Jobs.ExceptionJob,
[...]
- otel.status_code: STATUS_CODE_UNSET,
+ otel.status_code: STATUS_CODE_ERROR,
[...]
- trigger.group: group1,
- trigger.name: helloTrigger,
+ trigger.group: group2,
+ trigger.name: exceptionTrigger,
1 occurrences of : - Name: internal,
- Resource: Quartz.Job.Execute,
+ Name: quartz.job.execute,
+ Resource: execute helloJob,
[...]
- Error: 1,
[...]
- error.msg: Expected InvalidOperationException thrown,
- error.stack:
[...]
- error.type: Quartz.JobExecutionException,
[...]
- job.group: group2,
- job.name: exceptionJob,
- job.type: QuartzSampleApp.Jobs.ExceptionJob,
+ job.group: group1,
+ job.name: helloJob,
+ job.type: QuartzSampleApp.Jobs.HelloJob,
[...]
- otel.status_code: STATUS_CODE_ERROR,
+ otel.status_code: STATUS_CODE_UNSET,
[...]
- trigger.group: group2,
- trigger.name: exceptionTrigger,
+ trigger.group: group1,
+ trigger.name: helloTrigger,
|
6cbdd75 to
05709b9
Compare
| foreach (var tag in activity.Tags) | ||
| { | ||
| if (tag.Key == "job.name") | ||
| { | ||
| jobName = tag.Value; | ||
| break; | ||
| } | ||
| } |
There was a problem hiding this comment.
A couple of performance nits here (that I've only found after diving deep on this stuff recently 😅)
- In
IActivity5, you should use theTagObjectsproperty, notTags. - When enumerating these objects, you should use the new
ActivityEnumerationHelper.EnumerateTagObjectshelper (as we do now inOtlpHelpers)
Unfortunately, I made that helper a bit too specific, so I need to tweak it before you can use it here I think 😅 I can look into that in a subsequent PR 🙂
There was a problem hiding this comment.
waited long enough for this to become available! 🕺🏾
zacharycmontoya
left a comment
There was a problem hiding this comment.
LGTM! Nice work!
|
Need to update the PR summary as we're doing reverse ducktyping |
There was a problem hiding this comment.
@lucaspimentel Do we already have this information anywhere? 🤔
There was a problem hiding this comment.
I don't think so. At least not so explicitly.
| activity.AddTag(Tags.InstrumentationName, ComponentName); | ||
| var jobName = activity.Tags.FirstOrDefault(kv => kv.Key == "job.name").Value ?? string.Empty; | ||
|
|
||
| string? jobName = null; |
There was a problem hiding this comment.
We should probably rework this to be allocation free (the foreach will allocate) but that requires a bunch of refactoring to the ActivityEnumerationHelper so I'm happy to take a look in a follow up PR 😄
| #else | ||
| private static void StartDiagnosticManager() | ||
| { | ||
| var observers = new List<DiagnosticObserver> |
There was a problem hiding this comment.
Braindump:
There's a somewhat interesting knock-on effect of this work... Many integrations change their behavior when there's a diagnostic manager enabled and attached. In particular, this can have performance impacts, and in some cases change real behaviour.
I was considering whether we should check if the quartz integration is actually enabled before enabling this, but given that we can toggle that at runtime, and there's a global switch for disabling the diagnostic source integration entirely, I don't think there's anything more we need to do.
Co-authored-by: Lucas Pimentel <[email protected]>
Summary of changes
Adds
.NET Frameworksupport for theDiagnosticManager/DiagnosticObserverinfrastructure and uses it to enhance Quartz span metadata on both Framework and non-Frameworktargets.
Reason for change
The
DiagnosticObserverclass was previously gated behind#if !NETFRAMEWORK, limiting tracing integrations that depend on it to modern .NET only. Quartz is the firstImplementation details
DiagnosticManager — Framework support
On
!NETFRAMEWORK, the existing path is unchanged:DiagnosticListener.AllListeners.Subscribe(new DiagnosticListenerObserver(this)).On
NETFRAMEWORK,DiagnosticListenerisn't available at compile time (it ships as a NuGet package, not part of the BCL). Two problems had to be solved:AllListenersproperty — solved with reflection to locate theDiagnosticListenertype and read its static property at runtime.AllListeners.SubscribeexpectsIObserver<DiagnosticListener>(the real type). A newFrameworkDiagnosticListenerObserverreverse duck type(
[DuckReverseMethod]+.DuckImplement()) generates a proxy at runtime that satisfies the exact generic interface, forwarding eachOnNextcall back toDiagnosticManager.DiagnosticObserver — duck typed DiagnosticListener
SubscribeIfMatchwas updated to acceptIDiagnosticListener(a new duck type interface) instead of the concreteDiagnosticListener, removing the compile-time dependency onthe type across the whole observer hierarchy.
Quartz
QuartzDiagnosticObserveris registered inStartDiagnosticManagerunconditionally (both platforms).QuartzCommonwas enhanced to set thecomponent: quartztag and activity kind on the pre-IActivity5fallback path (< .NET 5), bringing its span metadata in line withnewer runtimes.
Cleanup
#if !NETFRAMEWORK/#elsesplit ofStartDiagnosticManagerinInstrumentation.csinto a single method with an inline directive.#if NETFRAMEWORKblock inActivityListener.csthat duplicatedCreateDiagnosticSourceListenerInstance— the IL emit approach works on Frameworktoo.
Test coverage
QuartzTestsV3NETFRAMEWORK.verified.txtcovering Quartz on .NET Framework.QuartzTestsV3NETCOREAPP3X.verified.txtto include thecomponent: quartztag now set on the pre-IActivity5path.Other details