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).
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;
}
}
}