Open thompson-tomo opened 2 years ago
Maybe something like this:
[ProviderAlias("DynamicNLog")]
public class DynamicNLogLoggerProvider : DynamicLoggerProviderBase
{
protected readonly IOptionsMonitor<LoggerFilterOptions> _filterOptions;
/// <summary>
/// Initializes a new instance of the <see cref="DynamicNLogLoggerProvider"/> class.
/// </summary>
/// <param name="filterOptions">Logger filters</param>
/// <param name="messageProcessors">message processors to apply to message</param>
public DynamicNLogLoggerProvider(IOptionsMonitor<LoggerFilterOptions> filterOptions, IEnumerable<IDynamicMessageProcessor> messageProcessors = null)
: base(() => new NLog.Extensions.Logging.NLogLoggingProvider(new NLog.Extensions.Logging() { RemoveLoggerFactoryFilter = false }), GetInitialLevelsFromOptions(filterOptions), messageProcessors)
{
}
private static InitialLevels GetInitialLevelsFromOptions(IOptionsMonitor<LoggerFilterOptions> filterOptions)
{
var runningLevelFilters = new Dictionary<string, Func<string, LogLevel, bool>>();
var originalLevels = new Dictionary<string, LogLevel>();
Filter filter = null;
foreach (var rule in filterOptions.CurrentValue.Rules.Where(p => string.IsNullOrEmpty(p.ProviderName) || p.ProviderName == "Console" || p.ProviderName == "Logging"))
{
originalLevels[rule.CategoryName ?? "Default"] = rule.LogLevel ?? LogLevel.None;
if (rule.CategoryName == "Default" || string.IsNullOrEmpty(rule.CategoryName))
{
filter = (category, level) => level >= (rule.LogLevel ?? LogLevel.None);
}
else
{
runningLevelFilters[rule.CategoryName] = (category, level) => level >= (rule.LogLevel ?? LogLevel.None);
}
}
return new InitialLevels
{
DefaultLevelFilter = filter,
OriginalLevels = originalLevels,
RunningLevelFilters = runningLevelFilters
};
}
}
RemoveLoggerFactoryFilter = false
will tell NLog to abide to default Microsoft Extension Logging Filters like the console-provider.
/// <summary>
/// Adds Dynamic NLog Logger Provider
/// </summary>
/// <param name="builder">Your ILoggingBuilder</param>
public static ILoggingBuilder AddDynamicNLog(this ILoggingBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
// only run if an IDynamicLoggerProvider hasn't already been added
if (!builder.Services.Any(sd => sd.ServiceType == typeof(IDynamicLoggerProvider)))
{
builder.AddFilter<DynamicNLogLoggerProvider>(null, LogLevel.Trace);
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, DynamicNLogLoggerProvider>());
builder.Services.AddSingleton((p) => p.GetServices<ILoggerProvider>().OfType<IDynamicLoggerProvider>().SingleOrDefault());
}
return builder;
}
That's a good starting point but would want to also include other functionality offered with serilog ie setting levels (src/Management/src/EndpointBase/Loggers/LoggersEndpoint.cs)
This would be a good candidate for community contribution. We are happy to help the effort along, but this is not likely a current priority for the core Steeltoe team
Is your feature request related to a problem? Please describe.
I have an on-premise micro service architecture with each application running dotnet core & nlog (company recommendation) and am needing a solution to centrally manage log levels. Currently my solution involves rebooting the services
Describe the solution you'd like
I would like NLog to have the same level of support as SeriLog
Describe alternatives you've considered
Switching to Serilog but I'd against corporate policies
Additional context
We should have a way of obtaining log levels from a microservice & adjusting them when using NLog