# Журналювання у програмах ASP.NET (частина 1... ймовірно)

<!--category-- Logging,Serilog,ASP.NET,C# -->
<datetime class="hidden">2024-10-27T17:00</datetime>

# Вступ

Лісозаготівля є невід'ємною частиною програм, але я часто бачу, що вона неправильно зрозуміла / неправильно використана у програмах ASP.NET. Це пост і частково виявлений спосіб ефективної реєстрації у програмах ASP. NET.

Це не повний посібник для ведення лісозаготівлі; там є LOTS; це більше стосується ефективної стратегії ведення лісозаготівель для ваших програм ASP.NET.

Основним веденням лісозаготівлі має бути USEROWE; чи буде він веденням журналу під час вашого розвитку, чи веденням журналу, він буде корисним для вас або вашої команди / ваших користувачів.

[TOC]

# Проблема

Надто часто лісозаготівля вважається "це тільки тоді, коли є якісь винятки. Я думаю, це не так, як має бути лісозаготівля.

**БЛИЗЬКІСТЬ НЕ Є ТІЛЬКИ ДЛЯ ВИЯВЛЕННЯ**

Загалом кажучи, ви можете запустити значну частину вашої програми локально; у цьому контексті `log.LogInformation`  твій друг.

# Розв'язання

## Успішний ведення журналу

Протягом 30 років я писав код, я бачив кілька прикладів хороших лісозаготівель і майже більше прикладів поганої лісозаготівлі.

Принципи хорошої лісозаготівлі:

1. Вхід у розвиток повинен надати достатніх відомостей про те, як виконується ваша програма, щоб зрозуміти, що відбувається, коли.
2. Вхід у систему Виробництва надасть вам дуже швидкого і простого механізму для розуміння помилок вашої програми.
3. ВІД НАШОГО ДОПИСУВАЧА У ВЕЛИКОБРИТАНІЇ

Пам' ятайте; журналювання ALWAYS тягне вниз швидкодію вашої програми; вам слід записувати все, що потрібно для визначення проблеми, але більше не у виробінні /, де швидкодія є критичною (наприклад, не пропускайте тест швидкодії, якщо ви використовуєте повний журнал зневаджування).

## Типи журналу в ASP.NET

### Serilog проти Microsoft. Extensions. loging

У ASP. NET вже побудовано систему ведення журналу; `Microsoft.Extensions.Logging`. Це гарна система лісозаготівлі, але вона не така гнучка, як серілог. Серілог - це гнучкіша система ведення журналу, яка надає вам змогу входити до декількох тонурів (вигульків) і збагачувати ваші журнали додатковими відомостями.

### Притопний ліс

Це журналювання, яке відбувається після запуску вашої програми. Це перше, що станеться, і це перше, що ви повинні побачити, коли запустите свою заявку. У ASP.NET особливо, коли ви використовуєте налаштування, це важливо, ви розумієте, що відбувається, коли ваша програма запускається. Це надзвичайно поширене джерело проблем в програмах ASP.NET.

Наприклад, у Serilog ви можете зробити це:

```csharp
Log.Logger = new LoggerConfiguration()
             .WriteTo.Console()
             .WriteTo.File("logs/boot-*.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7)
             .CreateBootstrapLogger();
```

*ЗАУВАЖЕННЯ: цей параметр обмежений, оскільки ви не маєте доступу до налаштувань, отже, наприклад, для використання AppInsights вам, ймовірно, знадобиться `#if RELEASE` блок для встановлення відповідного ключа.*

Це надає вам дані щодо всіх проблем, пов' язаних з запуском у вашій програмі; вона пише як у консоль, так і до файла. Важливо також переконатися, що ви не зберігаєте ВСІ файли журналів; ви можете побачити тут, що ми зберігаємо лише 7 днів вартості журналів.

Ви також бажаєте загорнути ваш метод запуску (у цій програмі я використовую новий `Program.cs` метод) за допомогою try/ knaet і записуйте всі винятки, які там трапляються.

```csharp
try
 {
        ..all your startup code
 }
catch (Exception ex)
{
    if(args.Contains("migrate"))
    {
        Log.Information("Migration complete");
        return;
    }
    Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}
```

Журнал. CloseADFlush} важливий, оскільки забезпечує запис всіх журналів на диск (ваша програма зазнає краху, отже, у іншому випадку вона завершить роботу перед тим, як зробить це).

За допомогою цього пункту я також можу визначити, чи запущено програму у режимі міграції, і, якщо так, фіксувати цей режим і виходити з нього.

`Log.Fatal` є найсуворішим рівнем журналу; його буде використано під час аварійного завершення роботи програми.
*Не всі винятки смертельні* - ви повинні використовувати `Log.Error` для тих (якщо вони не означають, що APP (а не запит) не може продовжуватися поза цією точкою).

## Рівні журналу

У ASP. NET (і. NET більш загально) є декілька рівнів журналу:

1. `Log.Fatal` - Це найсуворіший рівень журналу. Він використовується під час аварійного завершення роботи програми.
2. `Log.Error` - Цей параметр використовується, якщо трапляється виняток, що означає, що APP (не запит) не може продовжуватися поза цією точкою.
3. `Log.Warning` - Це використовується, коли щось трапляється, це не помилка, але щось, про що вам слід знати (наприклад, зіпсована служба / щось) *не зовсім правий* але не помилка).
4. `Log.Information` - Це використовується для загальної інформації про те, що відбувається у вашій заяві.
5. `Log.Debug` - Це використовується для інформації, яка корисна лише для усування вад у вашій програмі (ВСЮ ВСЕ в розробці, але її слід вимкнути у виробництві).

Для виробництва я б зазвичай встановив, що лісозаготівля - це `Log.Fatal`, `Log.Error` і `Log.Warning` Только.

## Журналювання під час виконання

На відміну від запуску входу до журналу, це журнал, який відбувається під час запуску вашої програми. Це журналювання, який повідомляє вам про те, що відбувається у вашій програмі у будь-який час.

Наприклад, щоб скористатися цими у серілогах, ви можете зробити ось що:

```json
  "Serilog": {
    "Enrich": ["FromLogContext", "WithThreadId", "WithThreadName", "WithProcessId", "WithProcessName", "FromLogContext"],
    "MinimumLevel": "Warning",
    "WriteTo": [
        {
          "Name": "Seq",
          "Args":
          {
            "serverUrl": "http://seq:5341",
            "apiKey": ""
          }
        },
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/applog-.txt",
          "rollingInterval": "Day"
        }
      }

    ],
    "Properties": {
      "ApplicationName": "mostlylucid"
    }
  },
```

## ЕнріксCity in Germany

Як бачите, я дуже великий прихильник серілога; це чудова лісозаготівельна бібліотека, дуже гнучка. Мені подобається здатність збагачувати ваші журнали додатковою інформацією. Це може бути дуже корисним у діагностуванні проблем у вашій програмі.
У наведеному вище прикладі ви можете бачити, що я збагачую свої журнали ідентифікатором нитки, ім'ям гілки, ідентифікатором процесу і назвою процесу. Це може бути дуже корисним у діагностуванні проблем у вашій програмі.

Я також встановлю для ведення журналу декілька "инків" (вигуків); у цьому випадку я відсилаю їх до консолі, до файла і до Сека (служби лісозаготівель).

Множина раковини буде корисною у випадку невдачі, у цьому випадку моя улюблена послуга лісозаготівлі - Сек, тому я відіслав її туди першим. Тоді, якщо це не вдасться, я відішлю його до консолі і до файла.

Крім того, ви можете вказати у журналі властивість applicationName. Ця властивість може бути корисною, якщо у вас є декілька програм, які входять до тієї самої служби (яка для поширених програм, які ви часто виконуєте, разом з ідентифікатором кореляції, який зв' яже ці журнали для окремого запиту).

Наприклад, якщо у вас є графічна оболонка JS і сервер. NET, ви можете встановити ідентифікатор кореляції у передній частині і передати його серверу. За допомогою цього пункту ви можете переглянути всі журнали одного запиту у одному місці. АБО, якщо ви використовуєте HtpClient у вашому сервері, ви можете передати ідентифікатор співвідношення у заголовках до іншої служби.

Існує чудова інформація про те, як ви могли б зробити це: https: // josef. codes/append- correation- id- all-log- entries- in- asp- net- core /, але я повідомлю про це у наступних повідомленнях.

## Структурований журнал

Структурований журналювання - це спосіб ведення журналу, який полегшує пошук і фільтрування ваших журналів. У серилогах ви можете зробити це за допомогою `Log.Information("This is a log message with {Property1} and {Property2}", property1, property2);` синтаксис. Це полегшує пошук журналів з певною властивістю.

## Контекстна реєстрація

Використання серілогів можна також використовувати `LogContext.PushProperty` щоб додати властивості до ваших журналів, які відповідають лише певній області видимості. Це може бути дуже корисним у діагностуванні проблем у вашій програмі.

## Налаштування серілогів

Серілог дуже гнучкий, оскільки надає вам змогу налаштувати його у коді, а також за допомогою налаштувань.
Наприклад, щоб скористатися параметрами, наведеними вище, ви можете зробити це:

```csharp
builder.Host.UseSerilog((context, services, configuration) =>
{
    configuration
        .MinimumLevel.Warning()
        .Enrich.FromLogContext()
        .Enrich.WithThreadId()
        .Enrich.WithThreadName()
        .Enrich.WithProcessId()
        .Enrich.WithProcessName()
        .WriteTo.Seq("http://seq:5341", apiKey: "")
        .WriteTo.Console()
        .WriteTo.File("logs/applog-.txt", rollingInterval: RollingInterval.Day)
        .Enrich.WithProperty("ApplicationName", "mostlylucid");
});

```

Це те саме, що і налаштування, які було наведено вище, але у коді. Це корисно, якщо ви бажаєте налаштувати ваші записи журналу у коді, вам залежить від того, як ви це робите.

# Фільтри виключення

У ASP. NET ви можете скористатися фільтрами Винятки для того, щоб у них можна було знайти винятки і зареєструвати їх. Це чудовий спосіб переконатися, що ви записуєте всі винятки у вашій програмі.
ЯК ЖЕ це не є замінником рівня ведення журналу методів; вам все ще слід записуватися на рівні методу так, щоб ви могли бачити, що відбувається у вашій програмі з подробицями; фільтр виключення просто показує, що відбувається після того, як весь стос запиту буде вимкнено і часто може бути дуже заплутаним, щоб розібратися у тому, що сталося.

Це змінилося в ASPNET Core 8 і є ТОН, ви можете зробити з цим [нові можливості](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0).

Вада знову застосування тих самих принципів; вам слід записуватися на рівні методу так, щоб ви могли бачити, що відбувається у вашій програмі з подробицями; фільтри виключення / визначення стану просто показують, що відбувається після того, як весь стос запитів буде вимкнено, і часто це може дуже спантеличувати вас, щоб розібратися у тому, що сталося.

# НЕ БЛИЗЬКО ВСІХ ЛЮДЕЙ

Журналювання має бути відповідним для середовища. У розділі Розвиток ви записуєте все, щоб бачити події, які відбуваються у кожному з точок вашої програми, але у Test вам потрібно менше журналу (можливо, журнал Інформація тут), а у процесі створення вам потрібно менше (Вартість і вище).

Це спокуса записати все в виробництві, але це погана ідея. Вам слід записати все необхідне, щоб поставити діагноз, але не більше. У провайдерах хмар ви можете легко отримати заряд за об' єм даних, які ви надсилаєте до служби ведення журналу, отже вам слід бути обережними з тим, скільки часу ви зберігатимете ці журнали (типово, журнал " Проникливість " зберігає журнали на 90 днів; часто це значення TOO ДОВГО, воно коштуватиме вам протягом того часу, доки зберігатимуться дані журналу).

Для дуже "активної" програми вам просто не знадобиться довгострокова лісозаготівля цих даних; ви маєте уявлення про те, що відбувається з програмою за останні декілька днів лісозаготівлі.

## Запитати журналювання

Коли я бачу поширене питання в виробництві - ведення лісозаготівельних запитів про невдачу, а ці можуть бути цікавими (нетілес хоче 404 / 401), вони можуть бути величезною кількістю даних, що може бути дуже дорогим для зберігання. Вам слід записувати лише записи *ви маєте намір виправити*, для 404 може бути, що це є важливим, але воно може вказувати на поламане посилання у вашій програмі; для 401 це може бути важливим, оскільки воно може вказувати на пошкоджену систему розпізнавання.

ЯК БИ я не згадував вище, вони краще оброблені в коді, в якому вони насправді відбуваються (у випадку 401), може бути, що вони також повинні бути зареєстровані як `Warning` або `Error` в коді, який насправді створює 401.

Щоб налаштувати запит на ведення журналу у системному журналі, ви можете зробити це:

```csharp
app.UseSerilogRequestLogging();
```

За допомогою цього пункту можна зареєструвати всі запити до вашої програми; це чудовий спосіб спостерігати за тим, що відбувається у вашій програмі на високому рівні. Але знову ж таки, вам слід бути обережними з тим, які дані ви ведете до журналу і скільки часу ви зберігатимете ці журнали.

Для " Проникливість у суть програми " вам, можливо, захочеться увійти до системи з використанням " Інформаційного рівня," оскільки це надасть вам доступ до низьких можливостей подорожі користувача. Це чудовий спосіб бачити, як користувачі використовують вашу програму, і може бути дуже корисним у проблемах з діагностуванням; але знову ж таки, ці проблеми швидко стискають витрати, отже вам слід бути обережними з тим, що ви ведете до журналу, і з часом, протягом якого ви зберігаєте ці журнали.

# Включення

Ось і все, швидко пройти через те, як увійти до програм ASP.NET. Більшість з них - це реакція на надмірні, непотрібні журнали, які я бачу у багатьох промислових програмах.
У розробці ви бажаєте бачити *спосіб роботи програми*; у створенні, яке ви хочете бачити *спосіб, у який програма зазнає невдачі*.
Журналювання надто часто є марною, дорогою частиною розвитку програми. Так само, як і все у програмному розробці, журналювання має бути фокусовано на USER; чи ви / інші розробники програми під час роботи над програмою у вашому IDE / local, чи сортування проблем у виробництві швидко і ефективно.