[wip][nomerge] Add Tracing Configuration#126220
[wip][nomerge] Add Tracing Configuration#126220rosebyte wants to merge 6 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @steveisok, @dotnet/area-system-diagnostics-tracing |
There was a problem hiding this comment.
Pull request overview
This PR introduces a configurable tracing extensibility model spanning System.Diagnostics.DiagnosticSource (ActivitySource updates + factory abstractions) and Microsoft.Extensions.Diagnostics(.Abstractions) (DI builder, options/rules, and configuration binding) to enable/disable tracing per listener/source and support DI-created (scoped) ActivitySources.
Changes:
- Add
IActivitySourceFactory+ActivitySourceOptions.Scope/ActivitySource.Scopeto distinguish DI-created vs globally-constructedActivitySources, and enable factory-managed lifetimes. - Add
ActivitySource.UpdateActivityListener(...)to allow listeners to re-evaluateShouldListenToand update attached sources. - Add DI + configuration surface (
ITracingBuilder,IActivityListener,TracingOptions/TracingRule, configuration binding + tests) to control tracing enablement via rules and config.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs | Adds coverage for UpdateActivityListener behavior. |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/IActivitySourceFactory.cs | Introduces ActivitySource factory abstraction for DI/scoping. |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySourceOptions.cs | Adds Scope to carry an opaque scoping marker into ActivitySource. |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySourceFactoryExtensions.cs | Adds convenience Create(...) overload for factories. |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/ActivitySource.cs | Makes ActivitySource inheritable, adds Scope, adds UpdateActivityListener, and adds protected Dispose(bool). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj | Includes new DiagnosticSource compile items. |
| src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs | Updates public ref surface for new/changed ActivitySource APIs and new factory types. |
| src/libraries/Microsoft.Extensions.Diagnostics/tests/TracingConfigurationSampleTests.cs | Adds end-to-end tests demonstrating configuration + rule behavior and scope distinctions. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/TracingServiceExtensions.cs | Adds AddTracing(...) service registration entrypoints and startup activation. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/DefaultActivitySourceFactory.cs | Implements IActivitySourceFactory with caching and rules-driven listener enablement. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/Configuration/TracingConfigureOptions.cs | Binds configuration keys into TracingOptions.Rules. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/Configuration/TracingConfiguration.cs | Wraps configuration instances for later merging. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/Configuration/TracingBuilderExtensions.cs | Adds AddConfiguration(...) for ITracingBuilder. |
| src/libraries/Microsoft.Extensions.Diagnostics/src/Tracing/Configuration/ActivityListenerConfigurationFactory.cs | Merges per-listener configuration from multiple registrations. |
| src/libraries/Microsoft.Extensions.Diagnostics/ref/Microsoft.Extensions.Diagnostics.cs | Adds public ref surface for tracing DI extensions. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/tests/TracingBuilderExtensionsRulesTests.cs | Unit tests for builder/options rule extension methods. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/TracingRule.cs | Defines rule model for enablement matching. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/TracingOptions.cs | Adds options container for tracing rules. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/TracingBuilderExtensions.Rules.cs | Adds rule authoring helpers on builder/options. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/TracingBuilderExtensions.Listeners.cs | Adds listener registration/clearing helpers on builder. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/ITracingBuilder.cs | Introduces builder abstraction for tracing configuration. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/IActivityListener.cs | Introduces DI-friendly activity listener abstraction. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/src/Tracing/ActivitySourceScope.cs | Adds scope enum to distinguish global vs DI-created sources. |
| src/libraries/Microsoft.Extensions.Diagnostics.Abstractions/ref/Microsoft.Extensions.Diagnostics.Abstractions.cs | Adds public ref surface for the new abstractions and extension methods. |
| /// <summary> | ||
| /// Update the <see cref="ActivityListener"/> object to start or stop listening to the <see cref="Activity"/> events based on the listener configuration. | ||
| /// </summary> | ||
| /// <param name="listener"></param> |
There was a problem hiding this comment.
The XML docs for UpdateActivityListener have an empty <param name="listener"> element. Please describe what the listener represents (and any expectations, e.g., that it must have ShouldListenTo configured) so the public API docs are complete.
| /// <param name="listener"></param> | |
| /// <param name="listener">The <see cref="ActivityListener"/> instance whose configuration, in particular its <see cref="ActivityListener.ShouldListenTo"/> callback, determines which <see cref="ActivitySource"/> instances it should listen to.</param> |
|
|
||
| protected override void Dispose(bool disposing) | ||
| { | ||
| // no-op, disallow users from disposing of the meters created from the factory. |
There was a problem hiding this comment.
This comment appears to be copied from the metrics factory: FactoryActivitySource.Dispose says "meters" but this type represents activity sources. Please update the comment to avoid confusion when debugging/discovering the intent of the override.
| // no-op, disallow users from disposing of the meters created from the factory. | |
| // no-op, disallow users from disposing of the activity sources created by the factory. |
| { | ||
| ArgumentNullException.ThrowIfNull(listener); | ||
|
|
||
| if (!s_allListeners.Any(x => x == listener)) |
There was a problem hiding this comment.
How does this work if called multiple times concurrently?
| public IList<InstrumentRule> Rules { get; } = null!; | ||
| } | ||
| } | ||
| namespace Microsoft.Extensions.Diagnostics.Configuration |
There was a problem hiding this comment.
| namespace Microsoft.Extensions.Diagnostics.Configuration | |
| namespace Microsoft.Extensions.Diagnostics.Tracing |
?
| public static IMetricsBuilder AddConfiguration(this IMetricsBuilder builder, Microsoft.Extensions.Configuration.IConfiguration configuration) => throw null!; | ||
| } | ||
| } | ||
| namespace Microsoft.Extensions.Diagnostics.Configuration |
There was a problem hiding this comment.
| namespace Microsoft.Extensions.Diagnostics.Configuration | |
| namespace Microsoft.Extensions.Diagnostics.Tracing |
1af772d to
fd417fb
Compare
| return activitySourceFactory.Create(new ActivitySourceOptions(name) | ||
| { | ||
| Version = version, | ||
| Tags = tags, | ||
| Scope = activitySourceFactory, | ||
| }); |
There was a problem hiding this comment.
The factory extension sets ActivitySourceOptions.Version directly from the optional version parameter. When version is omitted this assigns null, which is inconsistent with ActivitySourceOptions' default of string.Empty and can lead to separate cache entries / different ActivitySource.Version values for otherwise identical sources. Consider only setting Version when a non-null value is provided (or normalize null to empty) to keep behavior consistent with the existing ActivitySource constructors/options defaults.
| return activitySourceFactory.Create(new ActivitySourceOptions(name) | |
| { | |
| Version = version, | |
| Tags = tags, | |
| Scope = activitySourceFactory, | |
| }); | |
| ActivitySourceOptions options = new(name) | |
| { | |
| Tags = tags, | |
| Scope = activitySourceFactory, | |
| }; | |
| if (version is not null) | |
| { | |
| options.Version = version; | |
| } | |
| return activitySourceFactory.Create(options); |
| if (options.Scope is not null && !ReferenceEquals(options.Scope, this)) | ||
| { | ||
| throw new InvalidOperationException(SR.InvalidScope); | ||
| } |
There was a problem hiding this comment.
SR.InvalidScope currently comes from the Microsoft.Extensions.Diagnostics resources and its text refers to "meter factory"/"meter" (see Strings.resx). Using it here for ActivitySourceFactory scope validation will produce a misleading exception message for tracing. Please introduce a tracing-specific resource string (or otherwise adjust) so the message refers to activity sources/tracing instead of meters.
| private static bool RuleMatches(TracingRule rule, string activitySourceName, string listenerName, bool isLocalScope) | ||
| { | ||
| if (!string.Equals(rule.ListenerName ?? string.Empty, listenerName, StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| return false; | ||
| } | ||
|
|
There was a problem hiding this comment.
RuleMatches requires rule.ListenerName ?? string.Empty to equal the requested listenerName, which means rules with ListenerName == null do not match any named listener. This contradicts the TracingRule docs (null matches all listeners) and differs from the existing metrics rule selector behavior. Consider treating null/empty ListenerName as a wildcard match, and update IsMoreSpecific accordingly so explicit listener names win over default rules.
| /// <summary> | ||
| /// Update the <see cref="ActivityListener"/> object to start or stop listening to the <see cref="Activity"/> events based on the listener configuration. | ||
| /// </summary> | ||
| /// <param name="listener"></param> |
There was a problem hiding this comment.
The XML docs for UpdateActivityListener have an empty <param name="listener"> entry. Please add a brief description (e.g., that it's the listener whose registration should be refreshed) to keep public API docs consistent with surrounding members.
| /// <param name="listener"></param> | |
| /// <param name="listener">The <see cref="ActivityListener"/> whose registration should be refreshed.</param> |
| /// <param name="builder">The <see cref="ITracingBuilder"/>.</param> | ||
| /// <param name="activitySourceName">The <see cref="ActivitySource.Name"/> or prefix. A null value matches all activity sources.</param> | ||
| /// <param name="listenerName">The <see cref="IActivityListener"/>.Name. A null value matches all listeners.</param> | ||
| /// <param name="scopes">A bitwise combination of the enumeration values that specifies the scopes to consider.</param> | ||
| /// <param name="enabled"><see langword="true"/> to enable matched activities; otherwise, <see langword="false"/>.</param> |
There was a problem hiding this comment.
The <see cref="IActivityListener"/>.Name references in these XML docs are not valid cref syntax and may produce documentation warnings. Use <see cref="IActivityListener.Name"/> (and similarly elsewhere in this file) so doc tooling can resolve the symbol correctly.
This pull request introduces a new extensibility model for configuring distributed tracing in the
Microsoft.Extensions.Diagnostics.Abstractionslibrary. It adds interfaces, options, rules, and extension methods to allow developers to register activity listeners and control which activities are enabled for tracing, with fine-grained rules and scopes.The most important changes are:
Tracing extensibility model
ITracingBuilderinterface to provide a builder pattern for configuring tracing and registeringIActivityListenerimplementations via dependency injection. [1] [2]IActivityListenerinterface, which allows custom listeners to receive activity lifecycle callbacks and participate in activity sampling. [1] [2]Tracing configuration and rules
TracingRuleclass andActivitySourceScopeenum to specify which activities are enabled for which listeners, supporting both global and DI-created activity sources. [1] [2] [3]TracingOptionsclass to hold a list ofTracingRuleobjects, enabling configuration of tracing behavior. [1] [2]Extension methods for configuration
TracingBuilderExtensionswith methods to add/clear listeners and enable/disable tracing for specific sources, listeners, and scopes, both on the builder and options. [1] [2] [3]new API surface