Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create NLog file with current date and time without caching it, keeping the archive file name the same

Tags:

c#

nlog

I'm using NLog to do some logging and I've run into an issue with the archiving and filenames.

I'm creating the logging configurations in code (I'm writing a wrapper to expose some specific functionality), and I've got the FileTarget object created with these options:

this._fileTarget.FileName = "${date:format=yyyy-MM-dd hh.mm.ss}.log";
this._fileTarget.ArchiveAboveSize = Math.Pow(1024, 2) * 5; //5MB
this._fileTarget.ArchiveNumbering = ArchiveNumberingMode.Date;
this._fileTarget.ArchiveEvery = FileArchivePeriod.Day;
this._fileTarget.ArchiveDateFormat = "yyyy-MM-dd hh.mm.ss";

I'm not sure why NLog did it like this, but that file name layout will create a new log file every second instead of just using the file name until the archive period is up.

I added the cached target wrapper to the filename as such:

this._fileTarget.FileName = "${cached:cached=true:inner=${date:format=yyyy-MM-dd hh.mm.ss}.log}";

But all that buys me is a file name that now never changes, and looks like this when archived

2014-12-03 12.00.00.2014-12-03 12.00.00.log
2014-12-03 12.00.00.2014-12-03 12.10.00.log
etc...

Is it possible to tell NLog to only archive files based on the file size and date and to ignore the archive numbering and date formatting? I'm trying to produce log files whose name is the timestamp of when it was created, where new files are only created above a certain size or every day.

Edit: This is what I am trying to acheive:

On application start

  1. Creates log file with the file name in the format of "yyyy-MM-dd hh.mm.ss".txt by using the current time stamp (Example -> "2014-04-29 11:11:11.txt")
  2. The application logs to that file for a while until it either
    • Becomes too large (over a defined limit) or
    • The archive time elapses (in my case, this is one day)
  3. The logger then stops writing to the file created in 1. ("2014-04-29 11.11.11.txt") and does not rename it or otherwise add sequential/rolling numbers or date formatting to it.
  4. Repeat steps 1-3 until the end of time.

Leaving me with a Log folder that looks like this:

Logs
|
|> 2014-12-10 12:50:50.txt    (1024 kb)
|> 2014-12-10 12:50:55.txt    (1020 kb)
|> 2014-12-10 12:51:01.txt    (1024 kb)
|> 2014-12-10 12:51:10.txt    (1003 kb)  
|> 2014-12-10 12:51:20.txt    (400 kb)  <-The currently active log file.
like image 447
Brandon Avatar asked Dec 03 '14 16:12

Brandon


2 Answers

This is an old question, but there are some recent improvements for this case.

I'm not sure why NLog did it like this, but that file name layout will create a new log file every second instead of just using the file name until the archive period is up.

Since NLog 4.3.9 you could configure the "cachekey", so you could control when the cache should be invalided.

For this case the following configration give you the date and time in the file name, but only 1 file each day. The time in the file name will the time of the first log event for that day.

filename="${cached:cached=true:Inner=${date:format=yyyy-MM-dd hh.mm.ss}:CacheKey=${shortdate}}.log"
like image 90
Julian Avatar answered Sep 21 '22 07:09

Julian


I don't know if you can do this with native layouts, but it's relatively easy to implement your own LayoutRenderer to achieve this.

I've done something pretty close to what you want a few time ago :

    [LayoutRenderer("UniqueName")]
    public class UniqueNameLayoutRenderer : LayoutRenderer
    {
        #region Fields (1)

        private string _constantName;

        #endregion Fields

        #region Enums (1)

        public enum PatternType
        {
            /// <summary>
            /// Long date + current process ID
            /// </summary>
            LongDateAndPID,
            /// <summary>
            /// Long date (including ms)
            /// </summary>
            LongDate,
        }

        #endregion Enums

        #region Properties (2)

        public string ConstantName
        {
            get
            {
                if (_constantName == null)
                {
                    if (Format == PatternType.LongDateAndPID)
                    {
                        string pid;
                        try
                        {
                            pid = Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture);
                        }
                        catch
                        {
                            pid = "000"; 
                        }

                        _constantName = DateTime.Now.ToString("yyyy-MM-dd_HHmmss-ffff") + "_pid" + pid;
                    }
                    else if (Format == PatternType.LongDate)
                    {
                        _constantName = DateTime.Now.ToString("yyyy-MM-dd_HHmmss-ffff");
                    }
                }

                return _constantName;
            }
        }

        [DefaultParameter]
        public PatternType Format { get; set; }

        #endregion Properties

        #region Methods (2)

        // Protected Methods (1) 

        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
        {
            builder.Append(ConstantName);
        }
        // Private Methods (1) 

        #endregion Methods
    }
}

It will generate the name of the file at the first call with current long time, and keep it until the end of execution. I have mostly used it with NLog 2 but it looks like to work well with NLog 3.2.

It's intended to be used with

"{UniqueName:format=LongDate}" 

in NLog configuration file for example. "LongDateAndPID" adds process id at the end of name, it can be useful to track different instances with rolling logs enabled.

Before to use it, you should register the appender with :

<extensions><add assembly="MyAssemblyWhichContainsRenderer"/></extensions>

To use it with rolling enabled, just use something like this :

<target xsi:type="File"
        name="logfile"
        fileName="${logDirectory}\logs-${UniqueName:format=LongDateAndPID}.txt"
        layout="${longdate} | ${level:uppercase=true} (${threadid}) | ${callsite} : ${message} ${exception:format=ToString}"
        archiveFileName="${logDirectory}\logs-${UniqueName:format=LongDateAndPID}_{##}.txt"
        archiveAboveSize="25165824"
        concurrentWrites="false"
        archiveNumbering="Sequence"
        maxArchiveFiles="99999" />

(of course this is just an example)

Feel free to adapt the layout renderer to you own needs.

like image 27
AFract Avatar answered Sep 17 '22 07:09

AFract