Я знаю, что можно использовать MinimalLevel.Override, который затем определяет конкретный уровень ведения журнала для каждого пространства имен или типа, но что, если я хочу зарегистрировать его с помощью чего-то более специфичного для моего контекста или требований?
Например, в моем приложении я хочу иметь определенную группу журналирования для всего, что связано с сущностью «Пользователи». Однако это не привязано к конкретному пространству имен или классу, это может быть код в контроллерах, репозитории или любой пользовательской службе. При отладке чего-либо, связанного с пользователями, я хотел бы включить для этого подробное ведение журнала, но не увеличивать его для каких-либо других журналов, служб или контроллеров, даже если они используют пространство имен совместно с пользователями. Опять же, «Пользователи» — это всего лишь пример — он может быть связан с определенным типом SQL-запросов, которые я делаю, всякий раз, когда используется какой-либо сервис, только когда выполняется определенное условие глубоко внутри некоторого кода и т. д. — возможно, я хочу, чтобы все SQL-запросы должны регистрироваться только в состоянии «Ошибка», за исключением некоторых, которые должны быть подробными.
Сначала я попробовал сделать это с помощью переключателей
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.MinimumLevel.Override("Case1", SerilogSwitches.Case1)
.MinimumLevel.Override("Case2", SerilogSwitches.Case2)
.CreateLogger();
Проблема в том, что «Case1» и «Case2» должны соответствовать определенному пространству имен или типу, который мне не подходит.
Я также рассмотрел возможность создания конкретного контекста журнала для каждого из этих случаев, используя Log.ForContext.
var logger1 = Log.ForContext("Context", "Case1");
var logger2 = Log.ForContext("Context", "Case2");
Хотя это позволило бы мне выбрать, какой регистратор использовать в любой момент, а затем легче находить и фильтровать журналы для этого конкретного контекста, все они по-прежнему регистрируются на одном и том же уровне — я не думаю, что смогу изменить уровень журналирования для конкретный контекст, например, Case1 — «Информация», а Case2 — «Ошибка».
Любая помощь приветствуется





Вы можете попробовать использовать WriteTo.Conditional, чтобы определить конфигурацию в зависимости от значения «Контекст». Например, следующий образец:
Log.Logger = new LoggerConfiguration()
.WriteTo.Conditional((evt) => {
var contextValue = ((ScalarValue)evt.Properties.GetValueOrDefault("Context")).Value;
return ( contextValue== "case1");
} , wt => wt.Console(restrictedToMinimumLevel:LogEventLevel.Information,outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}]({Context}) {Message:lj}{NewLine}{Exception}"))
.WriteTo.Conditional((evt) => {
var contextValue = ((ScalarValue)evt.Properties.GetValueOrDefault("Context")).Value;
return (contextValue == "case2");
}, wt => wt.Console(restrictedToMinimumLevel: LogEventLevel.Error, outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}]({Context}) {Message:lj}{NewLine}{Exception}"))
.CreateLogger();
Тест
Log.ForContext("Context","case1").Information("case1 info");
Log.ForContext("Context", "case2").Information("case2 info");
Log.ForContext("Context", "case2").Error("case2 error");
Результат
В вашем примере:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.MinimumLevel.Override("Case1", SerilogSwitches.Case1)
// ...
Использование SourceContext приведет к сопоставлению переопределения уровня и применению определенных уровней:
var logger1 = Log.ForContext("SourceContext", "Case1");
(Для этого существует константа, называемая Serilog.Core.Constants.SourceContextPropertyName.)
Вы потеряете имя типа, которое в противном случае обычно появлялось бы в этом значении, но это может быть приемлемым компромиссом, если этого требует ваш сценарий - и вы все равно можете записать имя типа дополнительно, используя что-то вроде:
var logger1 = Log
.ForContext("SourceContext", "Case1")
.ForContext("SourceType", typeof(MyClass));