I am working on a project and writing a logging framework. I encountered an issue with nlog when logging with Info method passing T as argument.
I installed nlog nuget. Below is 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="info" internalLogFile="internalLog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<!-- the targets to write to -->
<targets async ="true">
<!-- write to file -->
<target xsi:type="File"
name="testlogging"
fileName="C:\testfolder\logs\testdata.log"
layout="${JsonLayout}" >
<layout xsi:type="JsonLayout" includeAllProperties ="true" >
<attribute name ="date" layout ="${longdate}"></attribute>
<attribute name ="message" layout ="${message}"></attribute>
</layout>
</target>
</targets>
<!-- rules to map from logger name to target -->
<rules>
<logger name ="testlogging" minlevel="Info" writeTo="testlogging" />
</rules>
</nlog>
Created NlogCustom class
public class NlogCustom : INlogCustom {
private readonly NLog.ILogger _logger;
public NlogCustom(NLog.ILogger logger)
{
_logger = logger;
}
public void WriteMessage(string message)
{
var tstlogentry = new TestLogEntry { Id = 1, Name = "Alexander" };
_logger.Info(tstlogentry);
}
}
public class TestLogEntry
{
public int Id { get; set; }
public string Name { get; set; }
}
Then calling from default weatherforecastcontroller
namespace TestNlog.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
private readonly INlogCustom _nloglogger;
public WeatherForecastController(ILogger<WeatherForecastController> logger,
INlogCustom nlogger)
{
_logger = logger;
_nloglogger = nlogger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
_nloglogger.WriteMessage("Init the Get method");
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}
But the log file shows
{ "date": "2024-01-23 13:17:30.8058", "message": "TestNlog.TestLogEntry" } { "date": "2024-01-23 13:17:57.7975", "message": "TestNlog.TestLogEntry" }
But what I was expecting is to see the data in TestLogEntry in Json format. I know this can be done with Nlog. Can anyone help me if there is something that I am missing in this process? In typical scenarios the TestLogEntry is some object that will have payload of request and response with different properties.
You have configured NLog JsonLayout to output LogEvent-properties, but not logging any properties.
If you want NLog to dump all object-properties using object-reflection, then you can use structured-logging:
public void WriteMessage(string message)
{
var tstlogentry = new TestLogEntry { Id = 1, Name = "Alexander" };
_logger.Info("{LogEntry}", tstlogentry);
}
You can consider to override TestLogEntry.ToString()
-method to control the output of ${message}
.