環境
.NET Framerowk 4.6.1
log4net 2.0.8
実行環境: Windows 10 Pro / Windows Server 2012
状況
コマンドラインアプリケーションにおいて、log4net
を利用しているのですが、Debug Build 時にはログが出力されるにも関わらず、Release Build 時にはログが出力されませんでした。
設定の状態
App.config に設定を記述する特になんの変哲もない設定です。
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="ConsoleAppendar" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %5level %message%newline" />
</layout>
</appender>
<appender name="FileAppendar" type="log4net.Appender.RollingFileAppender">
<file value="logs\ConsoleApp\ConsoleApp" />
<appendToFile value="true" />
<maximumFileSize value="10000KB" />
<maxSizeRollBackups value="2" />
<param name="DatePattern" value='"."yyyy-MM-dd".log"' />
<param name="RollingStyle" value="date " />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<applicationName value="ConsoleApp"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %message%newline"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="WARN"/>
<param name="LevelMax" value="FATAL"/>
</filter>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="ConsoleAppendar" />
<appender-ref ref="FileAppendar" />
<appender-ref ref="EventLogAppender" />
</root>
</log4net>
</configuration>
なぜ Release Build 時にだけログが出ないのかさっぱりわかりませんでした
原因と対処
公式の設定ファイルの書き方のところに普通に書いてありました
Using attributes can be a clearer method for defining where the application's configuration will be loaded from. However it is worth noting that attributes are purely passive. They are information only. Therefore if you use configuration attributes you must invoke log4net to allow it to read the attributes. A simple call to LogManager.GetLogger will cause the attributes on the calling assembly to be read and processed. Therefore it is imperative to make a logging call as early as possible during the application start-up, and certainly before any external assemblies have been loaded and invoked.
どうやら、assembly の attribute として記述する場合は、アプリのスタートからできるだけ早く log4net の呼び出しを行わなければいけないようです。
実際、私の書いていたコンソールアプリは、起動からそこそこの初期化処理( DB への I/O もある)の後に Logger
を初めて呼び出すようになっていました。
エントリーポイントになるクラスで LogManager.GetLogger
相当を呼び出すことで Release Build でもログが問題なく出力されるようになりました。
どうして Debug Build では問題なかったのか
自分の知識だときちんと説明ができないのですが、Debug Build 時には依存アセンブリが事前にある程度ロードされるのではないかと思います。
Appendix
調査していて参考になったリンク
- Log4net configuration from assembly attribute does not load configuration file - Stack Overflow
- c# - Log4Net not working, but only for release console builds - Stack Overflow
- security - C# WebApp log4net partial trust (High or Medium) not working - Stack Overflow
- [LOG4NET-274] log4net doesn't log when running a .Net 4.0 Windows application built in Release mode - ASF JIRA
- log4net自身のデバッグログを出力する方法 | netplanetes log
- [log4net] log4netの設定 | HIRO's.NET Blog
- C#によるlog4netの実装 | TomoSoft
- 【C#】log4netの使い方 - TechBox