28

As the title implies how can I create a new log file for each application run ? I know how to do it for minute/hour/etc. but not for app. run

There is what I have for now:

target name="Debug" archiveEvery="Hour"
archiveFileName="${basedir}/logs/Debug.{#####}.txt" maxArchiveFiles="4" 
archiveNumbering="Sequence" xsi:type="File" fileName="${basedir}/logs/Debug.txt" 
layout="${date:format=HH\:mm\:ss} | ${level} | ${message} ${exception}
${exception:format=stacktrace}"

But actually I dont need to archive every hour, what I want is to archive every time when I run my app. There is what I found in old forum, but I dont know how to use Cached_layout_renderer

invis
  • 1,078
  • 2
  • 14
  • 26

4 Answers4

49

I came across this problem myself, and it took me a long time to figure it out. Most of the answers I've found only have part of the solution and don't explain how/why it works... which makes it hard to adapt if you have a slightly different use case.

Example:

<target name="log"
   xsi:type="File"
   fileName="${basedir}/logs/log.${longdate:cached=true}.log"
   layout="${message}"
   archiveFileName="${basedir}/logs/archives/log.${shortdate}.{#}.log"
   archiveAboveSize="5242880"
   archiveEvery="Day"
   archiveNumbering = "Rolling"
   maxArchiveFiles="20" 
   />

Explanation

You have to use both the Cached Layout Renderer and the longdate variable. To understand why this works, you need to understand how they they work, and how they interact.

longdate:

fileName="${basedir}/logs/log.${longdate}.log"

Using the longdate variable in your log name will pretty much guarantee a new log file on every execution... except it creates a new log file every millisecond even during a single execution which is probably not desirable except in the most rare of circumstances.

Cached Layout Renderer:

fileName="${basedir}/logs/log.${shortdate:cached=true}.log"

Cached layout renderer will cache the variable on the first log call, and then always use that value for subsequent entries... but the cache only persists until the execution completes. Using shortdate, or any other variable that isn't guaranteed to changeon each execution, won't work. It will find a log file with the same filename it wants to use, and it'll just append (or delete if you have that set). This is not what we want.

Combined:

fileName="${basedir}/logs/log.${longdate:cached=true}.log"

This works because it takes the millisecond timestamp of the first log per execution, and then caches it, and always uses that logfile until the execution terminates (clearing the cache). Next time you run it (unless it's the same millisecond... unlikely!) you'll get a new value cached, and a new log file (but only one!).

Mir
  • 2,429
  • 1
  • 29
  • 34
  • This is a helping answer! Thanks. – Mikey Dec 03 '15 at 08:13
  • 2
    I've found another way - `${guid:cached=true}.log` – Kai Jun 29 '17 at 17:19
  • @Mir: This is a very good answer. But I've found a case when it's not working. If autoReload (https://github.com/nlog/NLog/wiki/Configuration-file#automatic-reconfiguration) is set to true and you are changing configuration without closing app it will close current log and start a new one. Is there a way to overcome this? – IgorStack Aug 25 '17 at 21:05
22

NLog's FileTarget support now a Property archiveOldFileOnStartup (NLog-3-2-0 Release).

archiveOldFileOnStartup="true"

There may be some issues with that, but if only a single instance of the App is running at the same time, it should have the desired behavior.

Mikey
  • 629
  • 1
  • 11
  • 19
5

See https://github.com/NLog/NLog/blob/master/tests/NLog.UnitTests/LayoutRenderers/Wrappers/CachedTests.cs for an example of how to use the Cached layout renderer.

Basically it can be used like this:

${cached:${variable}:cached=true}
Xharze
  • 2,703
  • 2
  • 17
  • 30
  • the first place anyone actually showed an example, rather than just saying "oh yeah used the Cached layout renderer" – drzaus Aug 19 '13 at 20:41
  • Cached seems to help prevent creating a new log file if the time/date/variable changes while logging... but I believe what the asker is looking for is a new file every time the executable is run. For example app.1.log, then app.2.log, ..., app.n.log. – Mir Jun 22 '15 at 22:41
4

archiveOldFileOnStartup="true" archiveNumbering="Rolling" deleteOldFileOnStartup="true"

Will archive the existing file and delete it. So you always end up with a new file.

kolaval
  • 171
  • 4
  • 10