Want to log Database connection failure issue in other file using NLog - c#

I am working on .Net Core 2.2 and MySQL.
General log of application are logged into Database using NLog but I want to log only DB errors (If occurs while logging) to the file.
How I can capture DB connection failure to the file with custom fields like UserID.?
Here's the code of 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"
autoReload="true"
throwExceptions="false"
internalLogLevel="Warn"
internalLogFile="D:\logs\New\internal-nlog.txt">
<targets>
<target name="database" xsi:type="Database"
dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
connectionString="${var:myConnectionstring}">
<commandText>
insert into log (
Logged, Message,
CallSite, Exception, userID
) values (
#Logged, #Message,
#Callsite, #Exception, #userID
);
</commandText>
<parameter name="#logged" layout="${date}" />
<parameter name="#message" layout="${message}" />
<parameter name="#callSite" layout="${event-properties:Callsite}" />
<parameter name="#exception" layout="${exception:tostring}" />
<parameter name="#userID" layout="${event-properties:userID}" />
</target>
</targets>
<rules>
<logger name="*" level="Error" writeTo="database" />
</rules>
</nlog>
In .Net core I had written this:
Logger logger = LogManager.GetCurrentClassLogger();
LogManager.Configuration.Variables["myConnectionstring"]=Setting.connString;
LogManager.ReconfigExistingLoggers();
logger.SetProperty("userID", "UR0001");
logger.SetProperty("Callsite", ex.Error.TargetSite.Name);
logger.LogException(NLog.LogLevel.Error, ex.Error.Message,ex.Error);

Related

.Net Framework 4.8 MVC - ${aspnet-TraceIdentifier} is always empty

In my .Net 4.8 MVC application I'm trying to write logs with NLog. One of the field is traceId - ${aspnet-TraceIdentifier}, which suppose to be supported by NLog.Web.
So I followed the documentation and installed:
NLog v4.7.6
NLog.Extensions.Logging v1.6.5
NLog.Web v4.9.3
I placed my NLog.config in project's directory:
<?xml version="1.0" ?>
<nlog autoReload="true"
xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwExceptions="true"
internalLogLevel="trace"
internalLogFile="c:\test\internal-nlog.txt">
<targets>
<target name="ws" xsi:type="WebService" protocol="JsonPost"
url="https://log-api.com/log/v1">
<parameter name="time" layout="${date}" />
<parameter name="level" layout="${level:upperCase=true}"/>
<parameter name="message" layout="${message}" />
<parameter name="host" layout="${machinename}" />
<parameter name="threadid" layout="${threadid}" />
<parameter name="ActivityId" layout="${activityId}" />
<parameter name="processId" layout="${processId}" />
<parameter name="threadid" layout="${threadid}" />
<parameter name="event-properties" layout="${all-event-properties}" />
<parameter name="exception" layout="${exception}" />
<parameter name="traceId" layout="${aspnet-TraceIdentifier}" />
<parameter name="environment" layout="Production" />
<parameter name="serviceName" layout="company-api2222222" />
<parameter name="session" layout="${aspnet-session}"/>
<parameter name="sessionId" layout="${aspnet-sessionid}"/>
<header name="X-License-Key" layout="${environment:LICENSE_KEY}"/>
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="ws" />
</rules>
</nlog>
According to the documentation, further configuration is not needed:
"Simply install the package. NLog will detect the extension automatically."
So, inside my controller I simply getting current class logger and logging:
NLog.LogManager.GetCurrentClassLogger().Info("Hello World");
But unfortunately, ${aspnet-TraceIdentifier} value is empty, and the worst thing is that I cannot find any documentation about how to make it works.
I tried to put extensions tag above targets in NLog.config file
<extensions>
<add assembly="NLog.Web"/>
</extensions>
and even tried this as well:
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
But nothing changed. Can anyone help? There is something that I am missing? maybe a configuration problem after all?
It's unclear if you're using ASP.NET or ASP.NET Core.
So an answer for both:
ASP.NET (non core)
For ASP.NET you should use <add assembly="NLog.Web"/> and the NLog.Web package
For ASP.NET with IIS needs IIS ETW feature enabled: https://learn.microsoft.com/en-us/iis/configuration/system.webServer/httpTracing/ (IIS7 - Win2008)
internally HttpWorkerRequest.RequestTraceIdentifier will be used.
ASP.NET Core
For ASP.NET Core you should use <add assembly="NLog.Web.AspNetCore"/> and the NLog.Web.AspNetCore package
NLog uses these for the traceindentifier:
ASP.NET Core 3-5: use System.Diagnostics.Activity.Current.Id (default) or HttpContext.TraceIdentifier
ASP.NET Core 1+2: HttpContext.TraceIdentifier
For ASP.NET Core 3-5 you maybe need ignoreActivityId. e.g. ${aspnet-TraceIdentifier:ignoreActivityId=true} - if true - HttpContext.TraceIdentifier will be used instead of System.Diagnostics.Activity.Current.Id

nlog failing on production server

I have setup my asp.Net Core 5 application with Nlog for logging errors on LIVE environment. It has been working smoothly till recently when I realized that the hosting company reconfigured permissions to folders on the server, denying write permissions to some folders.
I started noticing that I was no longer able to upload files to some of the folders I had under www folder in the application.
When I brought their attention to it, they enabled write access to that folder and since then, I can upload files but I also noticed that at about the same time, my error logging stopped working. Locally, my error logging still works but not working on the production server anymore.
Now I wish to find out whether the error logging can be affected by the review of write permissions and how I might be able to troubleshoot the issue further and probably make some reasonable suggestions to the technical support team to help resolve the issue faster.
My Nlog configuration file is as follows
<?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">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore" />
<add assembly="NLog.MailKit" />
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="alllogs" fileName="./logs/all-logs/${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="errorlogs" fileName="./logs/error-logs/${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<!-- Database Logging target -->
<target name="db" xsi:type="Database"
dbHost="hosteserver"
dbDatabase="databasename"
dbUserName="username"
dbPassword="password">
<commandText>
insert into dbo.ErrorLogs (
Logtime, Level, Message, Exception,
Logger
) values (
#TimeLogged, #Level, #Message, #Exception,
#Logger
);
</commandText>
<parameter name="#TimeLogged" layout="${longdate}" />
<parameter name="#Level" layout="${level}" />
<parameter name="#Message" layout="${message}" />
<parameter name="#Exception" layout="${exception:tostring}" />
<parameter name="#Logger" layout="${logger}" />
</target>
<!-- my mailkit target for email notifications on error -->
<target xsi:type="Mail"
name="ErrorMailLogTarget"
subject="Error Occurred on The Application Name"
to="myname#myemail.com"
from="email#mydomain.com"
body="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}"
smtpUserName="email#mydomain.com"
smtpServer="mydomain.com"
smtpPort="587"
timeout="20000"
smtpPassword="email_password"
smtpAuthentication="basic"
skipCertificateValidation="true"
priority="Urgent"
/>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="alllogs" />
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxlevel="Info" final="true" />
<!-- BlackHole without writeTo -->
<logger name="*" minlevel="Error" writeTo="errorlogs" />
<!-- Error Mail notification log -->
<logger name="*" minlevel="Error" writeTo="ErrorMailLogTarget" />
<!-- Database Logging Provision -->
<logger name="*" minlevel="Error" writeTo="db" />
</rules>
</nlog>
I will appreciate any guide to resolve this.
Thank you

NLog database target

I have the following target in nlog.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">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets>
<target name="dbTarget"
xsi:type="Database"
connectionString="Server=SERVER;Database=Log;Trusted_Connection=True;"
commandText="INSERT INTO Logs(LogTime, LogLevel, Message) VALUES (#LogTime, #LogLevel, #Message);">
<!-- Parameters to log -->
<parameter name="#LogTime" layout="${longdate}"/>
<parameter name="#LogLevel" layout="${level}"/>
<parameter name="#Message" layout="${message}"/>
</target>
</targets>
<rules>
<logger name="dbLogger" minlevel="Trace" writeTo="dbTarget" />
</rules>
</nlog>
In code I get my logger like this.
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetLogger("dbLogger");
But it doesn't work. If I add a file rule, the it logs to the file, so my guess is my dbTarget config is wrong.
Try to include a dbProvider attribute in you target tag. Set the dbProvider attribute with the right value which fits to your database. You can find the values here: https://github.com/nlog/NLog/wiki/Database-target#connection-options
Try modifying the connection string:
connectionString="Data Source=SERVER;Initial Catalog=Log;Integrated Security=True;"
dbProvider="System.Data.SqlClient"
Did you try remove the last ";" from the commandText:
<target name="dbTarget"
xsi:type="Database"
connectionString="Server=SERVER;Database=Log;Trusted_Connection=True;"
commandText="INSERT INTO Logs(LogTime, LogLevel, Message) VALUES (#LogTime, #LogLevel, #Message)">

NLog ${identity} and ${windows-identity} saved as "notauth"

I'm working on a C# class library project that is using NLog. NLog is logging to a database. I've set up a console app test project to call the library (the console app has no logging). I have a column in the log table to store the user name of the logged in user running the application.
According to NLog's documentation, that value is stored in either the ${identity} or ${windows-identity} layout renderers. I've tried using both, but when the log writes to the database, the value of the UserName column is notauth::. How can I fix this? My nlog.config file is below.
<?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="false"
internalLogLevel="Off"
internalLogFile="c:\temp\nlog-internal.log"
throwConfigExceptions="true">
<targets>
<target name="db"
xsi:type="Database"
connectionString="Server=ServerName;Database=DatabaseName;Integrated Security=True;">
<commandText>
INSERT INTO Logs.TableName
(
[Level]
, UserName
, CallSite
, [Message]
, Exception
, StackTrace
, Logged
)
VALUES
(
#level
, #userName
, #callSite
, #message
, #exception
, #stackTrace
, #logged
)
</commandText>
<parameter name="#level" layout="${level}" />
<parameter name="#userName" layout="${identity}" />
<parameter name="#callSite" layout="${callsite}" />
<parameter name="#message" layout="${message}" />
<parameter name="#exception" layout="${exception:tostring}" />
<parameter name="#stackTrace" layout="${stacktrace}" />
<parameter name="#logged" layout="${date}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="db" />
</rules>
</nlog>
I think there is something strange in you project. I made a small repo and have the following results:
${identity} shows indeed notauth::, that's correct as I don't authenticate to something - we use this for IIS with forms or windows authentication.
${windows-identity} shows COFFEE-LAKE\Julian - which is correct. "COFFEE-LAKE" is my machine name and Julian is also correct :) note - ${windows-identity} will never render notauth:: - I checked NLog's source
See repo here: https://github.com/304NotModified/nlog-console-notauth
When running, there is a "test1.log" in your "bin/Debug" folder.
note: it has the following 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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<targets>
<target xsi:type="File" name="f"
fileName="${basedir}/test1.log"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}|identity: '${identity}' | windows-identity: '${windows-identity}'" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="f" />
</rules>
</nlog>

How do I configure NLog to write to a database?

I'm trying to get NLog to write to a database, however with my current code it throws an exception when I attempt to debug, the exception is: The type initializer for 'NotifyIcon.Program' threw an exception.
my NLog configuration file code is below, as this seems to be causing the issue as it's the only code I've changed.
<?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">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- add your targets here -->
<target name="database" xsi:type="Database" />
<target xsi:type="Database"
name="String"
dbUserName="Layout"
dbProvider="sqlserver"
useTransactions="false"
connectionStringName="String"
connectionString="Data Source=AC-02\SQLEXPRESS;Initial Catalog=master;Integrated Security=True"
keepConnection="true"
dbDatabase="Layout"
dbPassword="Layout"
dbHost="Layout"
installConnectionString="Layout"
commandText="INSERT INTO Logs (Machine_Name, Username, Logon_Time, Screensaver_On, Screensaver_Off, Logoff_Time, Program_Start) Values #MachineName, #Username, #LogonTime, #Screensaver_On, #Screensaver_Off, #LogoffTime, #ProgramStart "/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="database" />
</rules>
</nlog>
any and all help would be greatly appreciated =]
You seem to be missing the parameters that are to be inserted.
See the examples at http://justinpdavis.blogspot.com/2010/04/logging-to-database-with-nlog.html
The nLog web page doesn't make it very clear that these are required, but if you squint your eyes and read https://github.com/nlog/NLog/wiki/Database-target you should find that they are required.
A simple example,
Config:
<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
<commandText>
INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (#Origin,#Message,#LogLevel,#Date, #OrderId);
</commandText>
<parameter name="#Date" layout="${date}" dbType="DbType.Date"/>
<parameter name="#Origin" layout="${callsite}"/>
<parameter name="#LogLevel" layout="${level}"/>
<parameter name="#message" layout="${message}"/>
<parameter name="#OrderId" layout="${event-properties:MyOrderId}" dbType="DbType.Int32"/> <!-- custom field! Note also the DB Type. Using Logger.WithProperty -->
</target>
Note, NLog 4.6 has also support for DbType - See https://nlog-project.org/2019/03/20/nlog-4-6-is-live.html
U also wrote 2 targets. And also a lot of attributes that u don't need to set. Should just be:
<target name="DbLog" xsi:type="Database" connectionString="YourConStr"
commandText="insert into [blablablabal] (Col1) values (#val1)">
<parameter name="#val1" layout="${level}" /></target>
Something like this. Easy no? :)
It looks your insert string is not in the right format? You are missing () around the parameters list.
commandText="INSERT INTO Logs (Machine_Name, Username, Logon_Time, Screensaver_On, Screensaver_Off, Logoff_Time, Program_Start) Values (#MachineName, #Username, #LogonTime, #Screensaver_On, #Screensaver_Off, #LogoffTime, #ProgramStart) "

Categories