Description
Background and motivation
When writing a custom logging provider, it's not uncommon to want to provide a default logging scope backed by NullExternalScopeProvider/NullScope. This provides a good default for log providers or situations that either don't require scope support or where a sane default is required and can be replaced later (e.g. by the logger provider implementing ISupportExternalScope
).
API Proposal
NullExternalScopeProvider and NullScope should change their visibility from internal
to public
.
/// <summary>
/// An empty scope without any logic
/// </summary>
- internal sealed class NullScope : IDisposable
+ public sealed class NullScope : IDisposable
}
/// <summary>
/// Scope provider that does nothing.
/// </summary>
- internal sealed class NullExternalScopeProvider : IExternalScopeProvider
+ public sealed class NullExternalScopeProvider : IExternalScopeProvider
Because these types are specifically designed as no-op replacements, no additional changes or considerations are required.
API Usage
This example assumes that NullExternalScopeProvider.Instance
is passed in the logger provider's CreateScope instance. It features support for later updating the scope provider should the logger provider implement ISupportExternalScope
public sealed class MyLogger(IExternalScopeProvider? scopeProvider)
{
internal IExternalScopeProvider? ScopeProvider { get; set; } = scopeProvider;
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
=> ScopeProvider?.Push(state) ?? NullScope.Instance;
// Remaining members excluded for brevity.
}
Alternative Designs
Currently, consumers of M.E.L that intend to write their own logger provider are required to implement their own no-op scope and scope provider types, should they wish for this functionality.
Risks
No expected risks. These no-op scope and scope provider types are agnostic to the ultimate destination of the logger.