Устранение дублирования журнала в log4net

У меня есть программа, которая вызывает много вызовов log4net для регистраторов "myprogram". Он также вызывает другой код, который вызывает вызовы log4net другим регистраторам. Я хочу захватить все журналы выше INFO для "myprogram" и всех журналов выше WARN для всего остального. Таким образом, я получаю сообщения о незавершенном процессе, специфичные для задачи, над которой я работаю, но я все еще уведомлен о потенциально опасных вещах, происходящих в поддерживающем коде. Я хочу, чтобы это послано как на консоль, так и на файл журнала.

У меня есть следующая конфигурация log4net:

<log4net>
    <root>
        <level value="WARN" />
        <appender-ref ref="Console" />
        <appender-ref ref="LogFile" />
    </root>
    <logger name="myprogram">
        <level value="INFO" />
        <appender-ref ref="Console" />
        <appender-ref ref="LogFile" />
    </logger>
    <appender name="Console" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message%newline" />
        </layout>
        <threshold value="INFO" />
    </appender>
    <appender name="LogFile" type="log4net.Appender.RollingFileAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="- %utcdate %level %logger %ndc %thread %message%newline" />
        </layout>
        <appendToFile value="false" />
        <staticLogFileName value="true" />
        <rollingStyle value="Once" />
        <file value="mylogfile" />
        <immediateFlush value="true" />
        <threshold value="INFO" />
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    </appender>
</log4net>

Это имеет для меня смысл: log > WARN для всего и > INFO для конкретного регистратора "myprogram".

Проблема заключается в том, что я получаю сообщения INFO в журнале дважды на консоли и в LogFile. Это происходит только в том случае, если у меня есть те элементы <root> и <logger>; если я удалю один, то оставшийся работает, как я ожидаю.

Я мог бы понять, получаю ли я двойную запись WARN-записей (поскольку myprogram соответствует как "root", так и "myprogram" ), но это происходит в INFO, хотя ROOT (предположительно) установлен в WARN.

Я делаю что-то неправильно здесь, или это ошибка/двусмысленность log4net?

Ответ 1

Вы получаете дублирование, потому что вы сообщаете ему дважды записывать сообщения. Я бы не рекомендовал использовать аддитивность здесь, так как вы можете столкнуться с некоторыми побочными эффектами, просто удалите ненужную конфигурацию:

<root>
    <level value="WARN" />
    <appender-ref ref="Console" />
    <appender-ref ref="LogFile" />
</root>
<logger name="myprogram">
    <level value="INFO" />
</logger>

Вам не нужно указывать appender-ref в myprogram logger, так как он наследует их от корневого регистратора; если вы укажете их снова, он будет записывать дважды.

Ответ 2

Попробуйте с этим изменением, установив аддитивность на false.

<root>
    <level value="WARN" />
    <appender-ref ref="Console" />
    <appender-ref ref="LogFile" />
</root>
<logger name="myprogram" additivity="false">
    <level value="INFO" />
    <appender-ref ref="Console" />
    <appender-ref ref="LogFile" />
</logger>