Search code examples
logging.net-coreasp.net-core-2.0

Is it possible to disable category output in .NET Core ConsoleLogger and DebugLogger?


I'm using a very typical (I think) setup for logging in a .NET Core console app I'm writing:

services.AddLogging(loggingBuilder => {
    loggingBuilder.AddConfiguration(Configuration.GetSection("Logging"));
    loggingBuilder.AddConsole();
    loggingBuilder.AddDebug();
});

To my eyes, the default output is difficult to read because it is polluted with contextual information that is of no interest to me:

Console (everything on the first line is unwanted noise):

info: MyApp.MyNamespace.OtherNamespace[0]
      The message I actually want to see

Debug (everything up to Information: is unwanted noise):

MyApp.MyNamespace.OtherNamespace:Information: The message I actually want to see

I assumed it would be easy to turn off this excess contextual information but so far I'm drawing a blank. Is it possible to disable this stuff short of writing a custom implementation of both ConsoleLogger and DebugLogger? (at which point it'd probably just be easier to use Log4Net).


Solution

  • Here's what I ended up writing to solve this problem (makes use of Crayon to colour the console output):

    using System;
    using System.Collections.Concurrent;
    using Crayon;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    
    namespace Kope.Pilot.Hrs.Utils.Logging
    {
        public class CleanConsoleLogger : ILogger
        {
            public LogLevel LogLevel { get; set; } = LogLevel.Information;
    
            public IDisposable BeginScope<TState>(TState state) => null;
    
            public bool IsEnabled(LogLevel logLevel) => logLevel >= this.LogLevel;
    
            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
            {
                if (!IsEnabled(logLevel))
                    return;
    
                string message = formatter(state, exception);
                if (exception != null)
                    message += $"{Environment.NewLine}{exception}";
    
                switch (logLevel)
                {
                    case LogLevel.Trace:
                        Console.Out.WriteLineAsync(Output.Bright.Black(message));
                        break;
                    case LogLevel.Debug:
                        Console.Out.WriteLineAsync(Output.Bright.Black(message));
                        break;
                    case LogLevel.Information:
                        Console.Out.WriteLineAsync(message);
                        break;
                    case LogLevel.Warning:
                        Console.Out.WriteLineAsync(Output.Dim().Yellow().Text(message));
                        break;
                    case LogLevel.Error:
                        Console.Error.WriteLineAsync(Output.Bright.Red(message));
                        break;
                    case LogLevel.Critical:
                        Console.Error.WriteLineAsync(Output.Bright.Red(message));
                        break;
                }
            }
        }
    
        public class CleanConsoleLoggerProvider : ILoggerProvider
        {
            private readonly ConcurrentDictionary<string, CleanConsoleLogger> _loggers = new ConcurrentDictionary<string, CleanConsoleLogger>();
            
            public ILogger CreateLogger(string categoryName)
                => _loggers.GetOrAdd(categoryName, name => new CleanConsoleLogger());
    
            public void Dispose()
            {
                _loggers.Clear();
            }
        }
    
        public static class CleanConsoleLoggerFactoryExtensions
        {
    
            public static ILoggingBuilder AddCleanConsole(this ILoggingBuilder builder)
            {
                builder.Services.AddSingleton<ILoggerProvider, CleanConsoleLoggerProvider>();
                return builder;
            }
    
        }
    }