Нові стандартні механізми

механізми

Це невелика серія статей про нові стандартні механізми у .NET. Разом з випуском .NET Standard Microsoft випустили велику кількість обв'язок, які повинні упорядкувати деякий зоопарк використовуваних технологій.

У першій статті (IoC-контейнер) ми поговорили про те, чому це круто мати реалізацію DI-контейнера за замовчуванням, і чому в більшості випадків варто використовувати саме його. Також написали просту реалізацію біндингу за атрибутами.

У другій (Конфігурація) я розповів про недоліки старого способу конфігурування програми (через app.config/web.config) та про те, як вони виправлені у новому підході.

У цій - третьій - подивимося на стандартний інтерфейс логування і прикрутимо до нього звичний NLog.

  1. Контейнер IoC.
  2. Конфігурація
  3. Логування.

Логування

Навіщо взагалі новий інструмент для логування?

Ми вже маємо NLog, log4net, Serilog. Все це чудові інструменти, але дуже сумно, коли у великому рішенні зустрічаються всі вони. Тоді доводиться або перекладати все наодинці, або впилювати якусь абстракцію. Ще не дуже добре використовувати конкретне рішення без прошарку в бібліотеці, що поширюється, тому що це знову приведе кінцевих споживачів до необхідності використовувати ваш інструмент (а вони вже можуть використовувати інший).

Ми вже маємо Common.Logging, якщо ми хочемо відвернутися від конкретного інструменту (наприклад, у бібліотеках). Common.Logging - це, звичайно, добре, але не факт, що кінцеві споживачі вашої бібліотеки захочуть використовувати його. Ще великий мінус, що ви не будете використовувати Common.Logging за умовчанням скрізь, набагато частіше простовізьмете NLog і забудете про проблему, доки вона не спливе.

Microsoft.Extensions.Logging відмінно вирішує ці проблеми. Це такий Common.Logging, який використовується за замовчуванням у Core додатках, що призводить до того, що миточно будемо використовувати цей спосіб. Тепер не абстракція підлаштовується під інструменти (як Common.Logging), а інструмент під абстракцію.

Подивимося, як це працює. Створимо консольну програму .NET Core і встановимо пакети:

І напишемо наступний код, щоб розібратися, що відбувається.

Тут ми використовуємо найпростіший спосіб ініціалізації та використання логування. Спочатку створюється фабрика логів LoggerFactory. Потім додаються провайдери через методи-розширення AddConsole (виведення на консоль) і AddDebug (виведення в консоль налагодження). Параметри задають предикат запису логів у провайдер. У разі AddConsole ми передали лямбду, яка приймає рядок повідомлення та рівень протоколювання, а повертає bool. У AddDebug передали мінімально можливий рівень. У виведенні консолі налагодження побачимо:

У консоль виведеться:

Все правильно, для консолі пишемо все, для налагодження - тільки Debug і вище

AddConsole і AddDebug - це просто обгортки над void AddProvider(ILoggerProvider provider), який додає провайдер до цієї фабрики логерів. Відповідно, ми можемо додати консольний логер наступним чином:

Ну і звичайно, ми можемо написати свій провайдер, якщо раптом виникне така необхідність.

Ще варто згадати таку річ, як Scopes. Вони дозволяють краще прив'язати логування до бізнес-завдань. Як приклад, напишемо таку програму:

Виведення на консоль буде таким:

використовувати

Видно, що скоупи впливають висновок, причому впливають попри всі логери.

ТеперСпробуємо прикрутити NLog в ASP.NET Core-додаток. Спочатку створимо проект за шаблоном «Web-додаток ASP.NET Core», «Порожній».

На момент написання статті NLog для .NET Core знаходиться в беті, тому ставимо наступною командою:

Після цього поставимо пакет NLog.Web.AspNetCore, який містить рендерери для веб-додатків.

Створимо в корені проекту файл NLog.config і виставимо йому правило копіювання у вихідний каталог Завжди копіювати. Вміст файлу:

У layout ми використовували кілька ASP.NET-специфічних рендерерів - наприклад, $ для відображення URL запиту.

Тепер змінимо наш Startup.cs, додавши туди підтримку NLog.

До методу ConfigureServices додамо:

Це дозволить нам інжектити IHttpContextAccessor у singleton-сервіси та мати доступ до поточного HttpContext.

А до методу Configure додамо наступне:

Метод AddNLogWeb зберігає в статичну змінну DI-контейнер (ServiceProvider), з якого NLog діставатиме необхідні речі (наприклад, той же IHttpContextAccessor).

loggerFactory.AddNlog — додає провайдер Nlog-а

Після запуску програми та виконання будь-якого запиту ми побачимо у нашому файлі рядки типу такого:

Тут ми бачимо все, що потрібне для розуміння, який це був запит.

Самі логери органічно вбудовані в інфраструктуру ASP.NET Core - ви можете інжектити ILogger в будь-який сервіс, і він розрізняється. Якщо ви хочете працювати як у класичних додатках і створювати логер руками, то просто збережіть екземпляр ILoggerFactory в статичне поле і смикайте CreateLogger, коли вам заманеться. Бажано не створювати статичних логерів, а мати індивідуальний екземпляр логгера на екземпляр класу.

Таким чином, інфраструктуралогування зазнала деяких змін, і тепер вам доведеться використати саме її. Протоколування піднято на новий рівень абстракції і ви можете вибрати, який спосіб логування використовувати. Усі системні інструменти/фреймворки (такі як ASP.NET Core) використовують саме такий підхід. Все це органічно вбудоване у загальну екосистему і вимагає від розробника якихось особливих знань.