How do I configure NLog to write to a database? - c#

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) "

Related

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

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);

How to log single SQL table using NLog in C#?

I am trying to log the single table using NLog bypassing parameter values into each column using NLog. But somehow I couldn't able to log in to the SQL table.
I tried by passing values by passing code like this and added the targets and rules in web.config.
Code in the class
private static Logger _logger;
public CustomToken()
{
_logger = LogManager.GetLogger("apiUsageLogger");
}
_logger.Info("{clientname}", "test");
_logger.Info($"clientusername", "test");
_logger.Info($"route", "test");
_logger.Info($"parameters", "test");
_logger.Info($"isuserauthenticated", 1);
In the web.config
<target name="apiUsageLog" xsi:type="Database" connectionStringName="connStringName">
<commandtext>
INSERT INTO Table
(ClientName, ClientUserName, Route, Parameters, IsUserAuthenticated, Machine)
VALUES
(#clientname, #clientusername, #route, #parameters, #isuserauthenticated, #machine)
</commandtext>
<parameter name="#clientname" layout="${clientname}" />
<parameter name="#clientusername" layout="${clientusername}" />
<parameter name="#route" layout="${route}" />
<parameter name="#parameters" layout="${parameters}" />
<parameter name="#isuserauthenticated" layout="${isuserauthenticated}" />
<parameter name="#machine" layout="${machinename}" />
</target>
</targets>
<rules>
<<logger name="apiUsageLogger" minlevel="Info" writeTo="apiUsageLog" />
</rules>
Somehow data is not getting populated into the table.
Is there a way I can able to achieve in populating the data into appropriate columns? NLog is the right way of doing it?
Not sure if it's clear, but with database target one log message will be one record in the database. I would recommend to read the tutorial. Also in this case the database target options are good to check.
Your config isn't working as ${clientusername} doesn't exist in NLog.
I will show 3 examples, hope that make things clear
Example 1: simple logs to database target
Logger call:
logger.Info("my info message");
config:
<target name="apiUsageLog" xsi:type="Database" connectionStringName="connStringName">
<commandtext>
INSERT INTO Table
(message, machinename)
VALUES
(#message, #machinenameParam)
</commandtext>
<parameter name="#messageParam" layout="${message}" /> <!-- this will be "my info message"-->
<parameter name="#machinenameParam" layout="${machinename}" /> <!-- defined in NLog, see https://nlog-project.org/config/?tab=layout-renderers-->
</target>
</targets>
This will create a log record in the database with my info message and the machine name.
Example 2: with custom properties:
I will use structured logging here. See structured logging
Logger call:
logger.Info("my info message with {Property1}", "value1");
config:
<target name="apiUsageLog" xsi:type="Database" connectionStringName="connStringName">
<commandtext>
INSERT INTO Table
(message, machinename, property1)
VALUES
(#message, #machinenameParam, #propertyParam1)
</commandtext>
<parameter name="#messageParam" layout="${message}" /> <!-- this will be "my info message"-->
<parameter name="#machinenameParam" layout="${machinename}" /> <!-- defined in NLog, see https://nlog-project.org/config/?tab=layout-renderers-->
<parameter name="#propertyParam1" layout="${event-properties:Property1}" /> <!-- this will be "value1" -->
</target>
</targets>
This will create a log record in the database with my info message with "Value1" , the machine name and the custom property with "value1".
Example 3: custom properties, not all in the message
This combines structured logging and WithProperty. You need at least NLog 4.6.3 for this.
Logger call:
logger.WithProperty("Property2", "value2")
.Info("my info message {Property1}", "value1");
config:
<target name="apiUsageLog" xsi:type="Database" connectionStringName="connStringName">
<commandtext>
INSERT INTO Table
(message, machinename, property1, property2)
VALUES
(#message, #machinenameParam, #propertyParam2)
</commandtext>
<parameter name="#messageParam" layout="${message}" /> <!-- this will be: my info message with "value1"-->
<parameter name="#machinenameParam" layout="${machinename}" /> <!-- defined in NLog, see https://nlog-project.org/config/?tab=layout-renderers-->
<parameter name="#propertyParam1" layout="${event-properties:Property1}" /> <!-- this will be "value1" -->
<parameter name="#propertyParam2" layout="${event-properties:Property2}" /> <!-- this will be "value2" -->
</target>
</targets>
This will create a log record in the database with my info message with "Value1" , the machine name and the custom properties "value1" and "value2"
Note, now "value1" is in the message and "value2" isn't.

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>

Conditionally execute NLog target statement

I have one Enum class given below
public enum ScanStatus
{
Success,
Failure,
Exception
}
From .cs file I have passing the value of Exception to Nlog.config file using code
GlobalDiagnosticsContext.Set("ExceptionStatus", Convert.ToString((int)ScanStatus.Exception));
In nlog.config, i have configured to log the message in database using below code.
<target name="database" xsi:type="Database" keepConnection="true"
dbProvider="System.Data.SqlClient"
connectionStringName="PaymentScan"
commandText="INSERT INTO [dbo].[LoggingTrace] (PaymentId, ExceptionStatus, TraceDetails) VALUES (#ItemId, #ExceptionStatus, #Message)">
<parameter name="#message" layout="${message}"/>
<parameter name="#ItemId" layout="${gdc:ItemId}"/>
<!-- custom field! -->
<parameter name="#ExceptionStatus" layout="${gdc:ExceptionStatus}"/>
<!-- custom field! -->
</target>
I want this target statement should execute only when any exception occurs in the code. To handle this, I have written the rules given below
<rules>
<logger name="*" minlevel="Info" writeTo="database">
<filters>
<when condition="equals('${gdc:ExceptionStatus}', '2')" action="Log" />
</filters>
</logger></rules>
I am facing issue that When exception does not occurs, the target is getting executed, means equals statement written in rules in not working.
Could any body let me know the solution for this.

Categories