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).
Related
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();
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.
Objective
Log the errors to Microsoft Teams with NLog from a console program.
Issue
Was able to log to the console, but not to Teams
Code
Config:
<targets>
<target xsi:type="Console" name="console"/>
<target xsi:type="WebService"
name="microsoft-teams"
url="https://outlook.office.com/webhook/abcd"
protocol='JsonPost'
encoding='UTF-8'
includeBOM='false' >
</target>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="console" />
<logger name='*' writeTo='microsoft-teams' />
</rules>
Logging code:
private static Logger logger = LogManager.GetCurrentClassLogger();
public static void Main(string[] args) {
logger.Error("{'text':'test'}");
logger.Fatal("Sample fatal error message");
}
The console target displayed the errors very well. But the Teams channel didn't have log, the nlog-internal.log showed
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
Any insight would be greatly appreciated!
You need at least send some parameters, see example webserver target:
<target type='WebService'
name='ws'
url='http://localhost:1234/logme'
protocol='HttpPost'
encoding='UTF-8' >
<parameter name='param1' type='System.String' layout='${message}'/>
<parameter name='param2' type='System.String' layout='${level}'/>
</target>
If this still isn't working, I would recommend checking the call with Fiddler
I know it is a little bit late, but you can try the NLog extension I created.
https://github.com/jedipi/NLog.Targets.MicrosoftTeams
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)
I am using Nlog 2.1 and trying to write errors into Windows Event logger with different eventId. To better distinguish different errors.
If I specify eventId property it's working, but if don't I am not seeing any record in Windows Event Logger.
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">
<targets>
<target name="console" xsi:type="ColoredConsole"
layout="${date:format=HH\:mm\:ss}|${level:uppercase=true}|${message}" />
<target xsi:type="EventLog"
name="eventlog"
layout="{${newline}
"Logger": "${logger}",${newline}
"StackTrace": "${stacktrace}",${newline}
"Message": "${message}",${newline}
"Exception": "${exception:format=ToString,Data}"${newline}}"
machineName="."
source="CareFusion Analytics Agent Service"
eventId="${event-properties:EventID}"
log="Application" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console" />
<logger name="*" minlevel="Error" writeTo="eventlog" />
</rules>
</nlog>
Usage:
private static void Main(string[] args)
{
Logger logger = LogManager.GetCurrentClassLogger();
logger.Error("Sample error message"); //This is not working
LogEventInfo logEvent = new LogEventInfo()
{
Level = LogLevel.Error,
Message = "Hello",
LoggerName = logger.Name
};
logEvent.Properties.Add("EventID", 400);
logger.Log(logEvent); //This is working
Console.WriteLine("Press any key....");
Console.ReadKey();
}
The call logger.Error("Sample error message"); goes wrong as the EventLogTarget tries to convert the ${event-properties:EventID} to a integer.
Because layout renders in NLog never return null (but string.Empty), this will give a exception - which will be caught by NLog. In the NLog's internal log you should see a FormatException.
So we need to specify a default value, you could do that with the whenEmpty:
<target xsi:type="EventLog"
...
eventId="${event-properties:EventID:whenEmpty=0}" />
PS: tested it with NLog 4.3.11