Ведение журналов корпоративной среды - AlwaysLog не работает с фильтром SourceLevel - PullRequest
2 голосов
/ 09 января 2012

Я использую EF 5 и пытаюсь использовать метод ShouldLog, чтобы определить, будет ли LogEntry записываться в журнал до его фактической регистрации. Моя проблема в том, что ShouldLog всегда возвращает true, даже если у меня есть фильтр для исключения определенных уровней. Фильтр работает, и записи не регистрируются, но, как представляется, ShouldLog не работает.

Я настраиваю свой логгер так:

internal static void ConfigureLogging(SourceLevels logLevel)
{
    var builder = new ConfigurationSourceBuilder();

    builder.ConfigureLogging()
        .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");

    var configSource = new DictionaryConfigurationSource();
    builder.UpdateConfigurationWithReplace(configSource);
    EnterpriseLibraryContainer.Current
        = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
}

И тестирование так:

ConfigureLogging(SourceLevels.Warning); //Do not allow Information level

var logEntry = new LogEntry { Message = "test", Severity = TraceEventType.Information };
var shouldLog = Logger.Writer.ShouldLog(logEntry);
Logger.Writer.Write(logEntry);

После запуска этого кода переменная shouldLog имеет значение true, но запись в журнале не записывается. Если я вместо этого передам SourceLevels.Information в метод ConfigureLogging, я получу запись, записанную в мой журнал. Я что-то не так делаю?

1 Ответ

1 голос
/ 10 января 2012

Я не думаю, что вы делаете что-то не так.Тем не менее, я признаю, что поведение немного странное.

Как уже упоминалось здесь метод 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...