File: System\Diagnostics\ActivitySourceFactory.cs
Web Access
Project: src\runtime\src\libraries\System.Diagnostics.DiagnosticSource\src\System.Diagnostics.DiagnosticSource.csproj (System.Diagnostics.DiagnosticSource)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;

namespace System.Diagnostics
{
    /// <summary>
    /// A factory for creating <see cref="ActivitySource"/> instances.
    /// </summary>
    /// <remarks>
    /// Activity source factories are responsible for creating and caching activity sources. Derived classes implement
    /// <see cref="CreateCore(ActivitySourceOptions)"/> to provide the actual creation logic; the framework invariants
    /// (null and scope validation, scope assignment) are enforced by the base class.
    /// </remarks>
    public abstract class ActivitySourceFactory : IDisposable
    {
        /// <summary>
        /// Creates an <see cref="ActivitySource"/> using the supplied <paramref name="options"/>.
        /// </summary>
        /// <param name="options">The <see cref="ActivitySourceOptions"/> describing the activity source to create.</param>
        /// <returns>An <see cref="ActivitySource"/> configured with the supplied <paramref name="options"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="options"/> is <see langword="null"/>.</exception>
        /// <exception cref="InvalidOperationException"><see cref="ActivitySourceOptions.Scope"/> is set to a value other than this factory.</exception>
        /// <remarks>
        /// The base implementation validates <paramref name="options"/>, then constructs a fresh
        /// <see cref="ActivitySourceOptions"/> copy with <see cref="ActivitySourceOptions.Scope"/> bound to this factory
        /// and delegates construction to <see cref="CreateCore(ActivitySourceOptions)"/>. The caller-supplied
        /// <paramref name="options"/> instance is never mutated, so concurrent calls that share an options instance are
        /// safe.
        /// </remarks>
        public ActivitySource Create(ActivitySourceOptions options)
        {
            ArgumentNullException.ThrowIfNull(options);

            if (options.Scope is not null && !ReferenceEquals(options.Scope, this))
            {
                throw new InvalidOperationException(SR.InvalidActivitySourceScope);
            }

            ActivitySourceOptions scoped = new(options.Name)
            {
                Version = options.Version,
                Tags = options.Tags,
                TelemetrySchemaUrl = options.TelemetrySchemaUrl,
                Scope = this,
            };

            return CreateCore(scoped);
        }

        /// <summary>
        /// Creates an <see cref="ActivitySource"/> with the specified <paramref name="name"/>, <paramref name="version"/>, and <paramref name="tags"/>.
        /// </summary>
        /// <param name="name">The name of the <see cref="ActivitySource"/>.</param>
        /// <param name="version">The version of the <see cref="ActivitySource"/>.</param>
        /// <param name="tags">The tags to associate with the <see cref="ActivitySource"/>.</param>
        /// <returns>An <see cref="ActivitySource"/> with the specified <paramref name="name"/>, <paramref name="version"/>, and <paramref name="tags"/>.</returns>
        public ActivitySource Create(string name, string? version = "", IEnumerable<KeyValuePair<string, object?>>? tags = null)
        {
            ActivitySourceOptions options = new(name)
            {
                Version = version,
                Tags = tags,
            };

            return Create(options);
        }

        /// <summary>
        /// When overridden in a derived class, creates the <see cref="ActivitySource"/> for the supplied <paramref name="options"/>.
        /// </summary>
        /// <param name="options">The <see cref="ActivitySourceOptions"/> describing the activity source to create.
        /// <see cref="ActivitySourceOptions.Scope"/> is guaranteed to be set to this factory.</param>
        /// <returns>An <see cref="ActivitySource"/> configured with the supplied <paramref name="options"/>.</returns>
        /// <remarks>
        /// Derived classes implement this method to perform the actual creation (and optional caching) of the
        /// <see cref="ActivitySource"/>. The supplied <paramref name="options"/> have already been validated and the
        /// <see cref="ActivitySourceOptions.Scope"/> property has been set to this factory instance; derived classes
        /// should forward the options to the <see cref="ActivitySource"/> constructor unchanged.
        /// </remarks>
        protected abstract ActivitySource CreateCore(ActivitySourceOptions options);

        /// <summary>
        /// Releases all resources used by the <see cref="ActivitySourceFactory"/>.
        /// </summary>
        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="ActivitySourceFactory"/> and optionally releases the managed resources.
        /// </summary>
        /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
        }
    }
}