NLog : How to conditional select target based on env variable - c#

I would like to define 2 targets (typically file target on Devops and UDP locally) in nlog and choose them dynamically based on location. Motivation for this is to use different targets when running locally and running on Devops.
There are a number of articles on how to do this using C# code, but I was wondering if it is possible to do this directly in the config file.
In Pseudo Code I am looking for something like this in my rules section:
<rules>
if(Env==DEVOPS)
<logger name="*" minlevel="Info" writeTo="file" />
else
<logger name="*" minlevel="Trace" writeTo="udp" />
end
</rules>

I suggest that you use the method described here:
<nlog>
<variable name="myFileLevel" value="Off" />
<variable name="myUdpLevel" value="Off" />
<rules>
<logger name="*" minLevel="${var:myFileLevel}" writeTo="file" />
<logger name="*" minLevel="${var:myUdpLevel}" writeTo="udp" />
</rules>
</nlog>
And then do this at runtime:
if (DevOps)
{
LogManager.Configuration.Variables["myFileLevel"] = "Debug";
}
else
{
LogManager.Configuration.Variables["myUdpLevel"] = "Trace";
}
LogManager.ReconfigExistingLoggers();
See also: https://github.com/nlog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules

Same configuration as in Rolf Kristensen's answer above, just in json (in case you want to make it a part of the applications' appsettings.json):
"variables": {
"logConsoleLevel": "Off",
"logFileLevel": "Off"
},
"rules": [
{
"logger": "*",
"minLevel": "${var:logConsoleLevel}",
"writeTo": "coloredConsole"
},
{
"logger": "*",
"minLevel": "${var:logFileLevel}",
"writeTo": "logfile"
}
]

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

How to add filter condition for NLog Target

I have a problem I have write a Nlog.target to log in database but I want nlog should log depending on a condition. I want to put a condition if dbvalue is true then made log entries in db.
I wrote the below code which is not working the dbvalue is false but log are still generated in db.
i have added this line in my startup.cs file
GlobalDiagnosticsContext.Set("dbvalue", "false");
here is my nlog.config
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" writeTo="" />
<logger name="*" minlevel="Info" writeTo="database" >
<filters>
<when condition="equals('${gdc:dbvalue}', 'true')" action="Log" />
</filters>
</logger>
</rules>
can someone help?
I would probably do it like this:
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" writeTo="" />
<logger name="*" minlevel="${gdc:dbLogMinLevel:whenEmpty=Off}" writeTo="database" />
</rules>
And then enable the database-logger like this:
NLog.GlobalDiagnosticsContext.Set("dbLogMinLevel","Info");
NLog.LogManager.ReconfigExistingLoggers(); // Explicit refresh active Logger-objects
See also: https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules
See also: https://github.com/NLog/NLog/wiki/Environment-specific-NLog-Logging-Configuration

Using nlog with ApplicationInsightsTelemetryWorkerService in .net core 3.1 console app

I'm configuring a .net core 3 console app with application insights and nlog
My code is configured as follows
Program.cs
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddNLog(NLog.LogManager.LoadConfiguration("nlog.config").Configuration);
})
.ConfigureServices((hostContext, services) =>
{
services.SetupConfiguration(hostContext.Configuration);
services.AddApplicationInsightsTelemetryWorkerService("--AI-Key--");
In my nlog.config I have
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="Microsoft.ApplicationInsights.NLogTarget" />
</extensions>
<!-- the targets to write to -->
<targets>
<target name="Console" xsi:type="Console" layout="${longdate} ${level} ${message}"/>
<target xsi:type="ApplicationInsightsTarget" name="appInsights" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="Console" />
<logger name="*" minlevel="Trace" writeTo="appInsights" />
</rules>
In appsettings.json I have
"Logging": {
"LogLevel": {
"Default": "Debug"
}
},
"ApplicationInsights": {
"InstrumentationKey": "--AI-Key--"
},
In my code I use constructor injection to get the logger and then just
_logger.LogDebug("something");
Yet when I run this I'm not getting anything in application insights. I also notice in my output window I get some logs starting with:
Application Insights Telemetry (unconfigured): .....
There's not much documentation to go on unfortunately. Can anyone point me in the right direction.
Thanks very much.
Besides peter Bons' answer, here is one important thing you should know:
The message Application Insights Telemetry (unconfigured): ..... means that the AI-key is not configured properly, so you cannot see the data float into appInsights.
Please try add the AI-key in nlog.config, like below:
<targets>
<target name="Console" xsi:type="Console" layout="${longdate} ${level} ${message}"/>
<target xsi:type="ApplicationInsightsTarget" name="appInsights">
<instrumentationKey>your_AI_Key</instrumentationKey>
</target>
</targets>
I can repro your issue, if without add AI_Key in nlog.config; But works fine if add AI_Key in nlog.config.
If you still have the issue, please provide a working sample code as well as these nuget packages and versions.
Do mind that setting the loglevel for Application Insights is done at a different level by using a section called ApplicationInsights inside the logging section:
"Logging": {
"LogLevel": {
"Default": "Debug",
"ApplicationInsights"
"LogLevel": {
"Default": "Debug"
}
}
},
"ApplicationInsights": {
"InstrumentationKey": "--AI-Key--"
}
So with you current setup you won't get Debug level messages.

Integration problem NLog with Elasticsearch in .NET Core

I am using NLog to write logs to file, which is working fine. Now I want to write logs to Elasticsearch, so I added NLog.Targets.ElasticSearch in nugets package and I configured my Nlog.config file. Unfortunately, I can't see any log information while calling http://localhost:9200/_search
In NLog.config, I added extension and targets for Elasticsearch:
<extensions>
<add assembly="NLog.Extended" />
<add assembly="NLog.Targets.ElasticSearch"/>
</extensions>
<targets>
<target xsi:type="ElasticSearch"
name="elastic"
layout="${logger} | ${threadid} | ${message}"
includeAllProperties="true"
uri="http://localhost:9200"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
<logger name="*" minlevel="Trace" writeTo="elastic" />
</rules>
I expect Trace type NLog should be written in Elasticsearch. Am I missing something in the config file?
By the way, I checked this doc for parameters: https://github.com/ReactiveMarkets/NLog.Targets.ElasticSearch/wiki
I just added BufferingWrapper type and it worked. Some references to read:
https://github.com/markmcdowell/NLog.Targets.ElasticSearch/blob/master/src/NLog.Targets.ElasticSearch.Tests/App.config
https://github.com/nlog/NLog/wiki/BufferingWrapper-target
Additionally, please check ElasticSearch.Net latest version in NuGet package.
You can find NLog configuration for Elasticsearch below, which is working fine for me:
<extensions>
<add assembly="NLog.Extended" />
<add assembly="NLog.Targets.ElasticSearch"/>
</extensions>
<target xsi:type="BufferingWrapper" name="ElasticSearch"
flushTimeout="5000">
<target xsi:type="ElasticSearch"
uri="http://localhost:9200"
includeAllProperties ="true">
</target>
</target>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
<logger name="*" minlevel="Trace" writeTo="ElasticSearch" />
</rules>

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

Categories