標準I/O機能ではなく、この種のものにはlog4netを使用します。私は、ConsoleAppenderとFileAppenderまたはRollingFileAppenderを使用して、log4netをコンソールとログファイルの両方に同時にログオンするように設定します。
素晴らしいことは、ログメッセージテンプレートだけでなく、ログメッセージだけでなく、あらゆる種類の有用な情報(時刻、スレッド/プロセスID、マシン名など)をトラップできることです。
SQL Server、イベントログ、またはリモートシンクにもログオンできます。
Easy!
using System;
using System.IO;
using System.Text;
using log4net ;
namespace ConsoleApplication22
{
public class Log4NetTextWriter : TextWriter, IDisposable
{
private static ILog log = log4net.LogManager.GetLogger(typeof(Log4NetTextWriter)) ;
#region properties
private StringBuilder buffer { get ; set ; }
public override Encoding Encoding
{
get
{
// since this TextWrite is writing to log4net, we have no idea what the final encoding might be.
// It all depends on the log4net configuration: tthe appender or appenders that wind up handling the logged message
// determine the final encoding.
//
// Might make more sense to return Encoding.UTF8 though, just to return something.
throw new NotImplementedException() ;
}
}
#endregion properties ;
public override void Flush()
{
if (this.buffer != null && this.buffer.Length > 0)
{
this.WriteLine() ;
}
return ;
}
public override void Close()
{
base.Close();
}
protected override void Dispose(bool disposing)
{
this.Flush() ;
base.Dispose(disposing);
}
#region public constructors
public Log4NetTextWriter() : this(null)
{
return ;
}
public Log4NetTextWriter(IFormatProvider formatProvider) : base(formatProvider)
{
this.buffer = new StringBuilder() ;
}
#endregion public constructors
#region public Write() overloads
public override void Write(bool value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(char value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(char[] buffer)
{
this.buffer.Append(buffer) ;
return ;
}
public override void Write(char[] buffer , int index , int count)
{
this.buffer.Append(buffer , index , count) ;
return ;
}
public override void Write(decimal value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(double value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(float value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(int value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(long value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(object value)
{
this.buffer.Append(value) ;
return ;
}
public override void Write(string format , object arg0)
{
this.buffer.AppendFormat(this.FormatProvider , format , arg0) ;
return ;
}
public override void Write(string format , object arg0 , object arg1)
{
this.buffer.AppendFormat(this.FormatProvider , format , arg0 , arg1) ;
return ;
}
public override void Write(string format , object arg0 , object arg1 , object arg2)
{
this.buffer.AppendFormat(this.FormatProvider , format , arg0 , arg1 , arg2);
return ;
}
public override void Write(string format , params object[] arg)
{
this.buffer.AppendFormat(this.FormatProvider , format , arg) ;
return ;
}
public override void Write(string value)
{
this.buffer.Append(value);
return ;
}
public override void Write(uint value)
{
this.buffer.Append(value);
return ;
}
public override void Write(ulong value)
{
this.buffer.Append(value);
return ;
}
public override void WriteLine()
{
string logMessage = this.buffer.ToString() ;
this.buffer.Length = 0 ;
log.Info(logMessage) ;
return ;
}
#endregion public Write() overloads
#region public WriteLine() overloads
public override void WriteLine(bool value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(char value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(char[] buffer)
{
this.Write(buffer) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(char[] buffer , int index , int count)
{
this.Write(buffer , index , count) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(decimal value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(double value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(float value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(int value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(long value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(object value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(string format , object arg0)
{
this.Write(format , arg0) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(string format , object arg0 , object arg1)
{
this.Write(format , arg0 , arg1) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(string format , object arg0 , object arg1 , object arg2)
{
this.Write(format , arg0 , arg1 , arg2) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(string format , params object[] arg)
{
this.Write(format , arg) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(string value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(uint value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
public override void WriteLine(ulong value)
{
this.Write(value) ;
this.WriteLine() ;
return ;
}
#endregion public WriteLine() overloads
}
}
ここではサンプルlog4netの設定ファイルです:
はここにlog4net経由のルートのすべてがそのサンプルしたTextWriterの実装です。これは、コンソールにもログファイルにも記録され、サイズに基づいた自動ロールオーバー(日付/時間または実行ごとにロールすることもできます)。あなたのプログラムが実行されている間、あなたがオンまたはオフにロギングを有効にすることができます
// Configure log4net using the .log4net file
[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
// This will cause log4net to look for a configuration file
// called TestApp.exe.log4net in the application base
// directory (i.e. the directory containing TestApp.exe)
// The config file will be watched for changes.
、または変更:
<log4net>
<!-- Log to the console -->
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<!-- Pattern to output the caller's file name and line number -->
<conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
</layout>
</appender>
<!-- Log to a log file. This particular setup should log to a static file name 'log.txt' -->
<!-- When it hits 100KB in size, it rolls, keeping up to 10 archived files. The archived -->
<!-- files are named 'log.text.1', 'log.txt.2', ... , 'log.txt.10' -->
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
log4netのを設定するには、最も簡単な方法は、このように、AssemblyInfo.csにXmlConfigurator属性を置くことです設定ファイルを編集して保存するだけです。 log4netは設定ファイルの変更を監視し、その場で自動的に再設定します。
このメソッドでは、私はDistributingTextWriterがConsole TextWriterとStreamWriterへの参照を保持していると仮定しています。これらの呼び出しをすべてのTextWriterに '配布'するために、それぞれのWriteメソッドとWriteLineメソッドを上書きする必要がありますか? – Nitax
私は心配です:TextWriterクラスのインターフェイスとの互換性を維持するには、これらのメソッドをすべて再実装する必要があります。ただし、ほとんどのコードをSystem.IO.StreamWriterの実装からコピーできます。 "SSCLI"と "Rotor"のGoogle検索で検索できます。 –