控制台应用程序未在 AppDomain.CurrentDomain.UnhandledException 中记录 NLOG 错误

发布于 2025-01-12 23:46:19 字数 572 浏览 1 评论 0原文

下面的代码没有记录到我的数据库。是否是因为控制台应用程序关闭得太快,如果是,我该如何防止这种情况?

   private static ILogger _logger;

      static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
        {
            _logger.Error((Exception)e.ExceptionObject);
        }
    
        private static void Main(string[] args)
        {
            var container = new Container();
            _logger = container.GetInstance<ILogger>();
    AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            throw new Exception("test");

The below code isn't logging to my database. Is it because the console application closes too soon and if so how can I prevent this?

   private static ILogger _logger;

      static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
        {
            _logger.Error((Exception)e.ExceptionObject);
        }
    
        private static void Main(string[] args)
        {
            var container = new Container();
            _logger = container.GetInstance<ILogger>();
    AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            throw new Exception("test");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

身边 2025-01-19 23:46:19

您可以在离开 UnhandledExceptionTrapper 方法之前调用 LogManager.Shutdown()。这会在内部调用 LogManager.Flush()

以 15 秒的默认超时时间刷新任何挂起的日志消息(如果是异步目标)。

请参阅 NSLog Flush 文档

其他故障排除

在调试控制台中,如果连接上发生 SQL 错误等情况,则会显示错误消息,但默认情况下您不会看到配置是否无效。

由于 NLog 提供了广泛的配置选项,因此很容易出现一些小的配置错误,从而导致不记录日志。一个典型的例子是不正确的 ConnectionStringDBProvider

例如,假设您配置了不正确的 DBProvider。

例如,你可以打电话

LogManager.GetCurrentClassLogger().Debug("test logging");
LogManager.Flush();

,但它会默默地失败。

但是,如果您

LogManager.ThrowExceptions = true;

在测试日志调用之前插入,您将在调试控制台中看到相应的消息。例如,如果您有一个无效的 DBProvider,例如 Npgsql.NpgsqlConnection1, Npgsql(请注意其中的无效 1),您会看到

Unhandled exception. NLog.NLogRuntimeException: Exception occurred in NLog
 ---> NLog.NLogRuntimeException: Target Database Target[nlog-db] failed to initialize.
 ---> System.TypeLoadException: Could not load type 'Npgsql.NpgsqlConnection1' from assembly 'Npgsql'.

哪个可以清楚地指示发生了什么错误的。

更多诊断

要查看更多诊断信息,您可以添加以下行:

InternalLogger.LogToConsole = true;
InternalLogger.LogLevel = LogLevel.Trace;

除其他外,您可以查看连接何时打开、写入了哪些数据以及有关刷新的信息(小样本摘录):

2022-03-11 08:47:56.8428 Trace DatabaseTarget(Name=nlog-db): Open connection.
2022-03-11 08:47:57.0275 Trace DatabaseTarget(Name=nlog-db): Executing Text: insert into "public"."log_table"(time_stamp,level,logger,message,stacktrace) values(CAST(@time_stamp AS timestamp),@level,@logger,@message,@stacktrace);
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@time_stamp' = '2022-03-11T08:47:56.837' (String)
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@level' = 'Debug' (String)
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@logger' = 'ConsoleDBLog.Program' (String)
2022-03-11 08:47:57.0395 Trace   DatabaseTarget: Parameter: '@message' = 'test logging' (String)
2022-03-11 08:47:57.0415 Trace   DatabaseTarget: Parameter: '@stacktrace' = '' (String)
2022-03-11 08:47:57.1099 Trace DatabaseTarget(Name=nlog-db): Finished execution, result = 1
2022-03-11 08:47:57.1111 Trace DatabaseTarget(Name=nlog-db): Close connection (KeepConnection = false).
2022-03-11 08:47:57.1167 Debug LogFactory Flush with timeout=15 secs

< strong>自包含示例

using System;
using NLog;
using NLog.Targets;

namespace ConsoleDBLog;

internal static class Program
{
    private static ILogger? _logger;

    static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
    {
        _logger?.Error((Exception?) e.ExceptionObject, "unhandled exception");
        LogManager.Shutdown();
    }

    private static void Main()
    {
        SetupDB_NLOG();
        _logger = LogManager.GetCurrentClassLogger();
        AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
        throw new Exception("test");
    }

    static void SetupDB_NLOG()
    {
        DatabaseTarget target = new DatabaseTarget();
        target.Name = "nlog-db";

        target.DBProvider = "Npgsql.NpgsqlConnection, Npgsql";
        target.ConnectionString = "Server=127.0.0.1;Port=5432;User Id=stephan;Password=;Database=stephan;";
        target.CommandText =
            "insert into \"public\".\"log_table\"(time_stamp,level,logger,message,stacktrace) values(CAST(@time_stamp AS timestamp),@level,@logger,@message,@stacktrace);";

        var param = new DatabaseParameterInfo
        {
            Name = "@time_stamp",
            Layout = "${date:format=yyyy-MM-ddTHH\\:mm\\:ss.fff}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@level",
            Layout = "${level}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@logger",
            Layout = "${logger}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@message",
            Layout = "${message}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@stacktrace",
            Layout = "${exception:format=stacktrace}"
        };
        target.Parameters.Add(param);

        NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Debug);

        //Uncomment the following lines to see things that would silently fail and
        //to get more diagnostic debug output about what is actually running.
        
        // InternalLogger.LogToConsole = true;
        // InternalLogger.LogLevel = LogLevel.Trace;
        // LogManager.ThrowExceptions = true;

        // LogManager.GetCurrentClassLogger().Debug("test logging");
        // LogManager.Flush();
    }
}

它在数据库中提供了以下条目:

nlog 数据库条目示例

You can call LogManager.Shutdown() before leaving your UnhandledExceptionTrapper method. This calls internally LogManager.Flush() which

Flush any pending log messages (in case of asynchronous targets) with the default timeout of 15 seconds.

see NSLog Flush documentation.

Additional Troubleshooting

In the debug console, error messages are displayed if, for example, SQL errors occur on the connection, but by default you do not see if you have an invalid configuration.

Since NLog offers extensive configuration options, it is easy to make a small configuration errors that results in no logging. A typical example would be an incorrect ConnectionString or DBProvider.

As an example, suppose you have configured an incorrect DBProvider.

You can e.g call

LogManager.GetCurrentClassLogger().Debug("test logging");
LogManager.Flush();

and it would just silently fail.

However, if you insert

LogManager.ThrowExceptions = true;

before the test log call, you will see appropriate messages in the debug console. For example, if you have an invalid DBProvider like Npgsql.NpgsqlConnection1, Npgsql (note the invalid 1 in it), you would see

Unhandled exception. NLog.NLogRuntimeException: Exception occurred in NLog
 ---> NLog.NLogRuntimeException: Target Database Target[nlog-db] failed to initialize.
 ---> System.TypeLoadException: Could not load type 'Npgsql.NpgsqlConnection1' from assembly 'Npgsql'.

which would give a clear indication of what went wrong.

More Diagnostics

To see even more diagnostics, you can add the following lines:

InternalLogger.LogToConsole = true;
InternalLogger.LogLevel = LogLevel.Trace;

Among other things, you can see when the connection is opened, what data is written and information about flushing, a small sample excerpt:

2022-03-11 08:47:56.8428 Trace DatabaseTarget(Name=nlog-db): Open connection.
2022-03-11 08:47:57.0275 Trace DatabaseTarget(Name=nlog-db): Executing Text: insert into "public"."log_table"(time_stamp,level,logger,message,stacktrace) values(CAST(@time_stamp AS timestamp),@level,@logger,@message,@stacktrace);
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@time_stamp' = '2022-03-11T08:47:56.837' (String)
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@level' = 'Debug' (String)
2022-03-11 08:47:57.0380 Trace   DatabaseTarget: Parameter: '@logger' = 'ConsoleDBLog.Program' (String)
2022-03-11 08:47:57.0395 Trace   DatabaseTarget: Parameter: '@message' = 'test logging' (String)
2022-03-11 08:47:57.0415 Trace   DatabaseTarget: Parameter: '@stacktrace' = '' (String)
2022-03-11 08:47:57.1099 Trace DatabaseTarget(Name=nlog-db): Finished execution, result = 1
2022-03-11 08:47:57.1111 Trace DatabaseTarget(Name=nlog-db): Close connection (KeepConnection = false).
2022-03-11 08:47:57.1167 Debug LogFactory Flush with timeout=15 secs

Self-Contained Example

using System;
using NLog;
using NLog.Targets;

namespace ConsoleDBLog;

internal static class Program
{
    private static ILogger? _logger;

    static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
    {
        _logger?.Error((Exception?) e.ExceptionObject, "unhandled exception");
        LogManager.Shutdown();
    }

    private static void Main()
    {
        SetupDB_NLOG();
        _logger = LogManager.GetCurrentClassLogger();
        AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
        throw new Exception("test");
    }

    static void SetupDB_NLOG()
    {
        DatabaseTarget target = new DatabaseTarget();
        target.Name = "nlog-db";

        target.DBProvider = "Npgsql.NpgsqlConnection, Npgsql";
        target.ConnectionString = "Server=127.0.0.1;Port=5432;User Id=stephan;Password=;Database=stephan;";
        target.CommandText =
            "insert into \"public\".\"log_table\"(time_stamp,level,logger,message,stacktrace) values(CAST(@time_stamp AS timestamp),@level,@logger,@message,@stacktrace);";

        var param = new DatabaseParameterInfo
        {
            Name = "@time_stamp",
            Layout = "${date:format=yyyy-MM-ddTHH\\:mm\\:ss.fff}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@level",
            Layout = "${level}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@logger",
            Layout = "${logger}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@message",
            Layout = "${message}"
        };
        target.Parameters.Add(param);

        param = new DatabaseParameterInfo
        {
            Name = "@stacktrace",
            Layout = "${exception:format=stacktrace}"
        };
        target.Parameters.Add(param);

        NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Debug);

        //Uncomment the following lines to see things that would silently fail and
        //to get more diagnostic debug output about what is actually running.
        
        // InternalLogger.LogToConsole = true;
        // InternalLogger.LogLevel = LogLevel.Trace;
        // LogManager.ThrowExceptions = true;

        // LogManager.GetCurrentClassLogger().Debug("test logging");
        // LogManager.Flush();
    }
}

Which gives the followoing entries in the DB:

nlog db entries example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文