Is there a way to format the output format in .NET Core logging?

BooFar picture BooFar · May 28, 2017 · Viewed 16.3k times · Source

I'm using the built in logging provider for logging into the console (Microsoft.Extensions.Logging.Console) in a .NET Core console application.

Each logging entry produces two lines in the output. I would like to have each entry in one single line. Is there a way to customize the output format?

Here is an example how I use it:

static void Main(string[] args)
{
    var serviceProvider = new ServiceCollection()
      .AddLogging() // This adds the Microsoft logging.
      .AddSingleton<IProjectGeneratorService, CSharpProjectGeneratorService>()
      .BuildServiceProvider();

    // Configure the console logging.
    serviceProvider
      .GetService<ILoggerFactory>()
      .AddConsole(LogLevel.Debug);

    // Write a logging entry
    var logger = serviceProvider.GetService<ILoggerFactory>().CreateLogger<Program>();
    logger.LogDebug("Application started...");
}

What I get is:

dbug: Generator.Program[0]
      Application started...

What I would like to have is something like this:

dbug: Generator.Program[0]: Application started...

Any idea? I know, I could write a custom logger, but I would like to know if there is an other way.

Thanks.

Answer

Ilya Chumakov picture Ilya Chumakov · May 28, 2017

As @MartinUllrich already mentioned this line break can't be disabled and you have to implement a custom logger to avoid it.

Registration:

loggerFactory.AddProvider(new CustomLoggerProvider());

The implementation (can be extended with using of the original ConsoleLogger source code - for example, you could add the GetLogLevelConsoleColors method):

public class CustomLoggerProvider : ILoggerProvider
{
    public void Dispose() { }

    public ILogger CreateLogger(string categoryName)
    {
        return new CustomConsoleLogger(categoryName);
    }

    public class CustomConsoleLogger : ILogger
    {
        private readonly string _categoryName;

        public CustomConsoleLogger(string categoryName)
        {
            _categoryName = categoryName;
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            Console.WriteLine($"{logLevel}: {_categoryName}[{eventId.Id}]: {formatter(state, exception)}");
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return true;
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }
    }
}