In our ASP.NET, ASP.NET Core, and command-line programs we have been using NLog for many years.
In an ASP.NET Core app targeting net6.0, the following configuration works when using NLog version 4.7.15 and NLog.Extensions.Hosting version 1.7.5. When upgrading both packages to version 5.0.x (e.g. the latest available version, 5.0.4), logging stops working. Nothing is logged: The log file remains empty.
The application is supposed to use the Microsoft.Extensions.Logging filters as defined in appsettings.json - see below.
I've read NLog 5.0 - List of major changes
many times and tried to workaround the breaking changes. Unfortunately I haven't been able to get it to work.
Our setup is below, hopefully someone is able to help. Thank you!
ASP.NET Core app targeting net6.0, using NLog version 4.7.15 and NLog.Extensions.Hosting version 1.7.5
As soon as I upgrade to NLog version 5.0.4 and NLog.Extensions.Hosting version 5.0.4, the logging breaks. Nothing is logged any more.
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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd http://nlog-project.org/schemas/NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off"
internalLogFile="D:\Logs\StevenVolckaert.WebService\nlog-internal.log">
<!-- Docs # https://github.com/nlog/nlog/wiki/Configuration-file -->
<!-- ASP.NET Core examples # https://github.com/akovac35/Logging.Samples -->
<extensions>
<add assembly="NLog.Extensions.Hosting" />
</extensions>
<!-- ConfigSetting Layout Renderer # https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer -->
<variable name="ApplicationName" value="${configsetting:item=ApplicationName:default=application}" />
<variable name="BuildNumber" value="${configsetting:item=BuildNumber:default=undefined}" />
<variable name="EnvironmentName" value="${configsetting:item=EnvironmentName:default=undefined}" />
<variable name="LogDirectory" value="${whenEmpty:whenEmpty=${basedir}logs:inner=${configsetting:item=NLog.LogDirectory}}" />
<!-- https://github.com/nlog/nlog/wiki/Configuration-file#targets -->
<targets>
<target
xsi:type="Console"
name="Console"
layout="${longdate} ${threadid:padding=2} ${uppercase:${level:padding=5}} ${logger} ${message} ${exception:format=toString}">
</target>
<target
xsi:type="File"
name="LogFile"
fileName="${var:LogDirectory}\${var:ApplicationName}.log"
layout="${longdate} ${threadid:padding=2} ${uppercase:${level:padding=5}} ${logger} ${message} ${exception:format=toString}"
archiveEvery="Day"
archiveFileName="${var:LogDirectory}\Archive\{#}.${var:ApplicationName}.log"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
maxArchiveDays="90">
</target>
</targets>
<!-- https://github.com/nlog/nlog/wiki/Configuration-file#rules -->
<rules>
<logger name="*" minlevel="Trace" writeTo="Console,LogFile" />
</rules>
</nlog>
appsettings.json
{
"ApplicationName": "StevenVolckaert.WebService",
"BuildNumber": null,
"ConnectionStrings": {
"DefaultDatabaseConnection": ""
},
"EnvironmentName": "Local",
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"NLog": {
"LogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
}
}
Program.cs
using NLog.Extensions.Logging;
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddLogging(loggingBuilder =>
{
loggingBuilder
.ClearProviders()
.SetMinimumLevel(LogLevel.Trace)
.AddConfiguration(builder.Configuration.GetSection("Logging"))
.AddNLog(builder.Configuration, new NLogProviderOptions { RemoveLoggerFactoryFilter = false });
});
// code removed for brevity
var app = builder.Build();
// code removed for brevity
app.Run();
}
I've tried adding the filters element to the logger rule, specifying defaultAction="Log", but this doesn't make a difference: Still no output in the logging.
<rules>
<logger name="*" minlevel="Trace" writeTo="Console,LogFile">
<filters defaultAction="Log" />
</logger>
</rules>
Think the issue is caused by this new default-value:
NLogProviderOptions.LoggingConfigurationSectionName = "NLog"
The change in default-value causes the "NLog"-section to become reserved, and intended for having NLog.config in appsettings.json. This works together with SchemaStore that provides basic-intellisense when editing the now reserved "NLog"-section.
This probably causes NLog.Extensions.Logging to lookup the "NLog"-section in the appsettings.json where it finds this:
{
"NLog": {
"LogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
}
}
After having "loaded" this empty NLog-configuration, then it skips further attempts and doesn't load your NLog.config-file.
I suggest that you remove the "NLog"-section and change it into this (And updates NLog.config to ${configsetting:NLogDirectory}):
{
"NLogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
}
Sorry about the bad experience, but it was done to make NLog.config in appsettings.json work out of the box (Making it closer to a first class citizen).
P.S Consider updating your program.cs like this (But I encourage that you remove RemoveLoggerFactoryFilter = false and instead make use of NLog finalMinLevel):
var builder = WebApplication.CreateBuilder(args);
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
builder.Host.UseNLog(new NLogProviderOptions { RemoveLoggerFactoryFilter = false });
var app = builder.Build();
Related
I just finished struggling with a generic error in AspNetCore3.1. The error simply reads this:
2019-12-11 21:52:46.6862 Microsoft.AspNetCore.Server.Kestrel
Connection id "0HLRUMQV9RNJI", Request id "0HLRUMQV9RNJI:00000001": An
unhandled exception was thrown by the application.
After much pain, I found that it was because I missing a registration of a service:
public void ConfigureServices(IServiceCollection services)
{
// This service was missing
services.AddTransient<IThingService, ThingService>();
services.AddControllers();
}
So, now, I'm on a quest to find out why I didn't get any details on what the problem was. I created a new Core 3.1 app from the Visual Studio templates. I installed NLog.Web.AspNetCore and added an 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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="true"
internalLogLevel="Off" internalLogFile="c:\temp\logs\nlog-internal.log">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets async="true">
<target xsi:type="ColoredConsole" name="c" layout="${longdate} ${logger} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="c" />
</rules>
</nlog>
AppSettings:
{
// I removed the logging section completely so that NLOG can control log levels
"AllowedHosts": "*"
}
I also added the following code to program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseIISIntegration()
.ConfigureLogging((hostingContext, loggingBuilder) =>
{
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseStartup<Startup>()
.UseNLog();
});
}
So then, I removed the registration of IThingService, and I started getting the same generic, useless error:
"2019-12-11 21:52:46.6862 Microsoft.AspNetCore.Server.Kestrel
Connection id "0HLRUMQV9RNJI", Request id "0HLRUMQV9RNJI:00000001": An
unhandled exception was thrown by the application."
After some tinkering, I found that I commented out the line in program.cs, "loggingBuilder.ClearProviders();" I started getting actual useful error messages:
System.InvalidOperationException: Unable to resolve service for type
'WebApplication3.Controllers.IThingService' while attempting to
activate 'WebApplication3.Controllers.WeatherForecastController'.
But, it's not NLog doing the logging, it's the default Core 3 logging.
Setup instructions for NLog can be found here: https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-3
So, now for the question, why does ClearProviders() make nlog work, but lose the details in my error messages? It seems to only be logs that would take place down in the pipeline, not at the controller/domain level.
I think the special detail you are looking for is ${exception:format=tostring}. Your current layout is this:
<target xsi:type="ColoredConsole" name="c" layout="${longdate} ${logger} ${message}" />
Try changing into this:
<target xsi:type="ColoredConsole" name="c" layout="${longdate} ${logger} ${message}${exception:format=tostring}" />
You might also consider including ${level} in Layout (Unless coloring is enough).
For my console application , I want to write all the logs to custom event source under Application and Services Logs under separate section MyEventSourceName.
I tried to use NLog.Etw, but seems nothing appears. How to do this?
<?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">
<extensions>
<add assembly="NLog.Etw" />
</extensions>
<targets async="true">
<target xsi:type="EtwEventSource"
name="eetw"
providerName="MyEventSourceName"
taskName="${level}"
layout="${message}">
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="eetw" />
</rules>
class Program
{
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
logger.Info("New person created with name {0}");
}
}
You could use the eventlog target:
For example:
<target xsi:type="EventLog"
name="eventlog"
source="MyEventSourceName"
log="MyEventSourceLogName"
layout ="${message}${newline}${exception:format=ToString}"/>
See docs
The target supports .NET3.5+ and .NET Standard 2.0. For NetStandard 2.0 use the NLog.WindowsEventLog package.
I have the following nlog.config file in ASP.NET Core 2.1 project. However, it's logging messages from every logger (including Microsoft logger) to console.
<?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="Error"
internalLogFile="${specialfolder:folder=UserProfile}\nlog\internal-nlog.txt">
<variable name="fullLayout" value="${shortdate} [${uppercase:${level}}] ${logger}: ${message} ${exception:format=tostring} url: ${aspnet-request-url}" />
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write to console -->
<target name="console" xsi:type="ColoredConsole" layout="${fullLayout}" />
<!-- write to file -->
<target xsi:type="File"
name="allfile"
fileName="${defaultDirectory}/test-api-all.log"
archiveEvery="Day"
archiveFileName="${defaultDirectory}/test-api-all-${#}.log"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
maxArchiveFiles="5"
layout="${fullLayout}" />
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
<target xsi:type="File"
name="ownFile-web"
fileName="${defaultDirectory}/test-api-app.log"
archiveEvery="Day"
archiveFileName="${defaultDirectory}/test-api-app-${#}.log"
archiveNumbering="Date"
archiveDateFormat="yyyy-MM-dd"
maxArchiveFiles="5"
layout="${fullLayout}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="console" />
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxLevel="Info" final="true" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
I do not have any logging settings in appsettings.json files. All logger configuration in in nlog.config. In the Program.cs, I'm registering NLog like:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.ClearProviders())
.UseNLog()
.Build();
How can I filter out Microsoft logs?
EDIT:
Above configuration started working without a problem the next day without me making any changes :O
Maybe this will work:
<!-- rules to map from logger name to target -->
<rules>
<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxLevel="Info" final="true" />
<logger name="*" minlevel="Trace" writeTo="console" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
The order of the logging rules are important, as the rules are matched from the top. See also https://github.com/NLog/NLog/wiki/Configuration-file#rules
The order of your logging rules seems to be correct. I suggest trying to double check if your updated nlog.config file is being copied to the build directory (e.g. \bin\Debug\netcoreapp2.1\nlog.config)
I kind of encountered the same issue, but found out that debugging using Visual Studio, it sometimes doesn't really copy the nlog.config file to your build directory. So the solution is to Clean the project first, then Build, and finally Debug.
I am writing a asp.net core app using NLog.Logging.Extensions to provide logging.
Log Registration:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
loggerFactory.AddNLog();
loggerFactory.ConfigureNLog("nlog.config");
loggerFactory.AddConsole();
loggerFactory.AddDebug();
app.UseMvc();
}
I am getting log output, however it doesn't match the format of my logging Layout defined in the .config file, and it doesn't show anything below information (but again, it is configured to show trace and above in the config file).
Is anyone able to shed any light as to why this may be occurring?
nlog.config:
<?xml version="1.0" encoding="utf-8"?>
<nlog>
<variable name="Layout" value="${longdate} ${level:upperCase=true} ${message} (${callsite:includSourcePath=true})${newline}${exception:format=ToString}"/>
<targets>
<target name="debugger" type="Debugger" layout="${Layout}" />
<target name="console" type="ColoredConsole" layout="${Layout}" detectConsoleAvailable="False"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="debugger,console" />
</rules>
</nlog>
Example Log Output:
Hosting environment: Development
Content root path: /Users/###/dev/###/Services/src/app/###/###
Now listening on: http://localhost:8888 Application started.
Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:8888/State
info: ###.###.###[0]
Building ### instance.
There are several problems here.
1. You get the log output because you've attached default .NET Core loggers:
loggerFactory.AddConsole();
loggerFactory.AddDebug();
And this is why the output doesn't match the format of your Layout. Do not add the default loggers if you are going to use only NLog. Then, keep these two lines below:
loggerFactory.AddNLog();
loggerFactory.ConfigureNLog("nlog.config");
2. NLog config is broken. <add assembly="NLog.Web.AspNetCore"/> is missing. Moreover, it looks like the Debugger target is breaking something in NLog.
There is a fully-workable nlog.config 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">
<!-- Load the ASP.NET Core plugin -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="Layout"
value="${longdate}|${level:uppercase=true}|${logger}|${message}"/>
<targets>
<target name="console"
type="ColoredConsole"
layout="${Layout}"
detectConsoleAvailable="False"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</nlog>
Additional examples: https://github.com/NLog/NLog.Web/wiki/Getting-started-with-ASP.NET-Core-(project.json)
In my code I have some info messages like logger.Log("dwewe") and logger.Debug("ddddf").
The problem is that the Debug messages are not being written even when I debug in VS.
<?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"
internalLogLevel="Trace"
internalLogFile="c:\nlog-app.log"
autoReload="false"
internalLogToConsole="true">
<!--
See http://nlog-project.org/wiki/Configuration_file
for information on customizing logging rules and outputs.
-->
<targets>
<!-- file targets -->
<target name="asyncFile" xsi:type="AsyncWrapper">
<target xsi:type="File" name="f" fileName="${basedir}/Logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message} ${event-context:item=error-source} ${event-context:item=error-class} ${event-context:item=error-method} ${event-context:item=error-message} ${event-context:item=inner-error-message} ${event-context:item=stack-trace}"/>
</target>
<!-- database targets -->
<target name="database" xsi:type="Database" keepConnection="true" useTransactions="true"
dbProvider="System.Data.SqlClient"
connectionString="data source=XXXXXX.database.windows.net;initial catalog=NLog;integrated security=false;persist security info=True;User ID=XXXXr;Password=BXXXX3"
commandText="INSERT INTO Logs(EventDateTime, EventLevel, UserName, MachineName, EventMessage, ErrorSource, ErrorClass, ErrorMethod, ErrorMessage, InnerErrorMessage, StackTrace) VALUES (#EventDateTime, #EventLevel, #UserName, #MachineName, #EventMessage, #ErrorSource, #ErrorClass, #ErrorMethod, #ErrorMessage, #InnerErrorMessage, #StackTrace)">
<!-- parameters for the command -->
<parameter name="#EventDateTime" layout="${date:s}" />
<parameter name="#EventLevel" layout="${level}" />
<parameter name="#UserName" layout="${windows-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}" />
<parameter name="#StackTrace" layout="${event-context:item=stack-trace}" />
</target>
<target name="console" xsi:type="Console" />
</targets>
<rules>
<!-- add your logging rules here -->
<logger name="*" minlevel="Info" writeTo="database" />
<logger name="*" minlevel="Error" writeTo="asyncFile" />
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</
The reason that you are not able to get Debug is that debug is the lowest level log level
just add following tag in rules tag in nlog.config file.
<logger name="*" minlevel="Debug" writeTo="console" />
I found the problem to be related to the default appsettings.json that Visual Studio automatically adds to the project. It looks like this.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
The solution was to remove or rename this section.
{
"Logging-DISABLE": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
This allowed nlog.config to be utilized.
You are using 3 different log targets.
Database target is set to Info level, so debug messages are not going there.
File target accepts only Error messages (and higher) so there will not be any debug either.
The last target Console is the one where debug mesages should be looged to. But as I see it you didn't set layout of the message. Try to look at this documentation. It says that layout is a required field.
Also I would suggest you temporarily set additional File target and set it to accept debug messages.
For anyone else who has this issue, an answer at a similar question just saved me: https://stackoverflow.com/a/8881521/3959735
If you are using a separate NLog.config file, make sure it's set to "copy always" via its file properties. Alternatively, you can include the NLog configuration section in your main App.config.
I think I might have caused this issue for myself either by trying to copy an NLog configuration file from another project manually; or because when adding NLog to my project I got a permissions error (of which I cannot remember any specific details) – just passing on this information in case it helps anyone diagnose their own issue.
Add nlog.config file to your project
Example of my config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="${basedir}/Logs/${date:format=yyyy-MM-dd}_log.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
</configuration>