Как получить уровень журнала в Json с Serilog -. NET Core 3.1 - PullRequest
3 голосов
/ 04 февраля 2020

Я новичок в Serilog и пытаюсь определить, как отправить сериализованный json в console с полями log level и date time. Похоже, в документации под structured data нет никакой информации.

Вот мой код, который вызывается в Startup.cs:

private void LoggerLoop(ILogger<Startup> logger)
{
    RabbitModel rb = new RabbitModel
    {
        Id = 1,
        DeviceNum = 1,
        DeviceName = "Device 1",
        InputNum = 1,
        InputName = "Input 1",
        InputState = 1,
        OnPhrase = "On",
        OffPhrase = "Off",
        When = "2020-01-01T22:45:00.1124303+00:00"
    };

    while (true)
    {
        logger.LogInformation("{@rb}", rb);
        Thread.Sleep(1000);
    }
}

А вот мой вывод:

[14:28:22 INF] {"Id": 1, "DeviceNum": 1, "DeviceName": "Device 1", "InputNum": 1, "InputName": "Input 1", "InputState": 1, "OnPhrase": "On", "OffPhrase": "Off", "When": "2020-01-01T22:45:00.1124303+00:00", "$type": "RabbitModel"}

I заметил, что он добавил поле $type и подумал, возможно ли добавить [14:28:22 INF] к json?

1 Ответ

2 голосов
/ 07 февраля 2020

Согласно приложению 12 factor приложение должно записывать все журналы в stdout / stderr.

Затем вам нужно собрать все журналы вместе и направить к одному или нескольким конечным пунктам назначения для просмотра ( Elasticserach ). Для этой цели доступны маршрутизаторы с открытым исходным кодом (например, FluentBit , Fluentd и Logplex ).

Итак, приложение никогда не касается сам с маршрутизацией или хранением своих логов. В приложении do tnet Вы можете легко добиться этого, используя Serilog

Допустим, у нас есть следующие настройки логгера в appsettings. json

"Logging": {
    "OutputFormat": "console",
    "MinimumLevel": "Information"
}

Мы можем создать метод расширения

private static IWebHostBuilder CreateWebHostBuilder() =>
    WebHost.CreateDefaultBuilder()
        .UseStartup<Startup>()
        .UseLogging();
}

, который может записывать журналы в консоль как в виде простого текста, так и в форматеasticsearch. Журналы в виде простого текста будут полезны для разработки, потому что они более удобочитаемы. На Производстве мы включаем форматasticsearch и видим все журналы только в Кибане.

Код расширения с комментариями:

public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder, string applicationName = null) =>
    webHostBuilder
        .UseSetting("suppressStatusMessages", "True") // disable startup logs
        .UseSerilog((context, loggerConfiguration) =>
        {
            var logLevel = context.Configuration.GetValue<string>("Logging:MinimumLevel"); // read level from appsettings.json
            if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
            {
                level = LogEventLevel.Information; // or set default value
            }

            // get application name from appsettings.json
            applicationName = string.IsNullOrWhiteSpace(applicationName) ? context.Configuration.GetValue<string>("App:Name") : applicationName;

            loggerConfiguration.Enrich
                .FromLogContext()
                .MinimumLevel.Is(level)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .MinimumLevel.Override("System", LogEventLevel.Warning)
                .Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
                .Enrich.WithProperty("ApplicationName", applicationName);

            // read other Serilog configuration
            loggerConfiguration.ReadFrom.Configuration(context.Configuration);

            // get output format from appsettings.json. 
            var outputFormat = context.Configuration.GetValue<string>("Logging:OutputFormat");
            switch (outputFormat)
            {
                case "elasticsearch":
                    loggerConfiguration.WriteTo.Console(new ElasticsearchJsonFormatter());
                    break;
                default:
                    loggerConfiguration.WriteTo.Console(
                        theme: AnsiConsoleTheme.Code,
                        outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss.sssZ} {Level:u3}] {Message:lj} <s:{Environment}{Application}/{SourceContext}>{NewLine}{Exception}");
                    break;
            }
        });

Когда OutputFormat равен elasticsearch, журнал будет похож на

{"@ timestamp": "2020-02-07T16: 02: 03.4329033 + 02: 00", "level": "Information", "messageTemplate": "Получить клиента по id: {CustomerId } "," message ":" Получить клиента по id: 20 "," fields ": {" CustomerId ": 20," SourceContext ":" Customers.Api.Controllers.CustomerController "," ActionId ":" c9d77549-bb25- 4f87-8ea8-576dc6aa1c57 "," ActionName ":" Customers.Api.Controllers.CustomerController.Get (Customers.Api) "," RequestId ":" 0HLTBQP5CQHLM: 00000004 "," RequestPath ":" / v1 / Customers "," CorrelationId ":" daef8849b662117e», "ConnectionId": "0HLTBQP5CQHLM", "Окружающая среда": "Развитие", "ApplicationName": "API", "Отметка": "2020-02-07T14: 02: 03.4329033Z"}}

в другом случае (использовать только для отладки)

[20-02-07 13: 59: 16.16Z INF] Получить клиента по id: 20

Тогда вам нужно настроить лог-маршрут r собрать журналы из контейнера и отправить их в Elasticsearch.

Если все журналы структурированы , это улучшает поиск и создание индексов в Kibana.

...