NLog DB Configuration - nlog

From the docs https://github.com/NLog/NLog/wiki/Database-target
It seems settings are shown as attributes on the target element such as:
<target xsi:type="Database"
name="String"
dbUserName="Layout"
dbProvider="String"
and in the example below as separate child nodes:
<target name="database" xsi:type="Database">
<connectionStringName>NLogDb</connectionStringName>
Neither work for me, I just get Invalid configuration exceptions with this message:
NotSupportedException: Parameter connectionStringName not supported on DatabaseTarget
The Config File:
<?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"
autoReload="true"
internalLogLevel="info"
throwExceptions="true"
internalLogFile="c:\temp\internal-nlog.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
<target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<target xsi:type="Database"
name="database"
keepConnection="true"
useTransactions="true"
dbProvider="System.Data.SqlClient"
connectionStringName="DefaultConnection"
commandText="INSERT INTO Logs (EventDateTime, EventLevel, UserName, MachineName, EventMessage, ErrorSource, ErrorClass, ErrorMethod, ErrorMessage, InnerErrorMessage) VALUES (#EventDateTime, #EventLevel, #UserName, #MachineName, #EventMessage, #ErrorSource, #ErrorClass, #ErrorMethod, #ErrorMessage, #InnerErrorMessage)">
<parameter name="#EventDateTime" layout="${date:s}" />
<parameter name="#EventLevel" layout="${level}" />
<parameter name="#UserName" layout="${aspnet-user-identity}" />
<parameter name="#MachineName" layout="${machinename}" />
<parameter name="#EventMessage" layout="${message}" />
<parameter name="#ErrorSource" layout="${event-context:item=error-source}" />
<parameter name="#ErrorClass" layout="${event-context:item=error-class}" />
<parameter name="#ErrorMethod" layout="${event-context:item=error-method}" />
<parameter name="#ErrorMessage" layout="${event-context:item=error-message}" />
<parameter name="#InnerErrorMessage" layout="${event-context:item=inner-error-message}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile,database" />
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxLevel="Info" final="true
" />
<!-- BlackHole without writeTo -->
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
How it is being called in program.cs
var logger = NLog.Web.NLogBuilder.ConfigureNLog( "nlog.config" ).GetCurrentClassLogger();
(copied from their docs)
Must be missing something obvious, but since there is conflicting info in the docs, and copying other people's configs posted on here, not sure where to go with it

Looks like you are running on NetCore. NLog is not able to read connectionStringName from AppSettings.json as you have found out yourself (Requires extra dependencies to access IConfiguration).
One possible solution is using this extension:
https://www.nuget.org/packages/NLog.Appsettings.Standard/
And use connectionString (Instead of connectionStringName) in NLog.config:
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="NLog.Appsettings.Standard"/>
</extensions>
<target xsi:type="Database" connectionString="${appsettings:name=ConnectionStrings.DefaultConnection}">
Alternative solution is to assign a GDC variable before logging:
NLog.GlobalDiagnosticsContext.Set("DefaultConnection", Configuration.GetConnectionString("DefaultConnection"));
And then use GDC in NLog.config:
<target xsi:type="Database" connectionString="${gdc:item=DefaultConnection}">
See also https://github.com/NLog/NLog/wiki/Gdc-layout-renderer
Update NLog.Extension.Logging ver. 1.4.0
With NLog.Extension.Logging ver. 1.4.0 then you can now use ${configsetting}
See also: https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer

Related

NLog - create log file at specific directory in linux

I've a .net core application on linux server.also in application i used nlog for logging. my application path on linux is /var/www-ninja/html/finance.api.gurukul.ninja. but with use of nlog i want to store logs in other linux directory. which is like /var/log/api/ninja/finance. so can I store logs in that directory. how can i do that ? for more details
nlog.production.config
<?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"
autoReload="true"
internalLogLevel="Info"
internalLogFile="c:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="NLog.Extensions.Logging"/>
<add assembly="NLog"/>
</extensions>
<variable name="ExceptionLayout" value="${longdate} [${processid}] ${uppercase:${level}} ${logger:shortName=true} ${environment-user} ${local-ip} ${aspnet-request-url} ${aspnet-request-method} ${message}${exception:format=tostring,Stacktrace}"/>
<variable name="CommonLayout" value="${longdate} [${processid}] ${uppercase:${level}} ${logger:shortName=true} ${environment-user} ${local-ip} ${message} "/>
<variable name ="logDir" value="/var/log/api/ninja/finance" />
<targets async="true">
<target xsi:type="File" name="file" layout="${CommonLayout}" fileName="${logDir}\log-${shortdate}.log" />
<target name="fileAsException"
xsi:type="FilteringWrapper"
condition="length('${exception}')>0">
<target xsi:type="File"
fileName="${logDir}\log-${shortdate}.log"
layout="${ExceptionLayout}" />
</target>
</targets>
<rules>
<logger name="*" writeTo="file,fileAsException"/>
<logger name="Microsoft.*" maxlevel="Info" final="true" />
</rules>
</nlog>
Make sure to use Unix-path, so stop using backslash \
Ex. instead of ${logDir}\log-${shortdate}.log then it should be ${logDir}/log-${shortdate}.log.
If still having issues then try to activate the NLog InternalLogger and check the output https://github.com/NLog/NLog/wiki/Internal-Logging

Asynchronous batch logging using Nlog and Asp.net core 2.0 in database

I am using NLog for logging in asp.net core 2.0. I am storing my log events in database.
I want my messages to save in batches asynchronously.
Nlog.config settings are:
<?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" autoReload="true"
internalLogLevel="Warn" internalLogFile="c:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<targets>
<target name="file" xsi:type="AsyncWrapper" queueLimit="5000" batchSize="5" overflowAction="Discard">
<target name="db" xsi:type="Database"
connectionString="Data Source=.;Initial Catalog=DatabaseName;User Id=userId;Password=pwd;"
commandType="StoredProcedure" commandText="Sp_name" dbProvider="System.Data.SqlClient">
<parameter name="#TimeStamp" layout="${date}" />
<parameter name="#Level" layout="${uppercase:${level}}" />
<parameter name="#Message" layout="${message}" />
<parameter name="#Exception" layout="${exception}" />
<parameter name="#StackTrace" layout="${exception:format=StackTrace,Data:maxInnerExceptionLevel=10}" />
<parameter name="#eventLookupId" layout ="1" />
</target>
</target>
</targets>
<rules>
<logger name="Microsoft.*" minlevel="Info" writeTo="" final="true" />
<logger name="*" minlevel="Info" writeTo="file" />
</rules>
</nlog>
For the above configuration I am expecting it to log in a batch size of 5 but it is logging immediately at the trigger of event rather than logging in a batch.
Not sure if any other configuration is also required to make it work.
NLog will sent the messages continuously with of max of the batchsize (5 here), and with a time between batches. The default "timeToSleepBetweenBatches" for the asyncWrapper is 1 ms.
e.g. when the batchsize is 100 and the timeToSleepBetweenBatches is 1 sec, a max of 6000 messages/minute are sent.
See the options: https://github.com/NLog/NLog/wiki/AsyncWrapper-target#buffering-options

NLog: Does the FormControl target really exist?

According to the documentation, NLog offers a FormControl target that will write log messages into the Text property of a control on a Windows Form. However, when I add a FormControl target to my configuration, I get an exception telling me that no target exists named "FormControl". I did download the NLog.Windows.Forms package and include a reference to the DLL in my project.
Here's the configuration:
<?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"
throwExceptions="true">
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets>
<!--
<target xsi:type="File" name="FileTarget" fileName="${basedir}/NLogger_4_1_2.log"
layout="${date} ${uppercase:${level}} ${message}" />
-->
<target name="AsyncTarget" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
<target xsi:type="File" name="FileTarget1" fileName="${basedir}/NLogger_4_1_2.log"
layout="${date} ${uppercase:${level}} ${message}" />
</target>
<target xsi:type="File" name="ReportTarget" fileName="${basedir}/NLogger_4_1_2_report.log"
layout="${date} ${uppercase:${level}} ${message}" />
<target xsi:type="FormControl"
name="FormControlTarget"
layout="${message}"
append="true"
controlName="TextBox1"
formName="Form1" />
</targets>
<rules>
<logger name="FileLogger" minlevel="Trace"
writeTo="AsyncTarget" />
<logger name="ReportLogger" minlevel="Trace"
writeTo="ReportTarget" />
<logger name="FormLogger" minlevel="Trace"
writeTo="FormControlTarget" />
</rules>
</nlog>
I found this question in 2022 trying to get this working in VS2022. The answer is you need the NLog.Windows.Forms NuGet package installed.
And it is recommended to update NLog.config to include NLog.Windows.Forms-assembly in <extensions>:
<?xml version="1.0" encoding="utf-8" ?>
<nlog>
<extensions>
<add assembly="NLog.Windows.Forms"/>
</extensions>
...
</nlog>

How do I make aspnet-request available in my NLog config?

I am trying to add the ip address to logging. I installed the NLog.Extended package and ensured that the NLog.Extended.dll is present in my bin next to the base NLog.dll. I have added the variable "${aspnet-request:serverVariable=remote_addr}" to my layout renderer. I get a generic error saying:
An error occurred creating the configuration section handler for nlog: Exception occurred when loading configuration from [my Web.config]
Here is my NLog.config:
<?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="NLog.Extended" />
</extensions>
<targets async="true">
<target name="fileLog" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${aspnet-request:serverVariable=remote_addr} ${longdate} ${callsite} ${level} ${message} ${exception:format=ToString}" />
<target name="dbLog" xsi:type="Database" connectionStringName="db.data" commandText="insert into log ([Date], [Origin], [LogLevel], [Message], [Exception], [StackTrace]) values (#date, #origin, #logLevel, #message, #exception, #stackTrace)">
<parameter name="#date" layout="${date}"/>
<parameter name="#origin" layout="${callsite}"/>
<parameter name="#logLevel" layout="${level}"/>
<parameter name="#message" layout="${message}"/>
<parameter name="#exception" layout="${exception:format=Message,StackTrace}"/>
<parameter name="#stackTrace" layout="${stacktrace}"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="dbLog" />
<logger name="*" minlevel="Trace" writeTo="fileLog" />
</rules>
</nlog>
When I remove the AspNetRequest variable it doesn't complain. I've tried replacing "remote_addr" with "remote_host" with no change. This project is using NLog 2.1.0. Any ideas on what I'm doing wrong here?
If you're using NLog 4.0 then you'll need NLog.Web to use the aspnet=* layout renderers.
It turned out that the NLog.Extended.dll(3.1.0.0) had to match the NLog.dll it was referencing. I upgraded the NLog.dll to 3.1.0.0 and everything is working now.
In my ASP.NET webapi 2.0 solution I had a separate projects for my API's and logging. Using nLog 4.4.12 installed through NuGet and all the helper packages (Config,Extended,Web,Schema) in the logging project.
The "aspnet-request" properties in my config would not work until I added the nLog references to my api project, even though "Copy Local" is set to true for all the nLog DLL's in the logging project. My nLog section from my web.config is below.
Hope this help someone,
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="db" xsi:type="Database" connectionStringName="NLogConn" commandType="StoredProcedure" commandText="[dbo].[NLog_AddEntry_p]">
<parameter name="#machineName" layout="${machinename}" />
<parameter name="#siteName" layout="${iis-site-name}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#username" layout="${aspnet-user-identity}" />
<parameter name="#message" layout="${message}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#properties" layout="${all-event-properties:separator=|}" />
<parameter name="#serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
<parameter name="#port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
<parameter name="#url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
<parameter name="#https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
<parameter name="#serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
<parameter name="#remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
<parameter name="#callSite" layout="${callsite:fileName=true:includeSourcePath=false:skipFrames=1}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="db" />
</rules>

How to force nlog to throw an exception when the logging to database fails?

When I take down the database that backs nlog, nothing gets get logged and it seems NLog swallows the problem. Is there any way to configure it to raise and exception or at least to log in a text file that logging failed?
Here is what my configuration looks like:
<?xml version="1.0" ?>
<nlog autoReload="true" throwExceptions="true" internalLogFile="${basedir}/App_Data/nlog.txt" internalLogLevel="Debug"
internalLogToConsole="true">
<targets>
<!--Useful for debugging-->
<target name="consolelog" type="ColoredConsole"
layout="${date:format=HH\:mm\:ss}|${level}|${stacktrace}|${message}" />
<target name="databaselog" type="Database">
<dbProvider>System.Data.SqlClient</dbProvider>
<!-- database connection parameters -->
<!-- alternatively you could provide a single 'connectionstring' parameter -->
<connectionString>Data Source=.\SQLEXPRESSZ;Initial Catalog=aspnetdb;Integrated Security=SSPI</connectionString>
<commandText>
insert into NLog_Error ([time_stamp],[level],[host],[type],[source],[logger],[message],[stacktrace],[allxml]) values(#time_stamp,#level,#host,#type,#source,#logger,#message,#stacktrace,#allxml);
</commandText>
<parameter name="#time_stamp" layout="${utc_date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#host" layout="${machinename}" />
<parameter name="#type" layout="${exception:format=type}" />
<parameter name="#source" layout="${callsite:className=true:fileName=false:includeSourcePath=false:methodName=false}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#message" layout="${message}" />
<parameter name="#stacktrace" layout="${exception:stacktrace}" />
<parameter name="#allxml" layout="${web_variables}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="databaselog" />
</rules>
</nlog>
You can force Nlog to throw exception when sql server is not reached by following
<nlog throwExceptions="true">
... your nlog config
</nlog>
More info here,
http://nlog-project.org/2010/09/05/new-exception-handling-rules-in-nlog-2-0.html
It's a new feature in v2.0 so you need v2.0.
It will not work in earlier versions.
Also checkout following configuration info
https://github.com/NLog/NLog/wiki/Logging-Troubleshooting
which allows Nlog to log it's own exceptions to a specified file.
Does NLog.config have the property "Copy to Output Directory" set as "Copy always"?
I think you have wrong NLog.config file: you use elements instead of attributes within the target (documentation). Should be something like this:
<target
name="databaselog"
type="Database"
dbProvider="System.Data.SqlClient"
connectionString="Data Source=.\SQLEXPRESSZ;Initial Catalog=aspnetdb;Integrated Security=SSPI"
commandText="insert into NLog_Error ([time_stamp],[level],[host],[type],[source],[logger],[message],[stacktrace],[allxml]) values(#time_stamp,#level,#host,#type,#source,#logger,#message,#stacktrace,#allxml);">
<parameter name="#time_stamp" layout="${utc_date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#host" layout="${machinename}" />
<parameter name="#type" layout="${exception:format=type}" />
<parameter name="#source" layout="${callsite:className=true:fileName=false:includeSourcePath=false:methodName=false}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#message" layout="${message}" />
<parameter name="#stacktrace" layout="${exception:stacktrace}" />
<parameter name="#allxml" layout="${web_variables}" />
</target>

Resources