DaveM
DaveM

Reputation: 93

Nlog log to database .NET 5.0 with DI and using appsettings.json

I've been trying to get Nlog to send logging to a database, but the examples I've found all return an internal nlog error. I'm using dependency inject in a console application with .NET 5.0...:

Info Adding target ConsoleTarget(Name=console)
Warn Error has been raised. Exception: NLog.NLogConfigurationException: Failed to create Target of type: Database
 ---> System.ArgumentException: Target cannot be found: 'Database'. Extension NLog.Database not included?
   at NLog.Config.Factory`2.CreateInstance(String itemName)
   at NLog.Config.LoggingConfigurationParser.FactoryCreateInstance[T](String classType, INamedItemFactory`2 factory)
   --- End of inner exception stack trace ---
Warn Error has been raised. Exception: NLog.NLogConfigurationException: Target 'dbTarget' not found for logging rule: *.

In my json, I have the following:

  "NLog": {
    "internalLogLevel": "info",
    "internalLogFile": "${basedir}/logs/internal-nlog.txt",
    "extensions": {
      "NLog.Extensions.Logging": {
        "assembly": "NLog.Web.AspNetCore"
      }
    },
    "targets": {
      "database": {
        "type": "Database",
        "name": "dbTarget",
        "dbProvider": "Microsoft.Data.SqlClient.SqlConnection,Microsoft.Data.SqlClient",
        "connectionString": "myconnectionstring",
        "commandText": "INSERT INTO dbo.Logs (Level,CallSite,Type,Message,StackTrace,InnerException,AdditionalInfo) values (@level, @callSite, @type, @message, @stackTrace, @innerException, @additionalInfo)",
        "parameters": [
          {
            "lots of parameters follow"
          }
        ]

      }
    },
    "rules": [
      {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "dbTarget"
      }
    ]

And this is in my Main():

        static void Main(string[] args)
        {
            ApplicationSettings applicationSettings = new ApplicationSettings();

            var settings = applicationSettings.GetConfiguration();

            var host = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddSingleton<IApplicationSettings, ApplicationSettings>();
                services.AddSingleton<IApplication, Application>();
                services.AddSingleton<ITeamMemberProcessor, TeamMemberProcessor>();
                services.AddLogging(loggingBuilder =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddNLog();
                });
            })
            .Build();
            

            var svc = ActivatorUtilities.CreateInstance<Application>(host.Services);
            svc.Run();
        }

Am I missing something? The write to file and write to console work fine. Also, as I understand, the nlog.config shouldn't be used anymore.. we should be using appsettings.json?

Thanks!

Dave

Upvotes: 7

Views: 9141

Answers (2)

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

I'm guessing that you are using NLog 5.0 where the NLog DatabaseTarget has been extracted into a seperate nuget-package.

Guess what the error-message is trying to say:

Exception: NLog.NLogConfigurationException: Failed to create Target of type: Database
 ---> System.ArgumentException: Target cannot be found: 'Database'. Extension NLog.Database not included?

It wants you install the extension NLog.Database from nuget, and also add it to the NLog config. Something like this:

"NLog": {
    "internalLogLevel": "info",
    "internalLogFile": "${basedir}/logs/internal-nlog.txt",
    "extensions": [
      { "assembly": "NLog.Database" },
      { "assembly": "NLog.Web.AspNetCore" }
    ],
    "targets": {
        "database": {
        "type": "Database",
        "name": "dbTarget",
        "dbProvider": "Microsoft.Data.SqlClient.SqlConnection,Microsoft.Data.SqlClient",
        "connectionString": "myconnectionstring",
        "commandText": "INSERT INTO dbo.Logs (Level,CallSite,Type,Message,StackTrace,InnerException,AdditionalInfo) values (@level, @callSite, @type, @message, @stackTrace, @innerException, @additionalInfo)",
        "parameters": [
            {
            "lots of parameters follow"
            }
        ]

        }
    },
    "rules": [
        {
        "logger": "*",
        "minLevel": "Debug",
        "writeTo": "dbTarget"
        }
    ]
}

See also: NLog configuration with appsettings.json

Upvotes: 12

DaveM
DaveM

Reputation: 93

So, I was able to get it to "work", although without DI.. which I still would like to try to figure out. It looks as if I was missing two lines in my ApplicationSettings:

            LogManager.Configuration = new NLogLoggingConfiguration(_configuration.GetSection("NLog"));
            var logger = NLogBuilder.ConfigureNLog(LogManager.Configuration).GetCurrentClassLogger();

And then in my "Application" class I removed the Logging injection, and added this at the top of my "Run" method:

var _logger = LogManager.Setup().LoadConfigurationFromSection(_configuration).GetCurrentClassLogger();

It then worked.. Again, I'm guessing I'm missing something so I can use dependency injection? But I'm not sure what..

Thanks for the responses, I appreciate you taking the time!

Dave

Upvotes: 0

Related Questions