WCF サービスに Log4Net を導入


WCF のサービスを IIS でホストしてると Console.WriteLine がどこにも出てこないので不便。
そこで log4net を導入して、ログまわりは心配しないようにします。

環境：

* VisualStudio 2015
* .Net Framework 4.5.2
* WCF プロジェクト

log4net の機能を色々使うのであれば、設定ファイルが大きくなりがちなので別の .config に分けるのもありだと思いますが、Release/Debug の構成毎に .config 分けれるので Web.config に設定を組込みます。


# インストール

NuGet でインストールします。
このあたりパッケージ管理で簡単。


# 設定

AssemblyInfo.cs、Web.config に次の内容を追加


``` AssemblyInfo.cs
	[assembly: log4net.Config.XmlConfigurator(Watch=true)]
```


``` Web.config
	<?xml version="1.0" encoding="utf-8"?>
	<configuration>
		<configSections>
			<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
		</configSections>
		
		<log4net>
			<root>
				<!-- ERROR以上のログを記録 -->
				<level value="ERROR" />
				<!-- 使用する Appender -->
				<appender-ref ref="InfoLogDailyAppender" />
				<appender-ref ref="ErrorLogDailyAppender" />
				<appender-ref ref="DebugLogDailyAppender" />
			</root>
	
			<!-- Infoログ：分割ファイル出力 -->
			<appender name="InfoLogDailyAppender" type="log4net.Appender.RollingFileAppender">
				<param name="File" value="${SystemDrive}\\inetpub\\logs\\LogFiles\\WCFService\\Info_" />
				<param name="DatePattern" value='yyyyMMdd".log"' />
				<param name="RollingStyle" value="date" />
				<param name="StaticLogFileName" value="false" />
	
				<AppendToFile value="true" />
	
				<filter type="log4net.Filter.LevelRangeFilter">
					<param name="LevelMax" value="WARN" />
					<param name="LevelMin" value="INFO" />
				</filter>
	
				<layout type="log4net.Layout.PatternLayout">
					<ConversionPattern value="%date [%thread] [%-5level] %logger - %message%n" />
				</layout>
			</appender>
	
			<!-- エラーログ：分割ファイル出力 -->
			<appender name="ErrorLogDailyAppender" type="log4net.Appender.RollingFileAppender">
				<!-- ファイル名は日付ごと -->
				<param name="File" value="${SystemDrive}\\inetpub\\logs\\LogFiles\\WCFService\\Error_" />
				<param name="DatePattern" value='yyyyMMdd".log"' />
				<param name="RollingStyle" value="date" />
				<param name="StaticLogFileName" value="false" />
	
				<param name="AppendToFile" value="true" />
	
				<filter type="log4net.Filter.LevelRangeFilter">
					<param name="LevelMax" value="FATAL" />
					<param name="LevelMin" value="ERROR" />
				</filter>
	
				<param name="MaximumFileSize" value="10MB" />
				<param name="MaxSizeRollBackups" value="10" />
	
				<layout type="log4net.Layout.PatternLayout">
					<ConversionPattern value="%date [%thread] [%-5level] %logger %file(%line) %class %method - %message%n" />
				</layout>
			</appender>
	
			<!-- デバッグ用：分割ファイル出力 -->
			<appender name="DebugLogDailyAppender" type="log4net.Appender.RollingFileAppender">
	
				<!-- ファイル名は日付ごと -->
				<param name="File" value="${SystemDrive}\\inetpub\\logs\\LogFiles\\WCFService\\Trace_" />
				<param name="DatePattern" value='yyyyMMdd".log"' />
				<param name="RollingStyle" value="date" />
				<param name="StaticLogFileName" value="false" />
	
				<param name="AppendToFile" value="true" />
	
				<filter type="log4net.Filter.LevelRangeFilter">
					<!-- <param name="LevelMax" value="FATAL" /> -->
					<param name="LevelMin" value="TRACE" />
				</filter>
	
				<param name="MaximumFileSize" value="10MB" />
				<param name="MaxSizeRollBackups" value="10" />
	
				<layout type="log4net.Layout.PatternLayout">
					<ConversionPattern value="%date [%thread] [%-5level] %logger %file(%line) %class %method - %message%n" />
				</layout>
			</appender>
		</log4net>
	</configuration>
```


[メモ]
> 最初の `<section name="log4net2 ...>` と、`<log4net>` を xml タグの階層に合う部分に追加してください。
たとえば
>
>			<section name="log4net2 ...>
>
>は、Web.config の `<configuration>` の中の `<configSection> ` の中です。他に追加されている `<section>` があれば、それと並べて書きます。自分のプロジェクトでは `<section name="entityFramework" ...>` というのがあって
>
>		<configuration>
>			<configSections>
>				<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
>				<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
>				<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
>			</configSections>
>			...
>
>という感じになってます。
>`<log4net>` は `</configuration>` の直前に追加すれば良いとおもいます。
>


# 構成毎のログレベルの変更

上の例では、デフォルトで運用環境の設定を Web.config に設定し、Debug の時だけログレベルを下げて詳細にログを出力させようとしています。
Debug の時のログレベルは Web.Debug.config ファイルにログレベルの部分だけを記入して Web.config の設定を上書き認識させます。


``` web.Debug.config
	<configuration>
		...
		
		<log4net>
			<root>
				<level value="TRACE" />
			</root>
		</log4net>
	</configuration>
```


# 使用

	using log4net;
	
	class WCFServiceClass {
		private static ILog Logger = LogManager.GetLogger(@"WCFService"));
	
		public WCFServiceClass() {
			// log4net 初期化
			log4net.Config.XmlConfigurator.Configure();
		}
		
		public void HogeFunction() {
			Logger.Error(@"エラー");
		}
	}

って、サンプルなんかには書いてますね。


# おまけ

Ruby とかで

	Log.Logger.Error(@"エラーだよ");

って感じの書き方に慣れきっているので

``` Log.cs
	namespace WCFService
	{
			public static class Log
			{
					private static ILog _logger = null;
	
					public static ILog Logger
					{
							get
							{
									if(_logger == null )
									{
											log4net.Config.XmlConfigurator.Configure();
											_logger = LogManager.GetLogger(@"WCFService");
									}
									return _logger;
							}
					}
			}
	}
```

Log クラスのプロパティにしてます。この使いかたで問題ないのか？