Avoid eager trace payload construction when diagnostics are disabled - #1381
Conversation
Guard trace formatting, factories, and exception payloads by EventSource level, and defer high-cost orchestration and Service Bus diagnostics until enabled. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e3e6992e-5a08-4288-8c62-c12f9cf27e8f
There was a problem hiding this comment.
Pull request overview
This PR improves tracing performance by ensuring expensive diagnostic payload construction (factories, formatting, exception payload strings, runtime-state serialization, batch joins) is deferred until the corresponding EventSource level is actually enabled, keeping enabled payloads/events unchanged.
Changes:
- Add an internal
DefaultEventSource.Log.IsEventEnabled(TraceEventType)helper and use it to early-return fromTraceHelperfactory/format/exception helpers when disabled. - Update high-throughput call sites (orchestration dispatcher + Service Bus) to wrap expensive formatting inside
Func<string>so work is skipped when diagnostics are off. - Add regression tests intended to verify factories/formatting are skipped when disabled and run exactly once when enabled (note: current test file location likely prevents execution in CI on case-sensitive filesystems).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Test/DurableTask.Core.Tests/TraceHelperTests.cs | Adds regression tests for lazy factory/format/exception payload evaluation (currently placed under legacy Test/ tree). |
| src/DurableTask.Core/Tracing/TraceHelper.cs | Adds level guards to prevent eager payload construction for factory/format/exception helpers. |
| src/DurableTask.Core/Tracing/DefaultEventSource.cs | Introduces IsEventEnabled(TraceEventType) to map trace levels to EventSource enablement checks. |
| src/DurableTask.Core/TaskOrchestrationDispatcher.cs | Defers runtime-state serialization and decision formatting behind Func<string> (only when enabled). |
| src/DurableTask.ServiceBus/ServiceBusOrchestrationService.cs | Defers batch/message formatting (string.Join, LINQ, etc.) behind Func<string> (only when enabled). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cgillum
left a comment
There was a problem hiding this comment.
This is a nice improvement. One caveat, however, is that I think Windows App Service-hosted apps capture all ETW trace levels by default, which means we won't observe improvements for those apps. However, I expect this will help with anything hosted on Linux or outside of App Service.
Summary
TraceHelperfactory, format, and exception payload construction with the matchingEventSourcelevel checkCompatibility and performance
This does not change public APIs or EventSource event IDs/schemas. Enabled diagnostic payloads remain unchanged. When the requested level is disabled, high-throughput dispatch paths now avoid runtime-state serialization, LINQ enumeration,
string.Join, interpolation, and final formatting allocations.Validation
dotnet test Test\DurableTask.Core.Tests\DurableTask.Core.Tests.csproj -f net8.0 --filter "FullyQualifiedName~TraceHelperTests|FullyQualifiedName~CommonTests.ShouldValidateEventSource"dotnet test Test\DurableTask.Core.Tests\DurableTask.Core.Tests.csproj -f net48 --filter "FullyQualifiedName~TraceHelperTests|FullyQualifiedName~CommonTests.ShouldValidateEventSource"dotnet build src\DurableTask.ServiceBus\DurableTask.ServiceBus.csprojFixes #1377