【问题标题】:logging exception in c#在 C# 中记录异常
【发布时间】:2011-03-30 07:19:54
【问题描述】:

记录异常 下面的代码允许将异常的内容保存在文本文件中。在这里我只得到错误的描述。

但它并没有告诉我异常发生在哪里,发生在哪一行。 谁能告诉我如何才能做到这一点,以便我什至可以获取发生异常的行号?

#region WriteLogError
/// <summary>
/// Write an error Log in File
/// </summary>
/// <param name="errorMessage"></param>
public void WriteLogError(string errorMessage)
{
  try
  {
    string path = "~/Error/" + DateTime.Today.ToString("dd-mm-yy") + ".txt";
    if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(path)))
    {
      File.Create(System.Web.HttpContext.Current.Server.MapPath(path))
     .Close();
    }
    using (StreamWriter w = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path)))
    {
      w.WriteLine("\r\nLog Entry : ");
      w.WriteLine("{0}", DateTime.Now.ToString(CultureInfo.InvariantCulture));
      string err = "Error in: " + System.Web.HttpContext.Current.Request.Url.ToString() 
                 + ". Error Message:" + errorMessage;
      w.WriteLine(err);
      w.WriteLine("__________________________");
      w.Flush();
      w.Close();
    }
  }
  catch (Exception ex)
  {
    WriteLogError(ex.Message);
  }

}

#endregion

【问题讨论】:

  • 附带说明,此代码不是线程安全的,IIS 是多线程环境。
  • 在你的 catch 块中递归调用 WriteLogError() 是一个非常糟糕的主意......
  • @jeroenh:无法使用更多相同的日志记录来报告日志记录期间的失败。一种替代方法是使用事件日志,这很痛苦但很有用。另一种是要么默默地忽略它,要么终止进程。

标签: c# exception logging


【解决方案1】:

我发现在 C# 中记录异常最简单的方法是调用ToString() 方法:

try
{

}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

这通常会为您提供所需的所有信息,例如错误消息和堆栈跟踪,以及任何额外的异常特定上下文信息。 (但请注意,如果您的应用程序使用调试信息编译,堆栈跟踪只会显示源文件和行号)

值得注意的是,查看完整的堆栈跟踪可能会让用户感到相当反感,因此您应该尽可能尝试处理异常并打印出更友好的错误消息。

另一方面 - 您应该用功能齐全的日志框架(如 Serilog)替换您的方法 WriteLogError,而不是尝试编写自己的方法。

您的日志记录方法不是线程安全的(您的日志文件可能最终会出现相互混合的日志消息),并且如果您捕获到异常,也绝对不应该调用自身 - 这意味着在记录时发生的任何异常错误可能会导致难以诊断的 StackOverflow 异常。

我可以建议如何解决这些问题,但是使用适当的日志记录框架会更好地为您服务。

【讨论】:

  • 关于使用 log4net 的好建议。这是避免这些线程安全问题的最简单方法。
  • 虽然我现在可能建议使用 NLog,而不是 log4net。也就是说,两者都很棒!
  • @davewasthere Serilog 是我选择的新日志框架
【解决方案2】:

只需登录ToString()。它不仅会为您提供堆栈跟踪,还会包括内部异常。

【讨论】:

  • 请注意,如果他想要行号,他也需要分发调试符号(但我认为可以使用 ilmerge 将它们合并到 exe 中)。
  • @Bobby:行号很好,但是常规的堆栈跟踪至少会给出方法名称,而且通常很多。
  • 没错,但他明确要求他们。
  • @Bobby:你说得对,他做到了。然而,他的代码根本没有显示堆栈跟踪,所以我认为这是更深层次的问题。行号很好,不过我完全赞成。
【解决方案3】:

此外,例如,当您将代码的发布版本部署到生产环境时,请不要忘记在发布包中包含 .pdb 文件。您需要该文件来获取例外代码的行号(请参阅How much information do pdb files contain? (C# / .NET)

【讨论】:

  • 所以,这就是他们的目的。
【解决方案4】:

您的解决方案非常好。我经历了同样的阶段
并且最终需要记录越来越多(它会来......):

  • 记录源位置
  • 异常前的调用堆栈(可能在不同的地方)
  • 所有内部异常以相同方式处理
  • 进程ID/线程ID
  • 时间(或请求滴答声)
  • 用于网络 - url、http 标头、客户端 ip、cookie、网络会话内容
  • 其他一些关键变量值
  • 在内存中加载程序集
  • ...

最好是我点击发生错误的文件链接的方式,
或单击调用堆栈中的链接,Visual Studio 在适当的位置打开。
(当然,您需要做的只是 *.PDB 文件,其中来自 IL 代码的路径
到你在 C# 中发布的源代码被存储。)

所以我终于开始使用这个解决方案:
它以Nuget package - Desharp 的形式存在。
它适用于两种应用程序类型 - Web 和桌面。
请参阅 Desharp Github documentation。它有很多配置选项。

try {
    var myStrangeObj = new { /*... something really mysterious ...*/ };
    throw new Exception("Something really baaaaad with my strange object :-)");
} catch (Exception ex) {

    // store any rendered object in debug.html or debug.log file
    Desharp.Debug.Log(myStrangeObj, Desharp.Level.DEBUG);

    // store exception with all inner exceptions and everything else
    // you need to know later in exceptions.html or exceptions.log file
    Desharp.Debug.Log(ex);
}

它具有 HTML 日志格式,每个异常都在一行中,
从 html 页面你可以在浏览器中打开,你可以点击
在文件链接上并转到 Visual Studio - 这真的很容易上瘾!
只需要安装这个Desharp editor opener

在此处查看一些演示:

尝试检查任何这些存储库并通过上述方式记录一些内容。
然后您可以在~/Logs 目录中看到记录的结果。大多数情况下,任何东西都是可配置的。

【讨论】:

    【解决方案5】:

    我只是回答问题,其他人已经提到过代码。如果您希望在日志中包含行号,则需要在部署到服务器时包含生成的调试文件 (pdb)。如果它只是您的开发/测试区域,那很好,但我不建议在生产中使用。

    【讨论】:

      【解决方案6】:

      请注意异常类是可序列化的。这意味着您可以使用内置的 XmlSerializer 轻松地将异常类写入磁盘 - 或使用自定义序列化程序写入 txt 文件。

      记录到输出当然可以通过使用 ToString() 来完成,而不是像其他答案中提到的那样只读取错误消息。

      异常类

      https://docs.microsoft.com/en-us/dotnet/api/system.exception?redirectedfrom=MSDN&view=netframework-4.7.2

      关于序列化的信息,将对象转换为磁盘上文件的行为,反之亦然。

      https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-04
        • 2013-08-31
        • 2019-04-09
        • 1970-01-01
        • 2010-10-02
        相关资源
        最近更新 更多