Nlog config escape colon - c#

I have a NLog.config file with the following variable
<variables>
<variable name="LogsFilePath" value="${appsetting:item=LogsFolderPath:default=C:\Company\Logs}" >
</variables>
<targets>
<target name="File"
xsi:type="File"
fileName="${LogsFilePath}\${event-properties:FileName}.log" />
</targets>
<rules>
<rule logger="DynamicLogger_*" minLevel="Trace" writeTo="File" />
</rules>
When there is no value in app.config file the default value taken is only C (because of the colon).
My target is something like this
Also if I use the variable in the config file like ${var:LogsFilePath} I have problems because of the colon. I have to use it with the static form ${LogsFilePath}
How can I solve this and use a path as default value in the default path of the appsetting variable?

You need to escape it. Replace ":" with "\:", also you need to escape backslash.
I got it working like this
<variables>
<variable name="LogsFolderPath" value="${appsetting:item=LogsFolderPath:default=C\:\\Company\\Logs}" />
</variables>

Related

Using NLog with InfluxDB

I want to configure Nlog.config to log into InfluxDB the same as logging to Seq. I couldn't find any InfluxDB extension for NLog. Do I need just to implement my own NLog.Targets.Targetor there is already something that works with InfluxDB?
Have you tried NLog.Targets.InfluxDB ?
<nlog>
<extensions>
<add assembly="NLog.Targets.InfluxDB"/>
</extensions>
<targets>
<target type="InfluxDB"
name="influx"
Host="https://yourinfluxhost.com"
Bucket="MyBucket"
Token="inFluXApi=K3y"
Org="Organisation">
<field name="data1" value="${event-properties:data1:format=#}" />
<tag name="data2" value="${event-properties:data2:format=#}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="influx" />
</rules>
</nlog>
Ex.
log.Info("This field {#data1} and tag {#data2} are sent to InfluxDB", data1, data2);
See also: https://github.com/tomcheney/nlog-influx-target

Programmatic change of NLog variable value is not taking effect

This is my NLog.config in which I've defined a variable logLevelMaxLength:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="true"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<variable name="logLevelMaxLength" value="20" />
<targets>
<target name="logfile" xsi:type="File" fileName="logfile.log" layout="${longdate}|${pad:padding=${logLevelMaxLength}:inner=${level:uppercase=true}}|${logger}|${message}" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="logconsole" />
<logger name="*" minlevel="Trace" writeTo="logfile" />
</rules>
</nlog>
I am using that variable value to pad the level printing in the log. But then in my code, I'm updating that value and trying to get the logging to use the new value for padding:
MessageBox.Show(LogManager.Configuration.Variables["logLevelMaxLength"].ToString()); //Shows old value: 20
LogManager.Configuration.Variables["logLevelMaxLength"] = "10";
MessageBox.Show(LogManager.Configuration.Variables["logLevelMaxLength"].ToString()); //Shows new value: 10
I am able to change the value programmatically and confirm the change via a MessageBox, but still the logs printed are still using the old value for printing. I even tried using the LogManager.ReconfigExistingLoggers(); command, but it didn't help. What am I doing wrong ?
When using ${logLevelMaxLength} the value can't be changed runtime. If you need this, use this syntax: ${var:logLevelMaxLength}
See docs of the var layout renderer
Performance is better when using NLog variables directly in config file (Ex. ${myvar}), instead of using this layout renderer that always performs dynamic lookup (Ex. ${var:myvar}). But this layout renderer reacts to NLog variables being modified at runtime.
Padding property
Unfortunately the padding property of ${pad} isn't layoutable (it's not of type Layout), so you can't use a dynamic value.
There are multiple solutions for that:
Edit the value from the API (e.g. C#)
Write your own padding layout renderer, which works with Layouts: https://github.com/NLog/NLog/wiki/How-to-write-a-custom-layout-renderer
Current work-around is to declare the entire Layout as NLog Config Variable, and then update the NLog Config Variable with the new complete updated Layout. Using ${var:mySpecialLayout}. See also (Thanks Rolf Kristensen!)

In NLog, is it possible to use layouts to define the log level?

I would like to use Layouts in NLog to be able to change the minimum log level using an external variable :
<nlog>
<variable name="loglevel" value="Debug"/>
<targets>
<target ... />
</targets>
<rules>
<logger name="*" minlevel="${loglevel}" writeTo="LogFile" />
</rules>
</nlog>
After starting NLog, all log levels (eg : Tracing, Debug, Info, ...) are set to false which indicate NLog failed to parse minlevel attribute properly.
The NLog layout feature seems to works with target attributes only.
What I want to achieve : in my real app, loglevel is not a constant but rather a custom layout renderer.
I have also tried to replace value="Debug" by value="LogLevel.Debug" without success.
** Updated Answer **
NLog ver. 4.6 added support for using NLog-Config-Variables in minLevel. See https://github.com/NLog/NLog/pull/2709
NLog ver. 4.6.7 added support for adjusting minLevel at runtime, by modifying NLog-Config-Variables and calling ReconfigExistingLoggers(). See https://github.com/NLog/NLog/pull/3184
** Original Answer **
The minlevel, maxlevel and level attributes on <logger> should be fixed strings.
In this case you could use a <filter>, e.g.
<nlog>
<variable name="loglevel" value="Debug"/>
<targets>
<target ... />
</targets>
<rules>
<logger name="*" writeTo="LogFile" >
<filter condition="${level} >= ${loglevel}" action="Log">
</logger>
</rules>
</nlog>
See the docs

Ignoring NLog Configuration referenced in other assembly

I have a unique problem with the NLog. I have a third-party assembly we use into our project. They have used the NLog into their project and referenced NLog configuration into their configuration which I don't have access to.
I initially had a problem even adding the NLog to a project since both version of dlls were different. I had to download the source code of NLog and change the assembly name since alias was not working for me (OR I didn't know how to use it.)
After giving my own assembly name, NLog started wotrking but.. It started logging third-party log information too with it. Looks like they were not careful enough when defining the logger and they just defined (*). Now my question is, how do I avoid their stuff from logging in to my file? I have also tried setting it to final = true.
Here is how my very simple configuration file looks like.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- add your targets here -->
<!--
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
<target name="errorLog" xsi:type="File"
fileName="${basedir}/logs/error/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}${onexception:${newline}EXCEPTION\: ${exception:format=ToString}}"
/>
<target name="generalLog" xsi:type="File"
fileName="C:/logs/${date:format=yyyy-MM-dd}.log"
layout="${longdate} ${uppercase:${level}} ${message}"/>
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="Errors" writeTo="errorLog" minlevel="Warn"/>
<logger name="EBusiness.Model.*" writeTo="generalLog" levels="Trace,Debug,Info" final="true"/>
<!--
<logger name="*" minlevel="Trace" writeTo="f" />
-->
</rules>
</nlog>
If they are writing to the root logger, you should configure the root logger to not log to anywhere you care (maybe point it at a console logger) and your application can log to a specific logger which does write to your files.
Ugly, but should work.
For example:
Add this target:
<target name="console" xsi:type="Console" />
And Change the * rule to be:
<logger name="*" minlevel="Fatal " writeTo="console" />
Then, Add your own logger rule, say something like:
<logger name="MyNameSpace.*" minlevel="Trace" writeTo="logfile" final="true" />
Assuming you have a logfile target defined pointing at your file.

How to make Nlog archive a file with the date when the logging took place

We are using Nlog as our logging framework and I cannot find a way to archive files the way I want. I would like to have the date of when the logging took place in the logging file name.
Ex All logging that happend from 2009-10-01 00:00 -> 2009-10-01:23:59 should be placed in Log.2009-10-01.log. But all the logs for this day should be placed in Log.log for tailing and such.
The current NLog.config that I use looks like this.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<extensions>
<add assembly="My.Awesome.LoggingExentions"/>
</extensions>
<targets>
<target name="file1" xsi:type="File"
fileName="${basedir}/Logs/Log.log"
layout="${longdate} ${level:uppercase=true:padding=5} ${session} ${storeid} ${msisdn} - ${logger:shortName=true} - ${message} ${exception:format=tostring}"
archiveEvery="Day"
archiveFileName="${basedir}/Logs/Log${shortdate}-{#}.log"
archiveNumbering="Sequence"
maxArchiveFiles="99999"
keepFileOpen="true"
/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file1" />
</rules>
</nlog>
This however sets the date in the logfile to the date when the new logfile is created. Which cause frustration when you want to read logs later.
It also seems like I have to have atleast one # in the archiveFileName, which I rather not. So if you got a solution for that also I would be twice as thankful =)
Probably too late to help you, but I believe all you need to do is include the date in the file name using the date layout renderer with the proper date format. By including the date, you don't need to specify the archive features. When the date changes, a new file will be automatically created.
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<extensions>
<add assembly="My.Awesome.LoggingExentions"/>
</extensions>
<targets>
<target name="file1" xsi:type="File"
fileName="${basedir}/Logs/${date:format=yyyy-MM-dd}.log"
layout="${longdate} ${level:uppercase=true:padding=5} ${session} ${storeid} ${msisdn} - ${logger:shortName=true} - ${message} ${exception:format=tostring}"
keepFileOpen="true"
/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file1" />
</rules>
</nlog>
Just in case if somebody still needs a solution -- requested feature has been added to NLog recently: https://github.com/NLog/NLog/pull/241, but it is still not available by Nuget
Maybe this is what you need,
Daily folder with the file Log.log in it
<target xsi:type="File" name="file1" fileName="${basedir}/logs/Log.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>

Categories