Take this simple NLog example configuration:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
How can this be set up to only log while debugging, and not when run in production?
EDIT:
To make things a bit more challenging: My NLog configuration files are centralized, shared over all applications/services/sites. So I would like to avoid altering every single project and just modify the config files.
A simple solution would be to have a NLog.config
file (whose contents will be overriden - you'll see later), plus one NLog config file per solution configuration/environment (let's say, NLog.debug.config
and NLog.release.config
). For example:
Then you configure a Pre-build event command line
to copy the config file corresponding to the current active configuration:
The complete command you should paste there:
del "$(ProjectDir)NLog.config"
if "$(ConfigurationName)"=="Debug" (
copy "$(ProjectDir)NLog.debug.config" "$(ProjectDir)NLog.config"
) else (
copy "$(ProjectDir)NLog.release.config" "$(ProjectDir)NLog.config"
)
This will copy NLog.debug.config
to NLog.config
(effectively overriding it) if DEBUG is the current active configuration/environment, otherwise it will copy NLog.release.config
.
A shorter version would look like this (note the file naming diference though):
del "$(ProjectDir)NLog.config"
copy "$(ProjectDir)NLog.$(ConfigurationName).config" "$(ProjectDir)NLog.config"
Another thing to note is that during compilation the compiler will throw various warnings about duplicate declarations related to NLog. The reason is that the compiler will find 2 (or more) distinct configuration files for NLog and their declarations will collide. In order to fix that you have to change the Properties
of each of your extra NLog configuration files to make the build action not copy them. For example:
Lastly, you may not want to duplicate common/shared targets|rules|whatnot to avoid having to change them in multiple files. To achieve that, you can move these common/shared parts to another file and use <include />.
I see three solutions here.
1) Using config file and its transformations. For the moment the transformations are supported for web applications (Im talking about VS2012). For desktop app you need to install additional extension.
2) Use two targets, one for development (I assume debugging=development in your case) and the second for production. At runtime you need to leave actual one by removing the other.
UPDATE
3) If you don't want to alter the projects it is possible to apply custom conditions to the logger depending on custom Layout Renderer (see example of how to make a custom layout renderer). In your case the layout renderer should return current Build Configuration (Debug or Release) of executing assembly. As a result the condition will look like this:
<rules>
<logger name="*" writeTo="logfile">
<filters>
<when condition="equals('${buildConfiguration}','Release')" action="Ignore" />
</filters>
</logger>
</rules>
where ${buildConfiguration} is your custom layout renderer.
PS And dont forget to put this
<extensions>
<add assembly="NameOfMyAssemblyThatContainsMyLayoutRenderer" />
</extensions>
to the nlog.config so NLog knows about the layout renderer.
I have based my answer on @neleus answer above but it still took me hours to get something working. Here is the completed guide incl. how to set up the LayoutRenderer
. For the NLog.config
you need:
<extensions>
<add assembly="AssemblyName" />
</extensions>
<target xsi:type="AsyncWrapper" name="asyncProd">
<target xsi:type="File" name="logfileProc" fileName="${basedir}/logs/${buildConfiguration}.log"/>
</target>
<logger name="*" minlevel="Info" writeTo="asyncProd">
<filters>
<when condition="equals('${buildConfiguration}','Debug')" action="Ignore" />
</filters>
</logger>
The target above is only for newbees to NLog so they have something running more quickly. Using the custom LayoutRenderer in the filename helps with debugging as you can see it's output in the file that is produced.
Then create a class called BuildConfigLayoutRenderer
which I adapted from neleus' link
[LayoutRenderer("buildConfiguration")]
[ThreadAgnostic]
public class BuildConfigLayoutRenderer : LayoutRenderer {
private String buildconfig;
private String GetBuildConfig() {
if (buildconfig != null) {
return buildconfig;
}
#if DEBUG
buildconfig = "Debug";
#else
buildconfig = "Release";
#endif
return buildconfig;
}
protected override void Append(StringBuilder builder, LogEventInfo logEvent) {
builder.Append(GetBuildConfig());
}
}
Important is the string passed into the LayoutRendererAttribute
. They need to match with what you register (needs to happen as early as possible in your code; main()) and the NLog.config
.
LayoutRenderer.Register<BuildConfigLayoutRenderer>("buildConfiguration");
Now ${buildConfiguration}
will work.
You can also use this for even more build configurations but you need to remember to add the filter that ignores that rule. I also tried the opposite, meaning to have action="Log"
in the rule to reduce the number of filters needed. Later I realised that is non-sense because the default is to use the logger... so you have to ignore it.
This answer nLog forum worked for us.
Reprinted below incase it ever gets lost.
What you can do is have two NLog.config files:
NLog.config
and NLog.Debug.config
In your code, somewhere close to the main method you can do:
#if DEBUG
LogManager.Configuration = new XmlLoggingConfiguration("NLog.Debug.config");
#endif
Now if most of the configuration is the same you can perhaps use include files - put everything htat is common (targets, etc.) into NLog.common.config and reference it with
NLog.debug.config:
<include file="NLog.common.config" />
<logger name="*" minLevel="Trace" writeTo="debug" /> <logger name="*" minLevel="Info" writeTo="viewer" final="true" />
NLog.release.config:
<include file="NLog.common.config" /> <!-- Release rules --> <logger name="*" minlevel="Info" writeTo="file" /> <logger name="*" minLevel="Error" writeTo="event" />
Let me know if it helps.
Jarek
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With