0

Using an ASP.NET Core 8 Web API, I tried to implement logging to a SQL Server table.

SQL Server version used:

Microsoft SQL Server 2019 (RTM-GDR) (KB5046859) - 15.0.2130.3 (X64)
Oct 18 2024 15:25:23   
Copyright (C) 2019 Microsoft Corporation  
Express Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 19045: ) (Hypervisor)

NLog is logging to the text file but NOT creating records in the SQL Server table. I can't figure out why.

I used the following references:

  1. https://github.com/NLog/NLog.Web/tree/master/examples Note NLOG only has documentation for .NET 7, not .NET 8.
  2. https://www.toshalinfotech.com/Blogs/ID/204/NLog-Writing-Logs-to-SQL-Server-from-Web-API
  3. https://code-maze.com/writing-logs-to-sql-server-using-nlog/

Program.cs:

using NLog;
using NLog.Web;

namespace Api
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            var logger = NLog.LogManager.Setup()
                .LoadConfigurationFromXml("nlog.config")
                .GetCurrentClassLogger();
            try
            {
                builder.Services.AddControllers();
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();

                builder.Logging.ClearProviders();
                builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);
                builder.Host.UseNLog();

                var app = builder.Build();

                // Configure the HTTP request pipeline.
                if (app.Environment.IsDevelopment())
                {
                    app.UseSwagger();
                    app.UseSwaggerUI();
                }

                app.UseHttpsRedirection();

                app.UseAuthorization();

                app.MapControllers();

                app.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();
            }
        }
    }
}

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:\Nlog\logs\internalLog.txt">
    <extensions>
        <!--enable NLog.Web for ASP.NET Core-->
        <add assembly="NLog.Web.AspNetCore"/>
    </extensions>
    <targets>
        <target xsi:type="Database"
            name="dbTarget"
            dbProvider="System.Data.SqlClient"
            commandType="TableDirect"
            connectionString="Data Source=localhost\sqlexpress;Initial Catalog=myDatabase;Integrated Security=True;Encrypt=False"
             <!-- Note I removed MachineName from the insert statement and commented out the parameter below. -->
            commandText="insert into dbo.Log (Logged, Level, Message, Logger, Exception)
                                      values (@Logged,@Level,@Message,@Logger,@Exception);">

            <!--<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="@Exception" layout="${exception:tostring}" />
        </target>
        <target name="file" xsi:type="File"
           layout="${longdate} ${level} ${logger} ${message} ${aspnet-request-url} ${exception:format=ToString}"
           fileName="C:/temp/logs/logfile.txt"
           keepFileOpen="true"
           encoding="utf-8" />
    </targets>

    <rules>
        <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
        <logger name="Microsoft.*" maxlevel="Info" final="true" />
        <logger name="System.Net.Http.*" maxlevel="Info" final="true" />
        
        <logger name="*" minlevel="Trace" writeTo="dbTarget" />
        <logger name="*" minlevel="Trace" writeTo="file" />
    </rules>
</nlog>

HomeController:

using Microsoft.AspNetCore.Mvc;

namespace Api.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class HomeController : ControllerBase
    {
        private readonly ILogger<HomeController> _logger;
        
        public HomeController(ILogger<HomeController> logger) 
        {
            _logger = logger;
        } 

        [HttpGet(Name = "GetHome")]
        public string Get()
        {
            _logger.LogInformation("GetHome was called");
            return "Success";
        }
    }
}

Logfile.txt that shows the logs created:

logfile.txt

My database table:

Log Table

T-SQL code to create Logs table:

-- Note I allowed nulls in all columns except the identity 
-- to ensure that the non null constraint was not causing the issue.

CREATE TABLE [dbo].[Log]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [MachineName] [nvarchar](50) NULL,
    [Logged] [datetime] NULL,
    [Level] [nvarchar](50) NULL,
    [Message] [nvarchar](max) NULL,
    [Logger] [nvarchar](250) NULL,
    [Exception] [nvarchar](max) NULL,

    CONSTRAINT [PK_dbo.Log] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Nuget packages:

Nuget References

4
  • 1
    So, what is your question...? You've given us a lot of code here, and an image of data (Please do not upload images of code/data/errors when asking a question.), but but asked anything. Commented Dec 6, 2024 at 14:45
  • Not Writing Logs to MSSQL Table - I have followed the examples and I am getting results/logs in my text logfiles but not my SQL table. Commented Dec 6, 2024 at 14:49
  • What if try to escape backslash in the connection string: "Data Source=localhost\\sqlexpress ... Commented Dec 6, 2024 at 15:06
  • Excellent suggestion connectionString="Data Source=localhost\\sqlexpress; unfortunately did not help. Commented Dec 6, 2024 at 15:13

1 Answer 1

1

The solution was the following:

Needed to Add Nuget:

  1. Microsoft.Data.SQLClient
  2. NLog.Database
  3. Removed other database related Nuget Packages

nlog.config changes:

  1. I am not certain if I need to load the NLog.Database assembly but did this.
  2. I also changed dbProvider
  3. No escape character for backslash is needed in 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="Trace"
      internalLogFile="C:\Nlog\logs\internalLog.txt">
    <extensions>
        <!--enable NLog.Web for ASP.NET Core-->
        <add assembly="NLog.Database"/>
        <add assembly="NLog.Web.AspNetCore"/>
    </extensions>
    <targets>
        <target xsi:type="Database"
            name="dbTarget"
            dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
            connectionString="Data Source=localhost\myDatabase;Initial Catalog=imsLearn;Integrated Security=True;Encrypt=False;"
            commandText="insert into dbo.Log(Logged, Level, Message, Logger, Exception) values (@Logged,@Level,@Message,@Logger,@Exception);">

            <!--<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="@Exception" layout="${exception:tostring}" />
        </target>
        <target name="file" xsi:type="File"
           layout="${longdate} ${level} ${logger} ${message} ${aspnet-request-url} ${exception:format=ToString}"
           fileName="C:/temp/logs/logfile.txt"
           keepFileOpen="true"
           encoding="utf-8" />
    </targets>

    <rules>
        <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
        <logger name="Microsoft.*" maxlevel="Info" final="true" />
        <logger name="System.Net.Http.*" maxlevel="Info" final="true" />
        
        <logger name="*" minlevel="Trace" writeTo="dbTarget" />
        <logger name="*" minlevel="Trace" writeTo="file" />
    </rules>
</nlog>

Record inserted

Logs in SQL

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.