Я не думаю, что вы делаете что-то не так.Тем не менее, я признаю, что поведение немного странное.
Как уже упоминалось здесь метод ShouldLog
запрашивает все настроенные фильтры по LogEntry
.Причина, по которой ShouldLog
возвращает true, состоит в том, что вы не определили никаких фильтров, поэтому все проходит.
«Но подождите!», Говорите вы.«Я установил фильтр уровня источника в свободной конфигурации!»
Это правда - в некотором смысле.Но, несмотря на название, метод Filter
не создает фактического фильтра (хотя, возможно, так и должно быть)!Он просто устанавливает значение SourceLevels
, которое проверяется только при вызове Write
.Если вместо текущей конфигурации вы используете файл конфигурации, то в файле конфигурации Filter
фактически называется switchValue
, так что это не так запутанно.
Так что ShouldLog
возвращает true, потому что нет фильтров, ноWrite
на самом деле не пишет из-за проверки по SourceLevels
.Это довольно нелогично.Было бы неплохо, если бы в версии 6 проверка была включена в ShouldLog
?Он игнорирует цель ShouldLog
, если возвращает true, что заставляет пользователя создавать кучу дорогих объектов, но в конце сообщение никогда не регистрируется из-за проверки SourceLevels
.
Я проверил, и похоже, что это поведение было примерно с версии 4.
Что делать с этим поведением?Самый простой способ - добавить пользовательский фильтр для выполнения проверки SourceLevels
:
public class SourceLevelFilter : LogFilter
{
private SourceLevels level;
public SourceLevelFilter(NameValueCollection nvc)
: base("SourceLevelFilter")
{
if (!Enum.TryParse<SourceLevels>(nvc["Level"], out level))
{
throw new ArgumentOutOfRangeException(
"Value " + nvc["Level"] + " is not a valid SourceLevels value");
}
}
public override bool Filter(LogEntry log)
{
if (log == null) throw new ArgumentNullException("log");
return ShouldLog(log.Severity);
}
public bool ShouldLog(TraceEventType eventType)
{
return ((((TraceEventType)level) & eventType) != (TraceEventType)0);
}
public SourceLevels SourceLevels
{
get { return level; }
}
}
// ...
SourceLevels logLevel = SourceLevels.Warning;
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.FilterCustom<SourceLevelFilter>("SourceLevelFilter",
new NameValueCollection() { { "Level", logLevel.ToString() } } )
.LogToCategoryNamed("General")
.WithOptions.SetAsDefaultCategory()
.SendTo.FlatFile("Main log file")
.FormatWith(
new FormatterBuilder()
.TextFormatterNamed("Text Formatter")
.UsingTemplate("{timestamp(local:MM/dd/yyyy HH:mm:ss.fff)} [{severity}] {message}"))
.Filter(logLevel) //Setting the source level filter
.ToFile("log.txt");
Теперь ShouldLog
будет включать значение SourceLevels
в свою проверку и вернет false для LogEntry
суровень важности информации, когда для SourceLevels установлено значение Warning.
UPDATE
Одна проблема, с которой вы можете столкнуться с фильтрами, заключается в том, что они являются глобальными, поэтому вам, вероятно, придется подменитьвверх по фильтру выше, чтобы сохранить SourceLevels вместе с Категорией.
Если вы просто хотите проверить, было ли включено предупреждение, вы можете проверить определенный фильтр:
public bool IsWarningEnabled
{
get
{
return writer.GetFilter<SourceLevelFilter>().ShouldLog(TraceEventType.Warning);
}
}
Другой подход заключается вУправляйте SourceLevels самостоятельно без фильтра.Так как вы пишете оболочку журнала общего назначения, я предполагаю, что SourceLevels будет установлен через вашу оболочку.Вы также говорите о разоблачении ваших собственных методов, таких как IsDebugEnabled.Если это так, то вы можете сохранить эти знания внутри вашей оболочки и предоставить эту проверку по требованию.Если вы возвращаете EntLib LogWriters вызывающим абонентам, это может сработать, поскольку пользователь захочет вызвать ShouldLog на LogWriter.Хотя вы также можете создавать методы расширения (такие как IsWarningEnabled ()) в LogWriter.