每天创建一个新的日志文件

时间:2010-05-24 15:32:30

标签: c# asp.net winforms logging log4net

标题暗示我如何在C#中每天创建一个新的日志文件?现在,该程序可能不一定全天候运行,但只能在工作时间调用。所以我需要做两件事。

  1. 如何每天创建新的日志文件?日志文件的名称将采用MMDDYYYY.txt
  2. 等格式
  3. 我如何在午夜之后创建它,以防它在夜间的所有时段运行?

10 个答案:

答案 0 :(得分:39)

更新2018:我更喜欢现在使用NLog

关于log4net的上一个答案:

This example显示如何配置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>

答案 1 :(得分:8)

我建议这样的事情:

string logFile = DateTime.Now.ToString("yyyyMMdd") + ".txt";
if (!System.IO.File.Exists(logFile))
{
    System.IO.File.Create(logFile);   
}
//append to logFile here...

你有什么理由想在午夜之后创造它吗?如果在记录错误时它不存在,为什么不创建呢?

还注意到我更改了日期格式。这将允许您按名称对文件进行排序并按顺序获取它们。在以任何方式弄乱日期时,我总是使用这种格式。

答案 2 :(得分:8)

其他人已经提到了Log4Net,所以我会继续和pimp 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}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;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 &amp; Warnings">
                <listeners>
                    <add name="Rolling Flat File Trace Listener" />
                </listeners>
            </errors>
        </specialSources>
    </loggingConfiguration>
</configuration>

答案 3 :(得分:6)

尝试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>

有关更多示例(包括除File之外的其他日志记录目标),请参阅NLog configuration examples on Github

答案 4 :(得分:3)

您不需要在特定时间创建它 - 在最简单的情况下,您可以在启动应用程序的日志记录服务时检查是否存在具有今天日期的日志文件作为其名称,如果没有你可以在开始追加它之前创建一个。

您需要特别注意此设置的唯一情况是应用程序运行过午夜。

答案 5 :(得分:3)

使用log4net。这是最常用的日志记录库之一。

可以根据需要轻松配置,请参阅样品。

答案 6 :(得分:3)

下面是我目前正在使用的appender XML。

根据您的要求 1)每天创建一次日志文件,
2)具有txt的扩展名,
你应该使用类似于下面的XML 下面的XML将创建一个名为system-20121106.txt的日志文件。

唯一的问题是,由于文件值是日志/系统,因此当您在当天写入文件时,您的文件将是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>

答案 7 :(得分:1)

当您记录某些内容时,请检查是否存在具有当前日期的文件,如果不存在 - 创建它。很简单:)

if(fileExists(todaysDate + ".txt")){
  appendToLogFile(message);
}else{
  createFile(todaysDate + ".txt");
  appendToLogFile(message);
}

答案 8 :(得分:0)

在您需要之前无需创建它,请使用:

 file = new StreamWriter(path, true, new UTF8Encoding(false));

(或者可能是不同的编码。)这将创建文件,如果它不存在,或者开始附加到它。

然后就是创建文件名,只使用它。

答案 9 :(得分:0)

如果您只需要一个简单的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);
    }

}