NLog.Web.AspNetCore no longer logging to database - c#

I have a dotnet core API that's up on version 2.2 with NLog.Web.AspNetCore 4.7.0 (NLog 4.5.11) which was previously working back in version 4.5.4. With the update, it now doesn't appear to be logging to the database. Nothing in terms of the logging infrastructure has changed within my code.
I should mention, I also have in the log this lovely line, so I know it's somewhat working. But I use to get A LOT more information, and of course, the database would have stuff written to it as well.
2018-12-26 15:06:59.9503||DEBUG|SomeApp.API.Program|init main |url: |action:
I tried looking around in the github issues and on here, but I haven't found anything of much use, any help is greatly appreciated!
Initial Setup in Program.cs
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
}
catch (Exception ex)
{
//NLog: catch setup errors
logger.Error(ex, "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();
}
Implementation
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseIISIntegration()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog() // NLog: setup NLog for Dependency injection
.Build();
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"
internalLogLevel="Trace"
internalLogFile="C:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets async="true">
<target type="File" name="file" fileName="${basedir}\logs\logfile.txt"
maxArchiveFiles="5" archiveAboveSize="20971520" archiveEvery="Day"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<target xsi:type="Null" name="blackhole" />
<target name="database" xsi:type="Database">
<connectionString>${gdc:item=connectionString}</connectionString>
<commandText>
insert into dbo.Log (
EventId, Logged, Level, Message,
Username,
ServerName, Port, Url, Https,
ServerAddress, RemoteAddress,
Logger, CallSite, Exception
) values (
#EventId, #Logged, #Level, #Message,
#Username,
#ServerName, #Port, #Url, #Https,
#ServerAddress, #RemoteAddress,
#Logger, #Callsite, #Exception
);
</commandText>
<parameter name="#EventId" layout="${event-properties:item=EventId_Id}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#message" layout="${message}" />
<parameter name="#username" layout="${aspnet-user-identity}" />
<parameter name="#serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
<parameter name="#port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
<parameter name="#url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
<parameter name="#https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
<parameter name="#serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
<parameter name="#remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#callSite" layout="${callsite}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
</targets>
<rules>
<!--Limit to only configured logs for all logs, change name="*"-->
<logger name="SomeApp.*" minlevel="Info" writeTo="database" />
<logger name="*" minlevel="Trace" writeTo="file" />
<!--Skip Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
</rules>
</nlog>
Sample logging code
_logger.LogInformation(1001, "Login success: {0}", userForLoginDto.Username);
appsettings.json & appsettings.Development.json Logging Settings
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Information"
}
The NLog internal log doesn't seem to have anything of significance, I can provide it if requested though.
Apologies for any weird formatting issues, the nlog.config file did not want to come willingly.

Related

NLog seems to be writing incorrect value in database

I'm using NLog for logging into database. It seems to me its misplacing value in columns. For instance, it writes StackTrace in Message column and Exception information in StackTrace column
Configuration:
<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwConfigExceptions="true" throwExceptions="true">
<targets>
<target name="database" type="Database" connectionString="Data Source=Server1;initial catalog=MyDb;Integrated Security=True;">
<commandText>insert into dbo.AppException ([Level], Logger, Message, Exception, StackTrace) values (#Level, #Logger, #Message, #Exception, #StackTrace);</commandText>
<parameter name="#Level" layout="${level}" />
<parameter name="#Logger" layout="${logger}" />
<parameter name="#Message" layout="${message}" />
<parameter name="#Exception" layout="${exception}" />
<parameter name="#StackTrace" layout="${stacktrace}" />
<dbProvider>System.Data.SqlClient</dbProvider>
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="database" />
</rules>
</nlog>
My test code:
throw new IOException("This is my message");
Logging code:
logger.Error(ex);
Below is a sample row in database
In my opinion, the value in "Exception" field should be written in "Message" column and value of "StackTrace" should be written into "Exception" column and finally value of "Message" should be written in "StackTrace".
Is there anything wrong in my configuration or my expectation is wrong?
I'm guessing you are logging the exception like this:
catch (Exception ex)
{
_logger.Error(ex); // ${message} will become ex.ToString(), since no message provided.
}
If you changed to this instead:
catch (Exception ex)
{
_logger.Error(ex, "Exception caught while testing");
}
And updated NLog.config to this:
<parameter name="#Exception" layout="${exception:format=tostring,data}" />
Then you will probably get what you want.
After reading answer posted by #Rolf, I found my nlog.config setting is not correct. The format setting in nlog is important
NLog Document
I changed my nlog to below and it worked as expected
<parameter name="#Message" layout="${exception:format=message}" />
<parameter name="#Exception" layout="${exception:format=type}" />
<parameter name="#StackTrace" layout="${exception:format=stacktrace}" />

NLog MySql .Net Core 3.0 logging not saving to database

I have setup NLog on my project that will save the logging to my audit database (separate from the default database). However, it is failing to write to the database. I have a console logger target as well and that is logging as expected. No errors are shown or given. It merely fails to write to the database.
I have tried various methods provided from google, but none seemed to have worked. I have also tried using NLogBuilder to configure the config for that specific controller but still, it doesn't write to the database
nlog.config file:
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
</configSections>
<nlog internalLogLevel="Trace">
<targets>
<target name="ConsoleLogger" type="Console"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}"/>
<target name="DatabaseLog" type="Database">
<commandtext>
INSERT INTO Logs
(LogDate, LogLevel, Message, Exception)
VALUES
(#log_date, #log_level, #message, #exception)
</commandtext>
<parameter name="#log_date"
layout="${log_date}"
dbType="DateTime"/>
<parameter name="#thread"
layout="${thread}"
dbType="String"
size="255"/>
<parameter name="#log_level"
layout="${log_level}"
dbType="String"
size="20" />
<parameter name="#logger"
layout="${logger}"
dbType="String"
size="250" />
<parameter name="#message"
layout="${message}"
dbType="String"
size="4000" />
<parameter name="#exception"
layout="${exception}"
dbType="String"
size="4000" />
<dbProvider>MySql.Data.MySqlClient.MySqlConnection, MySql.Data</dbProvider>
<connectionString>User Id=username;Password=password;Host=localhost;Database=audit_database;TreatTinyAsBoolean=false</connectionString>
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" maxlevel="Fatal" writeTo="ConsoleLogger,DatabaseLog" />
</rules>
</nlog>
Controller method:
public static Logger _logger = LogManager.GetCurrentClassLogger(typeof(ActionerController));
_logger.Info("text");
Main.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddNLog();
}).ConfigureAppConfiguration((hostingContext, config) =>
{
config
.AddJsonFile($"environment-mount/appsettings.json", optional: true)
.AddEnvironmentVariables();
}).ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
For MySQL, make sure you have installed the MySql.Data package.
There are also some mistakes in your config and code:
${log_date}, ${log_level} and ${thread} don't exist. I guess you mean ${date}, ${level} and ${threadid}. See all options here.
LogManager.GetCurrentClassLogger with an argument expects a logger type - so inherits from NLog.Logger. I think you are looking for LogManager.GetCurrentClassLogger() or LogManager.GetLogger(typeof(ActionerController).FullName). See API docs
Of course there could be other errors, e.g. a wrong query, mistyped colum names or wrong column types. NLog could of course tell you the problem:
Or enable exceptions. In your config <nlog throwExceptions=true >
Or enable the internal log: <nlog internalLogFile="c:\log.txt" internalLogLevel="Warn">. Read more here

NLog entries to SQL Server in .NET Core 2.2

What I want to do is to save all my logs to a table in a separate logging database, using NLog, and I can't seem to make it work.
This is my 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"
internalLogLevel="Trace"
internalLogFile="c:\temp\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<target name="dbLogger" xsi:type="Database"
connectionStringName="LoggingConnection" commandType="StoredProcedure"
commandText="[dbo].[NLog_AddEntry_p]">
<parameter name="#machineName" layout="${machinename}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" 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}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="dbLogger"/>
</rules>
</nlog>
I managed to make it log in a .txt file with a similar config, but it does not write to the DB. The "LoggingConnection" connection string is identical to the one I use for normal CRUD operations in the website; the difference is that is uses another DB.
So, after some digging checking the internal log file I've come up with this solution.
System.Data.SqlClient was added to the project and it need to be. Also I've added Nlog.Config Nuget package to the project as well.
I've removed the "extension" tag and I've done some tweaks to the nlog tag
<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="Trace" internalLogFile="c:\temp\nlog-internal.log">
I've replaced the "connectionStringName" attribute with "connectionString" and added the connection string from the appSettings.json.

Unable to set my connectionstring in NLog

The NLog.config file does not set the connection string.
<?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="Warn"
internalLogFile="c:\temp\internal-nlog.txt">
<!-- Load the ASP.NET Core plugin -->
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<variable name="SirNLogDb" value="data source=SQL_MULALLEY;initial catalog=LogFiles;User ID=xxx;Password=yyy;">
</variable>
<!-- providerName="System.Data.SqlClient"-->
<!-- the targets to write to -->
<targets>
<target name="db"
xsi:type="Database"
dbProvider="System.Data.SqlClient"
connectionString="${var:SirNLogDb}"
commandType="StoredProcedure"
commandText="[dbo].[NLog_AddEntry_p]">
<parameter name="#machineName" layout="${machinename}" />
<parameter name="#siteName" layout="${iis-site-name}" />
<parameter name="#logged" layout="${date}" />
<parameter name="#level" layout="${level}" />
<parameter name="#username" layout="${aspnet-user-identity}" />
<parameter name="#message" layout="${message}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#properties" layout="${all-event-properties:separator=|}" />
<parameter name="#serverName" layout="${aspnet-request:serverVariable=SERVER_NAME}" />
<parameter name="#port" layout="${aspnet-request:serverVariable=SERVER_PORT}" />
<parameter name="#url" layout="${aspnet-request:serverVariable=HTTP_URL}" />
<parameter name="#https" layout="${when:inner=1:when='${aspnet-request:serverVariable=HTTPS}' == 'on'}${when:inner=0:when='${aspnet-request:serverVariable=HTTPS}' != 'on'}" />
<parameter name="#serverAddress" layout="${aspnet-request:serverVariable=LOCAL_ADDR}" />
<parameter name="#remoteAddress" layout="${aspnet-request:serverVariable=REMOTE_ADDR}:${aspnet-request:serverVariable=REMOTE_PORT}" />
<parameter name="#callSite" layout="${callsite}" />
<parameter name="#exception" layout="${exception:tostring}" />
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="database" />
</rules>
</nlog>
I put a breakpoint and the connection string is null;
My Startup method is as follows;
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddMvcOptions(o => o.OutputFormatters.Add(
new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared)));
var connectionStringMSurveyV2 = Configuration.GetConnectionString("MSurveyV2Db");
services.AddScoped<MSurveyV2Db>(_ => new MSurveyV2Db(connectionStringMSurveyV2));
var connectionStringSir = Configuration.GetConnectionString("SirDb");
services.AddScoped<SirDb>(_ => new SirDb(connectionStringSir));
services.AddScoped<IPropertiesRepo, PropertiesRepo>();
services.AddScoped<ISirUoW, SirUoW>();
services.AddScoped<Services.IMailService, Services.MailService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
loggerFactory.AddDebug();
loggerFactory.AddNLog();
//add NLog.Web
app.AddNLogWeb();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler();
}
app.UseMvc();
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Exception, OperationStatus>();
cfg.CreateMap<ViewSelectedContracts, ContractDto>();
});
var logger = LogManager.GetCurrentClassLogger();
logger.Info("Logged in");
}
}
EDIT - I change the logger rule to <logger name="*" minlevel="Trace" writeTo="db" /> but still it didn't output anything. However I looked for the c:\temp\internal-nlog.txt and it had not been created. So it appears the nlog.config file is being ignored. But it is in my project next to the Startup.cs file.
EDIT2: - the null configuration can be solved by setting "Copy to output directory" to "copy always".
From the comments underneath I have now got this working.
Updated answer
Since NLog.Web.AspNetCore 4.8 (NLog.Extensions.Logging 1.4 for .NET Core console programs) you could directly read from your appSettings.json
${configsetting:name=MyConnectionString}
see docs
Original answer
Unfortunately reading connectionstrings/settings from appSettings.json / app.config is not yet supported in NLog for .NET core.
Two options:
Set the connectionstring programmatically, by using variables.
In your nlog.config:
<target ... connectionString="${var:myConnectionstring}" ... />
and in code: (e.g. in Configure)
LogManager.Configuration.Variables["myConnectionstring"] = "...."; //read config here
Or, set the connectionstring in nlog.config.
In your nlog.config:
<variable name="myConnectionstring" value="...." />
and using in your target in nlog.config:
<target ... connectionString="${var:myConnectionstring}" ... />
Another option is to create and register a custom NLog layout-renderer (startup.cs):
https://github.com/NLog/NLog/wiki/How-to-write-a-custom-layout-renderer
Which outputs the ConnectionString after having read it from your favorite configuration-location. Then you don't have the connectionstring in your nlog.config, but just refer to your custom layout-renderer.
Maybe cheer for this pending issue:
https://github.com/NLog/NLog.Web/issues/107

NLog not writing debug messages

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>

Categories

Resources