Config nLog .NET Core 3.1, missing debug messages - c#

I have looked at numerous configurations for nLog in .net core, all is working, except that I cannot get a debug message to log. If I write an information message or error message those work just fine. So this seems like a logging level problem, but try as I might I can't seem to get the level low enough to write out debug messages.
I have also looked at this: Missing trace\debug logs in ASP.NET Core 3?
Nlog.Web.AspNetCore 4.11
.Net Core 3.1
Here is my configuration:
nothing logging specific in startup.cs
program.sc
public static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog();
appsettings.json
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
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"
throwConfigExceptions="true"
internalLogLevel="info"
internalLogFile="c:\temp\Nlog.log">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets>
<target name="database" xsi:type="Database" connectionString="${appsettings:name=ConnectionStrings.applog}" >
<commandText>
INSERT INTO [NLog] (
[ApplicationName],
[AppUserIdentity],
[LogDate] ,
[LogLevel] ,
[LogSource],
[LogAssembly] ,
[LogMessage] ,
[MachineName] ,
[DomainUser],
[CallSite],
[LogThread] ,
[LogException] ,
[ClientIp]
)
VALUES (
#ApplicationName,
#AppUserIdentity,
#LogDate ,
#LogLevel ,
#LogSource,
#LogAssembly,
#LogMessage ,
#MachineName ,
#DomainUser ,
#CallSite ,
#LogThread ,
#LogException,
#ClientIp
);
</commandText>
<parameter name="#ApplicationName" layout="${appsettings:name=AppName:default=Missing-Config}" />
<parameter name="#AppUserIdentity" layout="${aspnet-user-identity}" />
<parameter name="#LogDate" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}" />
<parameter name="#LogLevel" layout="${level}" />
<parameter name="#LogSource" layout="${logger} " />
<parameter name="#LogAssembly" layout="${assembly-version}" />
<parameter name="#LogMessage" layout="${message}" />
<parameter name="#MachineName" layout="${machinename}" />
<parameter name="#DomainUser" layout="${windows-identity:domain=true}" />
<parameter name="#CallSite" layout="${callsite}" />
<parameter name="#LogThread" layout="${threadid}" />
<parameter name="#LogException" layout="${exception}" />
<parameter name="#ClientIp" layout="${aspnet-request-ip}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" maxlevel="Error" final="true" writeTo="database" />
</rules>
</nlog>
injected into a service. This call will not log, but if it were _logger.LogInformation("xx"), it will log. This ILogger reference is Microsoft.Extensions.Logging.ILogger
public TaxCalculationService(IUnderwritingRepository repository, ILogger<TaxCalculationService> logger)
{
_repository = repository;
_logger = logger;
}
public TaxCalculationResponseDto CalculateTaxes(TaxCalculationRequestDto request)
{
_logger.LogDebug("calculateTaxes request: " + JsonConvert.SerializeObject(request));

Please try to upgrade to NLog.Web.AspNetCore v4.12.0, and then change UseNLog() to use RemoveLoggerFactoryFilter = true like this:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog(new NLogAspNetCoreOptions() { RemoveLoggerFactoryFilter = true });
See also: https://github.com/NLog/NLog.Extensions.Logging/pull/482
You might want to update the NLog-LoggingRules to ignore noise from Microsoft-Loggers:
<rules>
<!-- Block output from noisy loggers -->
<logger name="Microsoft.*" maxlevel="Info" final="true" />
<logger name="System.Net.Http.*" maxlevel="Info" final="true" />
<!-- Write the good stuff to the databse -->
<logger name="*" minlevel="Debug" writeTo="database" />
</rules>

Related

Struggling to add custom NLog layout renderer in .Net 6 Web API

I have a .Net 6 Web API. I use NLog for my logging. I'm trying to log a custom field with NLog, but I am struggling to get it to work. I'm following this sample: https://nlog-project.org/2015/06/30/extending-nlog-is-easy.html.
So my nlog.config currently looks like this (I'm just showing the db target as that's the only relevant part I believe):
<target name="db"
xsi:type="Database"
dbProvider="MySqlConnector.MySqlConnection, MySqlConnector"
connectionString="some_connection_string"
commandType="StoredProcedure"
commandText="`abc`.`InsertLog`"
>
<parameter name="machineName" layout="${machinename}" />
<parameter name="logged" layout="${date}" />
<parameter name="logLevel" layout="${level}" />
<parameter name="message" layout="${message}" />
<parameter name="logger" layout="${logger}" />
<parameter name="properties" layout="${all-event-properties:separator=|}" />
<parameter name="callsite" layout="${callsite:fileName:true}" />
<parameter name="exception" layout="${exception:tostring}" />
<parameter name="callsiteLineNumber" layout="${callsite-linenumber}" />
<parameter name="stackTrace" layout="${stacktrace}" />
</target>
The db target basically calls a MySql Stored Proc.
Now I'd like to save an extra, custom field, so I add this line just before the closing tag:
<parameter name="newField" layout="${newField}" />
( I also added the relevant field to the MySql Stored Proc)
Then I create a new class, inheriting from LayoutRenderer:
using NLog;
using NLog.LayoutRenderers;
using System;
using System.Text;
namespace PropWorx.API
{
[LayoutRenderer("newField")]
public class NLogLayoutRenderer : LayoutRenderer
{
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append("test");
}
}
}
I'm not sure if that's all I need? Because it's not working. I get this error when I try to start up the API:
NLogConfigurationException: Error when setting property 'Layout' on
DatabaseParameterInfo
ArgumentException: LayoutRenderer cannot be found: 'newField'
This happens on the very fist line of my Program.cs file:
public static void Main(string[] args)
{
// Exception is thrown on the following line:
NLog.Logger logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Info("Init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
NLog.LogManager.Shutdown();
}
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog();
}
Any ideas where I;m going wrong? Thanks
Replace this line:
NLog.Logger logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
With this line:
NLog.Logger logger = NLog.LogManager.Setup().SetupExtensions(s =>
s.RegisterLayoutRenderer<PropWorx.API.NLogLayoutRenderer>("newField")
).LoadConfigurationFromAppSettings().GetCurrentClassLogger();
See also: https://github.com/NLog/NLog/wiki/Register-your-custom-component#register-nlog-extensions-from-assembly-at-runtime
See also: https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-6#3-update-programcs

Custom logging with NLog on database

I have some problem with NLog. According to here that said
If you want custom layout properties (NLog calls them layout renderers) you can use the EventProperties Layout Renderer.
I wrote some config :
<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="on" internalLogFile="c:\temp\nlog-internal.log">
<targets>
<!-- database target -->
<target name="databaseauthentication"
xsi:type="Database"
connectionString="Data Source = [....]; Initial Catalog = [....]; User Id = [....]; Password = [....]"
commandText="exec dbo.InsertAuthentication
#company,
#firstname,
#lastname,
#ip,
#pcname,
#additionalInfo">
<parameter name="#company" layout="${event-properties:item=companyValue}" />
<parameter name="#firstname" layout="${event-properties:item=firstnameValue}" />
<parameter name="#lastname" layout="${event-properties:item=lastnameValue}" />
<parameter name="#ip" layout="${event-properties:item=ipValue}" />
<parameter name="#pcname" layout="${event-properties:item=pcnameValue}" />
<parameter name="#additionalInfo" layout="${event-properties:item=additionalInfoValue}" />
</target>
</targets>
<rules>
<logger levels="Info" name="asyncdatabaseauthenticationLogger" writeTo="asyncdatabaseauthentication"/>
<logger levels="Info" name="databaseauthenticationLogger" writeTo="databaseauthentication"/>
</rules>
</nlog>
And used that like :
public static void SendLogin()
{
var eventInfo = new LogEventInfo(LogLevel.Info, databaseAuthenticateLogger.Name, "Message");
eventInfo.Properties["firstnameValue"] = "My Fist Name;
eventInfo.Properties["lastnameValue"] = "My Last Name";
eventInfo.Properties["companyValue"] = "My Company";
eventInfo.Properties["ipValue"] = "IP";
eventInfo.Properties["pcnameValue"] = "PC Name";
eventInfo.Properties["additionalInfoValue"] = "Login";
databaseAuthenticateLogger.Log(eventInfo);
}
But this code don't work. Can anyone tell me where is my mistake?
The Above code is true, But We need to add this part in c# code :
static Logger databaseAuthenticateLogger = LogManager.GetLogger("databaseauthenticationLogger");
static Logger asyncdatabaseAuthenticateLogger = LogManager.GetLogger("asyncdatabaseauthenticationLogger");
Everythings works good.

How to change the NLog layout at run time?

I created the 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"
throwExceptions="false"
throwConfigExceptions="true"> <!--make NLog complain, when something is wrong with the configuration-->
<targets>
<target name="logfile" xsi:type="File"
fileName="${basedir}/Logs/Log_${shortdate}.txt"
layout="[${longdate}] [${uppercase:${level}}] ${message} ${exception:format=tostring}"
/>
<target name="logconsole" xsi:type="ColoredConsole"
layout="[${longdate}] ${uppercase:${level}}: ${message} ${exception:format=tostring}"
/>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
When I call logger.Info("Hello World"); I get an output both in the console and the file:
[2018-03-17 15:34:24.2843] INFO: Hello World
Which is fine.
Now in some cases I do not want to display the date-time part, and I want to display it only in the console.
How would I do that with NLog?
A pseudo solution I would want is:
logger.Info("Hello World", writeTo: "logconsole", layout: "[${uppercase:${level}}] ${message}");
I tried adding a new taget
<target name="logconsole_simple" xsi:type="ColoredConsole"
layout="${uppercase:${level}}: ${message} ${exception:format=tostring}"/>
and new rule:
<logger name="logconsole_simple" level="Info" writeTo="logconsole_simple" />
And call it like:
logger.Log(LogEventInfo.Create(LogLevel.Info, "logconsole_simple", "simple message!"));
But it still displays the date-time part and logs it to the file also (which I don't want).
How to fix this?
Add a target and rule for your special case and reference your loggers by name.
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"
throwExceptions="false"
throwConfigExceptions="true"><!--make NLog complain, when something is wrong with the configuration-->
<targets>
<target name="logfile" xsi:type="File"
fileName="${basedir}/Logs/Log_${shortdate}.txt"
layout="[${longdate}] [${uppercase:${level}}] ${message} ${exception:format=tostring}"
/>
<target name="logconsole_default" xsi:type="Console"
layout="[${longdate}] ${uppercase:${level}}: ${message} ${exception:format=tostring}"
/>
<target name="logconsole_other" xsi:type="Console"
layout="${uppercase:${level}}: ${message} ${exception:format=tostring}"
/>
</targets>
<rules>
<logger name="default" minlevel="Debug" writeTo="logfile" />
<logger name="default" minlevel="Info" writeTo="logconsole_default" />
<logger name="other" minlevel="Info" writeTo="logconsole_other" />
</rules>
</nlog>
Usage:
internal class Program
{
private static readonly Logger DefaultLogger = LogManager.GetLogger("default");
private static readonly Logger OtherLogger = LogManager.GetLogger("other");
private static void Main(string[] args)
{
for (var i = 0; i < 2; i++)
{
if (i % 2 == 0)
{
DefaultLogger.Info("normal log message");
}
else
{
OtherLogger.Info("special case");
}
}
}
}
EDIT: If you really want to do it in code by modifying your existing target and rule, you can (this will work with the config from your original post):
using System.Linq;
using NLog;
using NLog.Layouts;
using NLog.Targets;
internal class Program
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static void Main(string[] args)
{
for (var i = 0; i < 2; i++)
{
if (i % 2 == 0)
{
Logger.Info("normal log message");
}
else
{
// reconfigure
var consoleTarget = LogManager.Configuration.FindTargetByName<ColoredConsoleTarget>("logconsole");
var oldLayout = consoleTarget.Layout;
consoleTarget.Layout = new SimpleLayout { Text = "${uppercase:${level}}: ${message} ${exception:format=tostring}" };
var fileRule = LogManager.Configuration.LoggingRules.Single(r => r.Targets.Any(t => t.Name == "logfile"));
LogManager.Configuration.LoggingRules.Remove(fileRule);
LogManager.Configuration.Reload();
Logger.Info("special case");
// replace originals
consoleTarget.Layout = oldLayout;
LogManager.Configuration.LoggingRules.Add(fileRule);
LogManager.Configuration.Reload();
}
}
}
}

Cannot get NLog custom target to work

I am really struggling to get a basic custom target working with NLog.
Program.cs
using NLog;
using NLog.Targets;
namespace NLogTestConsole
{
class Program
{
private static Logger logger = null;
static Program()
{
logger = LogManager.GetCurrentClassLogger();
Target.Register<NLogTestConsole.Gerald>("Gerald");
}
static void Main(string[] args)
{
logger.Trace("Sample trace message");
logger.Debug("Sample debug message");
logger.Info("Sample informational message");
logger.Warn("Sample warning message");
logger.Error("Sample error message");
logger.Fatal("Sample fatal error message");
}
}
}
NLogCustomTarget.cs
using NLog;
using NLog.Targets;
namespace NLogTestConsole
{
[Target("Gerald")]
public sealed class Gerald : TargetWithLayout
{
public Gerald()
{
// this.Host = "localhost";
}
//[RequiredParameter]
//public string Host { get; set; }
protected override void Write(LogEventInfo logEvent)
{
// Breakpoint here never gets hit
string logMessage = this.Layout.Render(logEvent);
System.Console.WriteLine("MYCUSTOMMSG: " + logMessage);
}
private void SendTheMessageToRemoteHost(string host, string message)
{
// TODO - write me
}
}
}
NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog autoReload="true"
throwExceptions="false"
internalLogLevel="Off"
internalLogFile="c:\temp\nlog-internal.log">
<!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables -->
<variable name="myvar" value="myvalue"/>
<!-- See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs. -->
<targets>
<!-- add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers. -->
<!-- Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" /> -->
<target name="logfile" type="File" fileName="file.txt" />
<target name="console" type="Console" />
<target name="debugger" type="Debugger"/>
<target name="Gerald" type="Gerald"/>
</targets>
<rules>
<!-- Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" /> -->
<logger name="*" minlevel="Trace" writeTo="logfile" />
<logger name="*" minlevel="Info" writeTo="console" />
<logger name="*" minlevel="Trace" writeTo="debugger" />
<logger name="*" minlevel="Trace" writeTo="Gerald" />
</rules>
</nlog>
If I comment out the "Gerald" target I get logging to file, console, and debug output. With that line there, nothing works
What have I got wrong?
Thanks,
Adam.
Enable the internal log and see the error in c:\temp\nlog-internal.log:
internalLogLevel="Warn"
You need to fix your code so that the logger is created after you register your target with NLog. Please see highlighted and annotated lines of code below:
using NLog;
using NLog.Targets;
namespace NLogTestConsole
{
class Program
{
private static Logger logger = null;
static Program()
{
// **********************************************************
// the next two code lines are swapped around,
// now the custom logger will work...
// **********************************************************
Target.Register<NLogTestConsole.Gerald>("Gerald");
logger = LogManager.GetCurrentClassLogger();
}
static void Main(string[] args)
{
logger.Trace("Sample trace message");
logger.Debug("Sample debug message");
logger.Info("Sample informational message");
logger.Warn("Sample warning message");
logger.Error("Sample error message");
logger.Fatal("Sample fatal error message");
}
}
}

Logging with NLog and runtime parameters to Database

I am trying to log some info to database with NLog, but I can retrieve some DB parameters only at runtime. Tried few solutions, but unsuccessfully.
There 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"
autoReload="true">
<variable name="sqlDate" value="[${date:format=yyyy-MM-dd HH\:mm\:ss\.fff}]"/>
<targets>
<target name="dataBase"
xsi:type="Database"
dbProvider="System.Data.SqlClient"
connectionString="${gdc:item=myConnectionstring}"
dbDatabase="${gdc:item=myDataBase}">
<commandText>
INSERT INTO [TABLE_NAME]([COL1], [COL2] )
VALUES(#val1, #val2)
</commandText>
<parameter name="#val1" layout="${event-context:item=val1}"/>
<parameter name="#val2" layout="${event-context:item=val2}"/>
</target>
</targets>
<rules>
<logger name="_dataBase" levels="Info" writeTo="dataBase" final="true" />
</rules>
</nlog>
And there is my .NET C# code:
public static class Log
{
private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
private static Config _config = LoadConfig();
public static void Info(string val1, string val2)
{
DatabaseTarget databaseTarget = (NLog.Targets.DatabaseTarget)NLog.LogManager.Configuration.FindTargetByName("dataBase");
databaseTarget.ConnectionString = _config.ConnectString;
databaseTarget.DBDatabase = _config.DBName;
NLog.LogManager.ReconfigExistingLoggers();
LogEventInfo info = new LogEventInfo(LogLevel.Info, "_dataBase", "Test_message");
info.Properties["val1"] = val1;
info.Properties["val2"] = val2;
_logger.Log(info);
}
}
And it just do nothing: not crashing, not writing any data to DB. Here is my internal NLog log: http://pastebin.com/0tLi9zJ1
How can I fix this?
P.S. Sorry for my last try to ask this question, it looks like I forgot to put to it some necessary information.
So, the working code is:
<?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">
<variable name="sqlDate" value="${date:format=yyyy-MM-dd HH\:mm\:ss\.fff}"/>
<targets>
<target name="dataBase"
xsi:type="Database"
dbProvider="System.Data.SqlClient"
connectionString="${gdc:item=myConnectionString}"
dbDatabase="${gdc:item=myDataBase}">
<commandText>
INSERT INTO [TABLE_NAME]([COL1], [COL2] )
VALUES(#val1, #val2)
</commandText>
<parameter name="#val1" layout="${event-context:item=val1}"/>
<parameter name="#val2" layout="${event-context:item=val2}"/>
</target>
</targets>
<rules>
<logger name="_dataBase" levels="Info" writeTo="dataBase" final="true" />
</rules>
</nlog>
public static class Log
{
private static Config _config = LoadConfig();
public static void Info(string val1, string val2)
{
NLog.Logger logger = NLog.LogManager.GetLogger("_dataBase");
GlobalDiagnosticsContext.Set("myConnectionString", _config.ConnectString);
GlobalDiagnosticsContext.Set("myDataBase", _config.DBName);
LogEventInfo info = new LogEventInfo(LogLevel.Info, "_dataBase", "Test_message");
info.Properties["val1"] = val1;
info.Properties["val2"] = val2;
logger.Log(info);
}
}

Categories