adams85 / filelogger

A lightweight yet feature-rich file logger implementation for the Microsoft.Extensions.Logging framework.
MIT License
147 stars 22 forks source link

Roll on program start #10

Closed smint80 closed 4 years ago

smint80 commented 4 years ago

I would like to be able to enable a setting for always creating next file on program start nomatter how big the file last used is.

deanwiles commented 4 years ago

To get a unique filename on program start, you can leverage the CustomBehavior sample that @adams85 provided. I added a template placeholder to the file path, so that the filename contains the start date & time (e.g. "Path": "<appname>-<startdate:yyyyMMdd-HHmmss>-<counter:000>.log"). See my CustomFileLoggerProcessor.cs in WFAppLogger for an example of how to implement this.

adams85 commented 4 years ago

I doubt that this requirement is too common, so I don't think it's worth introducing a new setting.

However, it's achievable pretty easy by customization of the logger processor. So @deanwiles pointed you in the right direction. I can only add to his comment that you don't need to include the datetime in the file name to get this behavior.

I'd rather do something like this:

public class CustomFileLoggerProcessor : FileLoggerProcessor
{
    public CustomFileLoggerProcessor(FileLoggerContext context) : base(context) { }

    protected override LogFileInfo CreateLogFile(ILogFileSettings fileSettings, IFileLoggerSettings settings)
    {
        LogFileInfo logFile = base.CreateLogFile(fileSettings, settings);

        var dummyEntry = new FileLogEntry
        {
            Text = string.Empty,
            Timestamp = Context.GetTimestamp()
        };

        while (logFile.FileAppender.FileProvider.GetFileInfo(Path.Combine(logFile.BasePath, FormatFilePath(logFile, dummyEntry))).Exists)
            logFile.Counter++;

        return logFile;
    }
}

This way the counter will be set to the first unused number when the log file gets created and you only need to include a counter in your log file name templates (e.g. myapp-<counter:000>.log). Just check out the CustomBehavior sample for how to wire up the customization.

deanwiles commented 4 years ago

Hi @adams85. Thanks for the feedback. Using the Context's timestamp will change over time or over dates, which may be desirable for a continually-running service like a website. However if my case (and possibly @smint80's), my app is a WinForm client exe and I want to get the logs associated with a particular user's run of the app, so app start date/time is preferable to Context timestamp. Hope that makes sense. Or am I missing something?

adams85 commented 4 years ago

@deanwiles No, you aren't. I see where you are getting at.

In that case this is the way to go:

public class CustomFileLoggerProcessor : FileLoggerProcessor
{
    private readonly DateTimeOffset _startupTimestamp;

    public CustomFileLoggerProcessor(FileLoggerContext context) : base(context) 
    {
        _startupTimestamp = context.GetTimestamp();
    }

    protected override LogFileInfo CreateLogFile(ILogFileSettings fileSettings, IFileLoggerSettings settings)
    {
        LogFileInfo logFile = base.CreateLogFile(fileSettings, settings);

        while (logFile.FileAppender.FileProvider.GetFileInfo(Path.Combine(logFile.BasePath, FormatFilePath(logFile, null))).Exists)
            logFile.Counter++;

        return logFile;
    }

    protected override string GetDate(string inlineFormat, LogFileInfo logFile, FileLogEntry entry)
    {
        return _startupTimestamp.ToLocalTime().ToString(inlineFormat ?? logFile.DateFormat, CultureInfo.InvariantCulture);
    }
}
afruzan commented 3 years ago

see my gist for easy and clean workaround https://gist.github.com/guidomocha/1ac375e9fe215c6f7f2649b4007ea9fa