将异常位置获取到记录器方法中,而无需解析堆栈



我想将所有错误日志记录合并到一个方法中,当我们处理异常时,该方法可以从我的应用程序中调用。我有一些尴尬的约束,我将在下面描述。

   public void Log(Exception ex)
   {
        string innerMessage = "";
        if (ex.InnerException != null)
        {
            innerMessage = ex.InnerException.Message;
        }
        Console.WriteLine($"Message: {ex.Message} # Location: { ex.StackTrace} # InnerMessasge: {innerMessage}" );
    }

我之前解析过堆栈,但代码最终变得丑陋,并且根据堆栈的不同,它可能会搞砸。

我真正想要的是抛出异常的位置,类和方法或位置的类和行。确保整个事情整齐地放在日志中的一行上。

您不需要自己解析异常,您可以使用 StackTrace 类从异常中获取易于理解的堆栈跟踪:

try
{
    int.Parse("dd");
}
catch (Exception e)
{
    var s = new StackTrace(e); // Gets the stack trace where the exception was thrown not where it was caught.
    var frame = s.GetFrame(0);
    var sourceMethod = frame.GetMethod();
    Console.WriteLine($"Method: {sourceMethod.Name} - Class {sourceMethod.DeclaringType.FullName} : Location: {frame.GetILOffset()}");
}
您可以从框架中获取

其他信息,例如文件、行、列(如果可用(,也可以沿着堆栈向上查找您的一个类而不是框架类(您可以从StrackTrace中获取所有框架并找到您需要的框架(。

.

Net 有一些非常有用的调用方成员属性,可用于此类操作。 将它们放在方法上,编译器会将值设置为调用该方法的成员名称、行号或文件路径。

public void Log(Exception ex, [CallerFilePath]string callerFilePath = null, [CallerMemberName]string callerMemberName = null, [CallerLineNumber]int callerLineNumber = 0)
{
    Console.WriteLine($"Message: {ex.Message} # File: {callerFilePath} # Line: {callerLineNumber} # Member: {callerMemberName}"  );
}

因此,每次调用 Log 方法时,都会获得调用该方法的行号和文件路径。 这也非常便宜,因为编译器将它们作为常量插入,而不必通过反射将它们拉出。

请注意,此日志是调用 Log 方法的位置,而不是引发异常的原始位置,但根据您的需要,这可能就足够了。

从生产角度解决这种混乱的有效方法之一是将其放在事件查看器中的所有日志中,而不是放在控制台中。

除此之外,下面形成组织错误非常有帮助。

        public void Log(Exception ex)
           {
         // Create an instance of StringBuilder. This class is in System.Text namespace
                StringBuilder sbExceptionMessage = new StringBuilder();
                sbExceptionMessage.Append("Exception Type" + Environment.NewLine);
                // Get the exception type
                sbExceptionMessage.Append(exception.GetType().Name);
                // Environment.NewLine writes new line character - n
                sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine);
                sbExceptionMessage.Append("Message" + Environment.NewLine);
                // Get the exception message
                sbExceptionMessage.Append(exception.Message + Environment.NewLine + Environment.NewLine);
                sbExceptionMessage.Append("Stack Trace" + Environment.NewLine);
                // Get the exception stack trace
                sbExceptionMessage.Append(exception.StackTrace + Environment.NewLine + Environment.NewLine);
                // Retrieve inner exception if any
                Exception innerException = exception.InnerException;
                // If inner exception exists
                while (innerException != null)
                {
                    sbExceptionMessage.Append("Exception Type" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.GetType().Name);
                    sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine);
                    sbExceptionMessage.Append("Message" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.Message + Environment.NewLine + Environment.NewLine);
                    sbExceptionMessage.Append("Stack Trace" + Environment.NewLine);
                    sbExceptionMessage.Append(innerException.StackTrace + Environment.NewLine + Environment.NewLine);
                    // Retrieve inner exception if any
                    innerException = innerException.InnerException;
    }
}

现在,sbExceptionMessage包含异常的每个详细信息,您甚至可以使用它轻松地将相同的日志添加到事件查看器或任何特定的文本文件或控制台。决定权在你。

最新更新