Aracılığıyla paylaş


Konsol günlük biçimlendirme

.NET 5'te, ad alanında Microsoft.Extensions.Logging.Console konsol günlüklerine özel biçimlendirme desteği eklendi. Önceden tanımlanmış üç biçimlendirme seçeneği vardır: Simple, Systemd, ve Json.

Önemli

Daha önce, ConsoleLoggerFormat numaralı liste, istenen günlük formatını seçmek için izin veriyordu; bu format, okunabilir olan Default veya Systemd olarak da bilinen tek satır idi. Ancak, bunlar özelleştirilebilir değildi ve artık kullanım dışı bırakıldı.

Bu makalede konsol günlüğü biçimlendiricileri hakkında bilgi edinacaksınız. Örnek kaynak kodu aşağıdakilerin nasıl yapılacağını gösterir:

  • Yeni bir biçimlendirici kaydet
  • Kullanılacak kayıtlı bir biçimlendirici seçin
  • Özel bir biçimlendirici uygulayın

Tavsiye

Günlük tutma örnek kaynak kodunun tamamı, indirilmek üzere Samples Browser'da bulunur. Daha fazla bilgi için Kod örneklerine göz atma: .NET'te günlük kaydı bölümüne bakın.

Kayıt biçimlendiricisi

GünlükConsole sağlayıcısı önceden tanımlanmış birkaç biçimlendiriciye sahiptir ve kendi özel biçimlendiricinizi yazma özelliğini kullanıma sunar. Kullanılabilir biçimlendiricilerden herhangi birini kaydetmek için ilgili Add{Type}Console uzantı yöntemini kullanın:

Kullanılabilir türler Tür kaydetme yöntemi
ConsoleFormatterNames.Json ConsoleLoggerExtensions.AddJsonConsole
ConsoleFormatterNames.Simple ConsoleLoggerExtensions.AddSimpleConsole
ConsoleFormatterNames.Systemd ConsoleLoggerExtensions.AddSystemdConsole

Basit

Konsol biçimlendiricisini Simple olarak kullanmak için AddSimpleConsole ile kaydedin:

using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddSimpleConsole(options =>
        {
            options.IncludeScopes = true;
            options.SingleLine = true;
            options.TimestampFormat = "HH:mm:ss ";
        }));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("[scope is enabled]"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("Logs contain timestamp and log level.");
    logger.LogInformation("Each log message is fit in a single line.");
}

Yukarıdaki örnek kaynak kodunda ConsoleFormatterNames.Simple biçimlendirici kaydedildi. Günlüklere yalnızca her günlük iletisinde zaman ve günlük düzeyi gibi bilgileri sarmalama olanağı sağlamanın yanı sıra, ANSI renk ekleme ve iletilerin girintilenmesine de olanak tanır.

Bu örnek uygulama çalıştırıldığında, günlük iletileri aşağıda gösterildiği gibi biçimlendirilir:

Basit biçimlendiriciyle yazılmış örnek konsol günlükleri.

Sistemli

Konsol ConsoleFormatterNames.Systemd günlükçü:

  • "Syslog" kaydedici düzey biçimi ve önem dereceleri kullanır
  • İletileri renklerle biçimlendirmez
  • İletileri her zaman tek bir satırda kaydeder

Systemd konsol günlüğünü sıklıkla kullanan kapsayıcılar için bu genellikle yararlıdır. .NET 5 ile konsol Simple günlükçüsü aynı zamanda tek bir satırda oturum açan kompakt bir sürüm sağlar ve önceki örnekte gösterildiği gibi renklerin devre dışı bırakılmasına da olanak tanır.

using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddSystemdConsole(options =>
        {
            options.IncludeScopes = true;
            options.TimestampFormat = "HH:mm:ss ";
        }));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("[scope is enabled]"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("Logs contain timestamp and log level.");
    logger.LogInformation("Systemd console logs never provide color options.");
    logger.LogInformation("Systemd console logs always appear in a single line.");
}

Örnek, aşağıdaki günlük iletilerine benzer bir çıkış oluşturur:

Systemd biçimlendiricisi ile yazılmış örnek konsol günlükleri.

Json

Günlükleri JSON biçiminde Json yazmak için konsol biçimlendiricisi kullanılır. Örnek kaynak kodu, bir ASP.NET Core uygulamasının bunu nasıl kaydedebileceğini gösterir. webapp Şablonu kullanarak dotnet new komutuyla yeni bir ASP.NET Core uygulaması oluşturun:

dotnet new webapp -o Console.ExampleFormatters.Json

Uygulamayı çalıştırırken şablon kodunu kullanarak aşağıdaki varsayılan günlük biçimini alırsınız:

info: Console.ExampleFormatters.Json.Startup[0]
      Hello .NET friends!
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\snippets\logging\console-formatter-json

Varsayılan olarak, Simple konsol günlüğü biçimlendiricisi varsayılan yapılandırmayla seçilir. AddJsonConsole çağırarak Program.cs'de bunu değiştirirsiniz.

using System.Text.Json;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Logging.AddJsonConsole(options =>
{
    options.IncludeScopes = false;
    options.TimestampFormat = "HH:mm:ss ";
    options.JsonWriterOptions = new JsonWriterOptions
    {
        Indented = true
    };
});

using IHost host = builder.Build();

var logger =
    host.Services
        .GetRequiredService<ILoggerFactory>()
        .CreateLogger<Program>();

logger.LogInformation("Hello .NET friends!");

await host.RunAsync();

Alternatif olarak, bunu appsettings.json dosyasında bulunan günlük yapılandırmasını kullanarak da yapılandırabilirsiniz:

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "json",
            "FormatterOptions": {
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

Yukarıdaki değişiklikle uygulamayı yeniden çalıştırın, günlük iletisi artık JSON olarak biçimlendirilir:

{
  "Timestamp": "02:28:19 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Console.ExampleFormatters.Json.Startup",
  "Message": "Hello .NET friends!",
  "State": {
    "Message": "Hello .NET friends!",
    "{OriginalFormat}": "Hello .NET friends!"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: https://localhost:5001",
  "State": {
    "Message": "Now listening on: https://localhost:5001",
    "address": "https://localhost:5001",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 14,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: http://localhost:5000",
  "State": {
    "Message": "Now listening on: http://localhost:5000",
    "address": "http://localhost:5000",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Application started. Press Ctrl\u002BC to shut down.",
  "State": {
    "Message": "Application started. Press Ctrl\u002BC to shut down.",
    "{OriginalFormat}": "Application started. Press Ctrl\u002BC to shut down."
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Hosting environment: Development",
  "State": {
    "Message": "Hosting environment: Development",
    "envName": "Development",
    "{OriginalFormat}": "Hosting environment: {envName}"
  }
}
{
  "Timestamp": "02:28:21 ",
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Content root path: .\\snippets\\logging\\console-formatter-json",
  "State": {
    "Message": "Content root path: .\\snippets\\logging\\console-formatter-json",
    "contentRoot": ".\\snippets\\logging\\console-formatter-json",
    "{OriginalFormat}": "Content root path: {contentRoot}"
  }
}

Tavsiye

Json Konsol biçimlendiricisi varsayılan olarak her iletiyi tek bir satırda günlüğe kaydeder. Biçimlendiriciyi yapılandırırken daha okunabilir hale getirmek için JsonWriterOptions.Indented öğesini true olarak ayarlayın.

Dikkat

Json konsol biçimlendiricisini kullanırken, JSON olarak serileştirilmiş günlük iletilerini geçirmeyin. Günlük altyapısı günlük iletilerinin seri hale getirilmesini zaten yönetir, dolayısıyla zaten serileştirilmiş bir günlük iletisi geçirecekseniz, çift seri hale getirilir ve bu da hatalı biçimlendirilmiş çıkışa neden olur.

Yapılandırma ile biçimlendirici ayarla

Önceki örneklerde bir biçimlendiricinin programatik olarak nasıl kaydedileceğini gösterilmiştir. Alternatif olarak, bu yapılandırma ile yapılabilir. Önceki web uygulaması örnek kaynak kodunu göz önünde bulundurun; Program.cs dosyasında çağırmak ConfigureLogging yerine appsettings.json dosyasını güncelleştirirseniz aynı sonucu elde edebilirsiniz. Güncelleştirilmiş appsettings.json dosya biçimlendiriciyi aşağıdaki gibi yapılandıracak:

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "json",
            "FormatterOptions": {
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

Ayarlanması gereken iki anahtar değer "FormatterName" ve "FormatterOptions" şeklindedir. "FormatterName" için değeri ayarlanmış bir biçimlendirici zaten kayıtlıysa, bu biçimlendirici seçilir ve özellikleri, "FormatterOptions" düğümü içinde anahtar olarak sağlandığı sürece yapılandırılabilir. "ConsoleFormatterNames altında önceden tanımlanmış biçimlendirici adları ayrılmıştır."

Özel bir biçimlendirici uygulayın

Özel bir biçimlendirici uygulamak için şunları yapmanız gerekir:

Bunu sizin için işlemek için bir uzantı yöntemi oluşturun:

using Microsoft.Extensions.Logging;

namespace Console.ExampleFormatters.Custom;

public static class ConsoleLoggerExtensions
{
    public static ILoggingBuilder AddCustomFormatter(
        this ILoggingBuilder builder,
        Action<CustomOptions> configure) =>
        builder.AddConsole(options => options.FormatterName = "customName")
            .AddConsoleFormatter<CustomFormatter, CustomOptions>(configure);
}

CustomOptions aşağıdaki gibi tanımlanır:

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomOptions : ConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }
}

Önceki kodda seçenekler ConsoleFormatterOptions'ün bir alt sınıfıdır.

AddConsoleFormatter API'si

  • Bir alt sınıfı kaydeder ConsoleFormatter
  • Yapılandırma ayarlarını işler
using Console.ExampleFormatters.Custom;
using Microsoft.Extensions.Logging;

using ILoggerFactory loggerFactory =
    LoggerFactory.Create(builder =>
        builder.AddCustomFormatter(options =>
            options.CustomPrefix = " ~~~~~ "));

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
using (logger.BeginScope("TODO: Add logic to enable scopes"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("TODO: Add logic to enable timestamp and log level info.");
}

CustomFormatter alt sınıfını ConsoleFormattertanımlayın:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomOptions _formatterOptions;

    public CustomFormatter(IOptionsMonitor<CustomOptions> options)
        // Case insensitive
        : base("customName") =>
        (_optionsReloadToken, _formatterOptions) =
            (options.OnChange(ReloadLoggerOptions), options.CurrentValue);

    private void ReloadLoggerOptions(CustomOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        string? message =
            logEntry.Formatter?.Invoke(
                logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        CustomLogicGoesHere(textWriter);
        textWriter.WriteLine(message);
    }

    private void CustomLogicGoesHere(TextWriter textWriter)
    {
        textWriter.Write(_formatterOptions.CustomPrefix);
    }

    public void Dispose() => _optionsReloadToken?.Dispose();
}

Önceki CustomFormatter.Write<TState> API, her bir günlük iletisinin etrafına hangi metnin sarıldığını belirler. Bir standart ConsoleFormatter , günlüklerin kapsamlarını, zaman damgalarını ve önem düzeylerini en azından kapsayabilmelidir. Ayrıca, günlük iletilerinde ANSI renklerini kodlayabilir ve istediğiniz girintileri de sağlayabilirsiniz. CustomFormatter.Write<TState>'nin uygulaması bu yeteneklere sahip değil.

Biçimlendirmeyi daha fazla özelleştirme konusunda ilham almak için ad alanında Microsoft.Extensions.Logging.Console mevcut uygulamalara bakın:

Özel yapılandırma seçenekleri

Günlük kaydının genişletilebilirliğini daha fazla özelleştirmek için türetilmiş ConsoleFormatterOptions sınıfınız herhangi bir yapılandırma sağlayıcısıyla yapılandırılabilir. Örneğin, özel seçeneklerinizi tanımlamak için JSON yapılandırma sağlayıcısını kullanabilirsiniz. Önce alt sınıfınızı ConsoleFormatterOptions tanımlayın.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.CustomWithConfig;

public sealed class CustomWrappingConsoleFormatterOptions : ConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }

    public string? CustomSuffix { get; set; }
}

Yukarıdaki konsol biçimlendirici seçenekleri sınıfı, ön ek ve son eki temsil eden iki özel özellik tanımlar. Ardından, konsol biçimlendirici seçeneklerinizi yapılandıracak appsettings.json dosyasını tanımlayın.

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "CustomTimePrefixingFormatter",
            "FormatterOptions": {
                "CustomPrefix": "|-<[",
                "CustomSuffix": "]>-|",
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss.ffff ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

Yukarıdaki JSON yapılandırma dosyasında:

  • "Logging" düğümü bir "Console" tanımlar.
  • "Console" düğümü, bir özel biçimlendiriciyle eşlenen "FormatterName""CustomTimePrefixingFormatter" öğesini belirtir.
  • Düğüm "FormatterOptions" , bir "CustomPrefix"ve "CustomSuffix"öğesinin yanı sıra diğer türetilmiş birkaç seçeneği tanımlar.

Tavsiye

$.Logging.Console.FormatterOptions JSON yolu ayrılmıştır ve ConsoleFormatterOptions uzantı yöntemi kullanılarak eklendiğinde özel AddConsoleFormatter ile eşleştirilir. Bu, kullanılabilir özelliklere ek olarak özel özellikleri tanımlama olanağı sağlar.

Aşağıdakileri CustomDatePrefixingFormattergöz önünde bulundurun:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.CustomWithConfig;

public sealed class CustomTimePrefixingFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomWrappingConsoleFormatterOptions _formatterOptions;

    public CustomTimePrefixingFormatter(
        IOptionsMonitor<CustomWrappingConsoleFormatterOptions> options)
        // Case insensitive
        : base(nameof(CustomTimePrefixingFormatter))
    {
        _optionsReloadToken = options.OnChange(ReloadLoggerOptions);
        _formatterOptions = options.CurrentValue;
    }

    private void ReloadLoggerOptions(CustomWrappingConsoleFormatterOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        string message =
            logEntry.Formatter(
                logEntry.State, logEntry.Exception);

        if (message == null)
        {
            return;
        }

        WritePrefix(textWriter);
        textWriter.Write(message);
        WriteSuffix(textWriter);
    }

    private void WritePrefix(TextWriter textWriter)
    {
        DateTime now = _formatterOptions.UseUtcTimestamp
            ? DateTime.UtcNow
            : DateTime.Now;

        textWriter.Write($"""
            {_formatterOptions.CustomPrefix} {now.ToString(_formatterOptions.TimestampFormat)}
            """);
    }

    private void WriteSuffix(TextWriter textWriter) =>
        textWriter.WriteLine($" {_formatterOptions.CustomSuffix}");

    public void Dispose() => _optionsReloadToken?.Dispose();
}

Önceki biçimlendirici uygulamasında:

Özel yapılandırma seçeneklerini kullanmak için, çağrı sırasında ConfigureLogging(IHostBuilder, Action<HostBuilderContext,ILoggingBuilder>) ile birlikte özel biçimlendirici uygulamalarını ekleyin.

using Console.ExampleFormatters.CustomWithConfig;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Logging.AddConsole()
    .AddConsoleFormatter<
        CustomTimePrefixingFormatter, CustomWrappingConsoleFormatterOptions>();

using IHost host = builder.Build();

ILoggerFactory loggerFactory = host.Services.GetRequiredService<ILoggerFactory>();
ILogger<Program> logger = loggerFactory.CreateLogger<Program>();

using (logger.BeginScope("Logging scope"))
{
    logger.LogInformation("Hello World!");
    logger.LogInformation("The .NET developer community happily welcomes you.");
}

Aşağıdaki konsol çıktısı, CustomTimePrefixingFormatter kullanarak görmeyi bekleyebileceğiniz şeye benzer.

|-<[ 15:03:15.6179 Hello World! ]>-|
|-<[ 15:03:15.6347 The .NET developer community happily welcomes you. ]>-|

Özel renk biçimlendirmesi uygulama

Özel günlük biçimlendiricinizde renk özelliklerini düzgün bir şekilde etkinleştirmek için, renkleri günlüklerde etkinleştirmek amacıyla kullanışlı bir SimpleConsoleFormatterOptions özelliği olduğundan SimpleConsoleFormatterOptions.ColorBehavior öğesini genişletebilirsiniz.

CustomColorOptions'den türetilen bir SimpleConsoleFormatterOptions oluşturun.

using Microsoft.Extensions.Logging.Console;

namespace Console.ExampleFormatters.Custom;

public class CustomColorOptions : SimpleConsoleFormatterOptions
{
    public string? CustomPrefix { get; set; }
}

Ardından, biçimlendirilmiş günlük iletilerine ANSI kodlu renkleri kolayca eklemenizi sağlayan bir TextWriterExtensions sınıfta bazı uzantı yöntemleri yazın:

namespace Console.ExampleFormatters.Custom;

public static class TextWriterExtensions
{
    const string DefaultForegroundColor = "\x1B[39m\x1B[22m";
    const string DefaultBackgroundColor = "\x1B[49m";

    public static void WriteWithColor(
        this TextWriter textWriter,
        string message,
        ConsoleColor? background,
        ConsoleColor? foreground)
    {
        // Order:
        //   1. background color
        //   2. foreground color
        //   3. message
        //   4. reset foreground color
        //   5. reset background color

        var backgroundColor = background.HasValue ? GetBackgroundColorEscapeCode(background.Value) : null;
        var foregroundColor = foreground.HasValue ? GetForegroundColorEscapeCode(foreground.Value) : null;

        if (backgroundColor != null)
        {
            textWriter.Write(backgroundColor);
        }
        if (foregroundColor != null)
        {
            textWriter.Write(foregroundColor);
        }

        textWriter.WriteLine(message);

        if (foregroundColor != null)
        {
            textWriter.Write(DefaultForegroundColor);
        }
        if (backgroundColor != null)
        {
            textWriter.Write(DefaultBackgroundColor);
        }
    }

    static string GetForegroundColorEscapeCode(ConsoleColor color) =>
        color switch
        {
            ConsoleColor.Black => "\x1B[30m",
            ConsoleColor.DarkRed => "\x1B[31m",
            ConsoleColor.DarkGreen => "\x1B[32m",
            ConsoleColor.DarkYellow => "\x1B[33m",
            ConsoleColor.DarkBlue => "\x1B[34m",
            ConsoleColor.DarkMagenta => "\x1B[35m",
            ConsoleColor.DarkCyan => "\x1B[36m",
            ConsoleColor.Gray => "\x1B[37m",
            ConsoleColor.Red => "\x1B[1m\x1B[31m",
            ConsoleColor.Green => "\x1B[1m\x1B[32m",
            ConsoleColor.Yellow => "\x1B[1m\x1B[33m",
            ConsoleColor.Blue => "\x1B[1m\x1B[34m",
            ConsoleColor.Magenta => "\x1B[1m\x1B[35m",
            ConsoleColor.Cyan => "\x1B[1m\x1B[36m",
            ConsoleColor.White => "\x1B[1m\x1B[37m",

            _ => DefaultForegroundColor
        };

    static string GetBackgroundColorEscapeCode(ConsoleColor color) =>
        color switch
        {
            ConsoleColor.Black => "\x1B[40m",
            ConsoleColor.DarkRed => "\x1B[41m",
            ConsoleColor.DarkGreen => "\x1B[42m",
            ConsoleColor.DarkYellow => "\x1B[43m",
            ConsoleColor.DarkBlue => "\x1B[44m",
            ConsoleColor.DarkMagenta => "\x1B[45m",
            ConsoleColor.DarkCyan => "\x1B[46m",
            ConsoleColor.Gray => "\x1B[47m",

            _ => DefaultBackgroundColor
        };
}

Özel renklerin uygulanmasını işleyen bir özel renk biçimlendirici aşağıdaki gibi tanımlanabilir:

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Options;

namespace Console.ExampleFormatters.Custom;

public sealed class CustomColorFormatter : ConsoleFormatter, IDisposable
{
    private readonly IDisposable? _optionsReloadToken;
    private CustomColorOptions _formatterOptions;

    private bool ConsoleColorFormattingEnabled =>
        _formatterOptions.ColorBehavior == LoggerColorBehavior.Enabled ||
        _formatterOptions.ColorBehavior == LoggerColorBehavior.Default &&
        System.Console.IsOutputRedirected == false;

    public CustomColorFormatter(IOptionsMonitor<CustomColorOptions> options)
        // Case insensitive
        : base("customName") =>
        (_optionsReloadToken, _formatterOptions) =
            (options.OnChange(ReloadLoggerOptions), options.CurrentValue);

    private void ReloadLoggerOptions(CustomColorOptions options) =>
        _formatterOptions = options;

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider? scopeProvider,
        TextWriter textWriter)
    {
        if (logEntry.Exception is null)
        {
            return;
        }

        string? message =
            logEntry.Formatter?.Invoke(
                logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        CustomLogicGoesHere(textWriter);
        textWriter.WriteLine(message);
    }

    private void CustomLogicGoesHere(TextWriter textWriter)
    {
        if (ConsoleColorFormattingEnabled)
        {
            textWriter.WriteWithColor(
                _formatterOptions.CustomPrefix ?? string.Empty,
                ConsoleColor.Black,
                ConsoleColor.Green);
        }
        else
        {
            textWriter.Write(_formatterOptions.CustomPrefix);
        }
    }

    public void Dispose() => _optionsReloadToken?.Dispose();
}

Uygulamayı çalıştırdığınızda, CustomPrefixFormatterOptions.ColorBehavior olduğunda, günlükler Enabled mesajını yeşil renkte gösterir.

Uyarı

LoggerColorBehavior Disabled olduğunda, günlük iletileri içinde gömülü olan ANSI renk kodlarını yorumlamaz. Bunun yerine ham mesajın çıktısını verir. Örneğin, aşağıdakileri göz önünde bulundurun:

logger.LogInformation("Random log \x1B[42mwith green background\x1B[49m message");

Birebir dizgeyi yazdırır ve renklendirilmemiştir.

Random log \x1B[42mwith green background\x1B[49m message

Ayrıca bakınız