Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NLog async target database connection exceptions - how to get them?

Can anyone help me with a situation where NLog is logging into a database using AsyncTargetWrapper and there is a connection problem? How can I obtain/intercept those exceptions (since async targets don't throw exceptions)? It seems to be a pretty common scenario so I find it hard to believe that InternalLogger is the only option. Here's an example project (requires NLog nuget package installed):

using System;
using System.Threading;
using NLog;
using NLog.Common;
using NLog.Config;
using NLog.Targets;
using NLog.Targets.Wrappers;

class Program
{
    static void Main(string[] args)
    {
        LogManager.ThrowExceptions = true;
        InternalLogger.LogToConsole = true;
        InternalLogger.LogLevel = LogLevel.Error;

        var conf = new LoggingConfiguration();
        var target = new DatabaseTarget
        {
            ConnectionString =
                "Server=BAD_SERVER;Database=foo;",
            CommandText = "INSERT INTO logs(message) VALUES ('bar')"
        };

        var asyncTarget = new AsyncTargetWrapper(target);
        var rule = new LoggingRule("*", LogLevel.Trace, asyncTarget);
        conf.LoggingRules.Add(rule);

        LogManager.Configuration = conf;

        Logger logger = LogManager.GetLogger("Example");
        logger.Info("Message"); // doesn't throw an exception

        Thread.Sleep(16000);

        Console.WriteLine("\nDone");
        Console.ReadLine();
    }
}

So the app can't connect to the server (invalid server name in connection string). After some default (hidden in NLog's guts?) connection timeout is hit, an exception is printed to the console by InternalLogger:

2016-01-20 16:39:36.8466 Error Error when writing to database System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)

Now, I know I can set InternalLogger.LogFile() but I have to use this in a Web service hosted on Azure Web Apps and it doesn't create any file when I try that (I have to use relative path, which works locally in a console app but not after deployment to Azure).

How one deals with connection exceptions when using async NLog logger?

like image 456
Piotr Avatar asked Jan 20 '16 15:01

Piotr


1 Answers

You can try: a fallback-wrapper with a file and DB target.

Something like this:

<targets>
  <target xsi:type="FallbackGroup" name="target1" returnToFirstOnSuccess="true">
    <target xsi:type="Database" ... />
    <target xsi:type="File" ... />
  </target>

That should also work with <targets async="true">, but I would advise to test it first without async.

Edit: It's a known issue that exceptions are not thrown even if ThrowExceptions =true. We're working on this, see GitHub.

For now, if you have trouble logging to file, you can choose another target, like the Memory or MethodCall target?

like image 77
Julian Avatar answered Sep 18 '22 17:09

Julian