2011年6月17日

Windows AzureでLog4Net RollingFileAppenderを使う

Windows Azure上で、Log4NetのRollingFileAppenderによりBlobストレージ上にログファイルを書きだすようにしてみたので、その方法についてまとめです。

やり方自体は単純で、RollingFileAppenderのログファイルの出力先を Windows Azureの Local Storageに設定し(これが意外と面倒)、出力先のLocal Storageの内容をDiagnostics Monitorで転送させてるだけです。またlog4netの設定ファイルlog4net.configはBlobストレージ上に置かれたものを使うようにしました。

プロジェクト構成

まずは、Visual Studioで新規プロジェクト→Windows Azure Projectを作り、そのRoleのプロパティからログファイルの出力用Local Storageを用意しておきます。

ここでは、LOG_FILESという名前で用意しました。

image

XmlConfiguratorによるlog4net.configの読み込み

次に以下のソースコードのように、log4net.Config.XmlConfiguratorを使ってBlobストレージ上に置かれたlog4net.configを読み込みます。

			var logConfig = ConfigurationManager.AppSettings["logConfig"];   //log4net.configが設置されたURL
			var logStorage = ConfigurationManager.AppSettings["logStorage"]; //ログ出力用のLocal Storage名

			var bytes = new WebClient().DownloadData(logConfig);

			using ( var ms = new MemoryStream(bytes) ) {
				if ( logStorage != null && RoleEnvironment.IsAvailable ) {
					//ローカルストレージへのパスを環境変数に設定し、log4net.configの中で使えるようにする
					var rootPath = RoleEnvironment.GetLocalResource(logStorage).RootPath;
					Environment.SetEnvironmentVariable(logStorage, rootPath);
				}

				XmlConfigurator.Configure(ms);
			}

1,2行目でweb.configからlogConfigとlogStorageという二つの設定を読み込んでます。logConfigの値がlog4net.configが設置されたURLを示し、logStorageの値がログ出力用のLocal Storage名を示してます。

で、4行目でlogConfigとして指定されたURLからlog4net.configファイルの中身をダウンロードしてます。設置場所にBlobストレージを利用していますが、Public Blobという前提でWebClientを使ってます。(Privateにしている場合はStorage Client SDKなどを用いてBlobの中身を読み込みます)

そして次がキーポイントですが、9,10行目においてlog4net.configでLocal Storageへのパスを使うために、環境変数名をlogStorage、値をlogStorageのパスとした環境変数をセットしてます。こうすることで、log4netが標準で持つ環境変数の参照機能を用いてLocal Storageへのパスを解決できます。

最後13行目は、ダウンロードしたlog4net.configからXmlConfiguratorによってコンフィグを読み込むだけ。

web.configのサンプル

web.configでは、以下のように<appSettings>の要素として、logConfig, logStorageの値を設定してます。

logConfigの値は実際にlog4net.configが置いてあるURLで、logStorageの値はRoleに用意したLocal Storageの名前です。

<configuration>
	<appSettings>
		<add key="logConfig" value="http://***.blob.core.windows.net/configs/log4net.config" />
		<add key="logStorage" value="LOG_FILES" />
	</appSettings>

	<system.diagnostics>
		<trace>
			<listeners>
				<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, 
					Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, 
					PublicKeyToken=31bf3856ad364e35"
				  name="AzureDiagnostics">
					<filter type="" />
				</add>
			</listeners>
		</trace>
	</system.diagnostics>

	<system.web>
		<compilation debug="true" targetFramework="4.0" />
	</system.web>

	<system.webServer>
		<modules runAllManagedModulesForAllRequests="true"/>
	</system.webServer>

</configuration>

log4net.configのサンプル

log4net.configでは、上に書いたように環境変数としてローカルストレージへのパスが用意されているため、5行目のようにそれを参照してログファイルの出力パスを設定します。(web.configでlogStorageとしてLOG_FILESを指定したため、LOG_FILESという環境変数名でローカルストレージへのパスが格納されてます)

<?xml version="1.0" ?>
<log4net debug="true" threshold="ALL">

  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="${LOG_FILES}\logfile" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="'_'yyyyMMdd'-'HHmm'.log'" />
    <staticLogFileName value="false" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - 
			%message%newline" />
    </layout>
</appender>

  <root>
    <level value="DEBUG" />
    <appender-ref ref="RollingFileAppender" />
  </root>
  
</log4net>

あとは、Diagnostics MonitorでLOG_FILESローカルストレージの内容をBlobに転送するように設定すればOKです。

まとめ

このようにすることで、Windows Azure上でRolling File Appenderを使い、Blobストレージ上にログファイルを出力することができます。

問題はDiagnostics Monitorによるファイル転送が差分転送ではなく、変更のあったファイルを全て転送することですが、データセンター内のファイル転送であることと、Rolling File AppenderではファイルがRollする単位で書込み先のファイルが変わり、古いログファイルは変更されなくなるため、大きな問題にはならないと思います。(ファイルサイズでRollするようにすれば、無駄な転送量を減らすこともできます)

あとは、Diagnostics Monitorの転送スケジュールが大きいと、ログファイルがBlobに転送されるまでに時間がかかることですが、これはOn-Demand Transferを使って解決できるでしょう。

0 件のコメント:

コメントを投稿