【问题标题】:Log all exception information for any kind of exception记录任何类型异常的所有异常信息
【发布时间】:2015-04-22 12:18:56
【问题描述】:

我正在使用 C#、ASP.NET MVC Web Api、Entity Framework 和 .NET Framework 4.0 进行开发。

我有这段代码来记录异常:

public void LogCompleteException(
    string controllerName,
    string actionName,
    Exception exception)
{
    string exceptionMessage = string.Empty;

    Exception e = exception;
    if (e.InnerException == null)
        e = null;
    else
        while (e.InnerException != null) e = e.InnerException;

    if (e == null)
        exceptionMessage = exception.Message;
    else
        exceptionMessage = string.Format("{0}\n\rInnerException: {1}", exception.Message, e.Message);

    _logger.ErrorFormat(
        LogTextFormatString,
        ExceptionText,
        controllerName,
        actionName,
        exceptionMessage);
}

但是在我的日志文件中我发现了这个:

一个或多个实体的验证失败。看 'EntityValidationErrors' 属性以获取更多详细信息。

当我写“有关更多详细信息,请参阅 'EntityValidationErrors' 属性”时,我只是展示了一个示例,我没有记录重要的属性。

有很多例外;但使用我的方法,我没有记录所有相关信息,因为可能存在我没有记录的“EntityValidationErrors”等属性。

当我传递异常来记录它时,我不知道它有什么属性,也不知道如何记录它的每个属性。

你知道完整记录异常的方法吗?我的代码不会出现带有EntityValidationErrors 属性或任何其他重要属性的异常。

我正在使用 log4net 进行日志记录。

【问题讨论】:

  • 我假设日志记录是通过 log4net 完成的?
  • 是的,我正在使用 log4net 登录。
  • 为什么不使用 exception.ToString()?
  • 你在 SO 上看到过similar posts 吗?假设您不想捕获 DbEntityValidationException 异常并自己创建完整的错误消息是否安全?
  • @Michael DbEntityValidationException exceptions 这只是一个例子,我可以获得多种异常并且没有任何重要信息。

标签: c# asp.net-mvc entity-framework exception log4net


【解决方案1】:

由于内部异常本身就是一个异常,也许您可​​以递归并重用已有的方法:

if (e.InnerException != null)
{
    LogCompleteException(controllerName, actionName, e.InnerException);
}

但是,如果这确实有效,您仍然会丢失 EntityValidationErrors。

我最近使用的另一种方法是显式捕获并记录发生的异常:

try
{
    db.Add(something);
    db.SaveChanges();
}
catch (DbEntityValidationException ex)
{
    StringBuilder sb = new StringBuilder();

    // collect some extra info about the exception before logging
    foreach (var eve in ex.EntityValidationErrors)
    {
        sb.AppendLine(String.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State));
        foreach (var ve in eve.ValidationErrors)
        {
            sb.AppendLine(String.Format("Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage));
        }
    }

    logger.Error("There was an error while trying to parse and save something!\n" + sb.ToString(), ex);
}

如果您想要 Exception.Data 字典条目,您也可以添加它们:

foreach (DictionaryEntry entry in ex.Data)
{
    // you will want to use a StringBuilder instead of concatenating strings if you do this
    exceptionMessage = exceptionMessage + string.Format("Exception.Data[{0}]: {1}", entry.Key, entry.Value);
}

至于自定义异常类的属性,就像 EntityValidationErrors 一样,我只会捕获并解析它们发生的地方。否则,您将不得不在每个异常类型上覆盖 ToString() 或使用一些反射黑客来枚举所有属性,这会严重地使日志与您不关心的属性混淆。

【讨论】:

  • 我想我的问题没有很好地解释。当我写“有关更多详细信息,请参阅 'EntityValidationErrors' 属性。”我正在展示一个我没有记录重要属性的示例。有很多类型的例外,我的方法并没有记录所有这些信息。
  • 你能举出更多关于“重要属性”的例子吗?大多数异常都将此数据存储在Exception.Data dictionary 中。虽然存在异常值(例如 EntityValidationErrors),您需要使用反射来枚举所有异常的属性或事先明确检查它们。对于这些异常值,最好的办法是在抛出时根据需要处理它们,例如在我的示例代码 IMO 中。
  • 我不能给你更多关于“导入属性”的例子,因为我不知道我必须记录什么样的异常。这就是为什么我要求完全记录异常,因为我想记录任何带有信息的属性。顺便说一句,我用while (e.InnerException != null) e = e.InnerException;这一行记录了最内心的IneerException
【解决方案2】:

您可以使用elmahlog4net appender。 Elmah 日志捕获所有异常并可以将它们记录到 log4net 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 2021-01-04
    • 1970-01-01
    • 2021-04-23
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多