タイトルが示すように、C#で毎日新しいログファイルを作成するにはどうすればよいですか?現在、プログラムは必ずしも昼夜を問わず実行されるとは限らず、営業時間中にのみ呼び出されます。だから私は2つのことをする必要があります。
2018年の更新:今はNLogを使用したい
Log4netに関する以前の回答:
この例 は、ある期間にログファイルをロールするようにRollingFileAppenderを構成する方法を示しています。この例では、ログファイルが毎分ロールされます。ローリング期間を変更するには、DatePattern値を調整します。たとえば、「yyyyMMdd」の日付パターンは毎日ロールされます。
使用可能なパターンのリストについては、 System.Globalization.DateTimeFormatInfo を参照してください。
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\temp\rolling.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd-HHmm" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
私はこのようなものをお勧めします:
string logFile = DateTime.Now.ToString("yyyyMMdd") + ".txt";
if (!System.IO.File.Exists(logFile))
{
System.IO.File.Create(logFile);
}
//append to logFile here...
真夜中過ぎに何かを作成したい理由はありますか?エラーをログに記録するときに存在しない場合は、作成しないのはなぜですか?
また、日付形式を変更したことにも気づきました。これにより、ファイルを名前で並べ替えて順番に取得できます。何らかの方法で日付をいじるときは、常にこの形式を使用します。
他の人がLog4Netについて言及しているので、先に進んで Enterprise Library Logging Blockをポン引きします。これは、あなたが望むことを実行することもできます。
このロールを毎日簡単に作成できることを示すコードをいくつか含めていただけますか? log4Netの例よりも簡単ですか?– Daniel Dyson
承知しました。通常、構成を構築するには Enterprise Library Configuration Tool を使用します。このツールには少し慣れが必要ですが、その仕組みを理解すれば、かなり強力になります。とはいえ、app.config
を手動で編集することもできます。
これが私が言及したツールの出力です。これは、毎日(または2MBを超える場合)ローリングするローリングフラットファイルにほとんどすべてをダンプします。書式設定は、ツールによって提供されるデフォルトです。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="Category">
<listeners>
<add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
formatter="Text Formatter" rollInterval="Day" rollSizeKB="2000" />
</listeners>
<formatters>
<add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
template="Timestamp: {timestamp}{newline}
Message: {message}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Thread Name: {threadName}{newline}
Win32 ThreadId:{win32ThreadId}{newline}
Extended Properties: {dictionary({key} - {value}{newline})}"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All" name="Category">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All" name="All Events">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</allEvents>
<notProcessed switchValue="All" name="Unprocessed Category">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</notProcessed>
<errors switchValue="All" name="Logging Errors & Warnings">
<listeners>
<add name="Rolling Flat File Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
</configuration>
NLogを試してみてください( nlog-project.org )。私の意見では、Log4Netよりも非常に柔軟性があり、操作が簡単です。
NLog.configの例:
<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="file" xsi:type="File"
layout="${longdate} ${logger} ${message}"
fileName="${basedir}/${shortdate}/${windows-identity:domain=false}.${level}.log" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="file" />
</rules>
</nlog>
その他の例(ファイル以外の他のロギングターゲットを含む)については、 GithubのNLog構成例 を参照してください。
以下は、私が現在使用しているアペンダーXMLです。
の要件に基づいて
1)1日1回のログファイルを作成し、
2)txtの拡張子を付けるには、
以下のようなXMLを使用する必要があります。
以下のXMLは、system-20121106.txtというログファイルを作成します。
唯一の問題は、ファイル値がlogs/system-であるため、当日の書き込み中のファイルがsystem-になることです。これを回避するには、ファイル値をlogs/system.txtに設定する必要がありますが、最終的なファイルとしてsystem.txt.20121106.txtを取得します。
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/system-" />
<appendToFile value="true"/>
<countDirection value="-1"/>
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd'.txt'" />
<maxSizeRollBackups value="0" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
特定の時間に作成する必要はありません。最も単純なケースでは、アプリのログサービスを開始するときに、名前として今日の日付のログファイルがあるかどうかを確認できます。ない場合は作成できます。あなたがそれに追加し始める前に1つ。
この設定で特に注意する必要がある唯一のケースは、アプリケーションが深夜を過ぎて実行される場合です。
log4net を使用します。これは、ロギングに最も一般的に使用されるライブラリの1つです。
好きなように簡単に設定できます。サンプルを参照してください。
何かをログに記録するときは、現在の日付のファイルが存在するかどうかを確認し、存在しない場合は作成します。そのような単純な :)
if(fileExists(todaysDate + ".txt")){
appendToLogFile(message);
}else{
createFile(todaysDate + ".txt");
appendToLogFile(message);
}
必要になるまで作成する必要はありません。次を使用してください。
file = new StreamWriter(path, true, new UTF8Encoding(false));
(または別のエンコーディングかもしれません。)これにより、ファイルが存在しない場合はファイルが作成されるか、ファイルへの追加が開始されます。
次に、ファイル名を作成し、それを使用するだけです。
単純なTraceListener
だけが必要な場合は、ここにミニ実装があります: https://github.com/datvm/DailyTraceListener
出力もCSV形式であるため、Excelまたは任意のCSVリーダーで読み取ることができます。
TraceListener
のソースコード:
public class DailyTraceListener : TraceListener
{
public bool UseUtcTime { get; private set; }
public string LogFolder { get; private set; }
public bool Disposed { get; private set; }
public bool HasHeader { get; private set; }
public string CurrentLogFilePath { get; private set; }
protected DateTime? CurrentLogDate { get; set; }
protected FileStream LogFileStream { get; set; }
protected StreamWriter LogFileWriter { get; set; }
private SemaphoreSlim LogLocker { get; set; } = new SemaphoreSlim(1, 1);
public DailyTraceListener(string logFolder)
{
this.LogFolder = logFolder;
}
public DailyTraceListener UseUtc()
{
this.UseUtcTime = true;
return this;
}
public DailyTraceListener UseHeader()
{
this.HasHeader = true;
return this;
}
protected virtual void WriteHeader()
{
this.LogFileWriter.WriteLine(string.Format("{0},{1},{2},{3},{4}",
"Time",
"Type",
"Source",
"ID",
"Message"));
}
protected virtual string FormatTime(DateTime time)
{
return time.ToString("o");
}
private DateTime GetCurrentTime()
{
if (this.UseUtcTime)
{
return DateTime.UtcNow;
}
else
{
return DateTime.Now;
}
}
private void InitializeLogFile()
{
this.CheckDisposed();
try
{
if (this.LogFileWriter != null)
{
this.LogFileWriter.Dispose();
}
if (this.LogFileStream != null)
{
this.LogFileWriter.Dispose();
}
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
var currentTime = this.GetCurrentTime();
var fileName = $"{currentTime.ToString("yyyy-MM-dd")}.log";
this.CurrentLogFilePath = Path.Combine(this.LogFolder, fileName);
// Ensure the folder is there
Directory.CreateDirectory(this.LogFolder);
// Create/Open log file
this.LogFileStream = new FileStream(this.CurrentLogFilePath, FileMode.Append);
this.LogFileWriter = new StreamWriter(this.LogFileStream);
// Write Header if needed
if (this.LogFileStream.Length == 0 && this.HasHeader)
{
this.WriteHeader();
}
}
private void CheckFile()
{
this.CheckDisposed();
var currentTime = this.GetCurrentTime();
if (this.CurrentLogDate == null || currentTime.Date != this.CurrentLogDate)
{
this.InitializeLogFile();
this.CurrentLogDate = currentTime.Date;
}
}
private void CheckDisposed()
{
if (this.Disposed)
{
throw new InvalidOperationException("The Trace Listener is Disposed.");
}
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
var time = this.FormatTime(this.GetCurrentTime());
this.WriteLine(string.Format("{0},{1},{2},{3},{4}",
time,
eventType,
EscapeCsv(source),
id.ToString(),
EscapeCsv(message)));
}
public override void Write(string message)
{
try
{
this.LogLocker.Wait();
this.CheckDisposed();
this.CheckFile();
var currentTime = this.GetCurrentTime();
this.LogFileWriter.Write(message);
this.LogFileWriter.Flush();
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
finally
{
this.LogLocker.Release();
}
}
public override void WriteLine(string message)
{
this.Write(message + Environment.NewLine);
}
protected string EscapeCsv(string input)
{
for (int i = 0; i < input.Length; i++)
{
if (input[i] == ',' || input[i] == '\n')
{
input = input.Replace("\"", "\"\"");
return $"\"{input}\"";
}
}
return input;
}
protected override void Dispose(bool disposing)
{
this.Disposed = true;
try
{
this.LogFileWriter?.Dispose();
this.LogFileStream?.Dispose();
this.LogLocker.Dispose();
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
base.Dispose(disposing);
}
}