c#简化的方法将异常线编号纳入Serilog

发布于 2025-02-10 04:11:05 字数 2233 浏览 2 评论 0原文

我正在使用Serilog使用此代码来将异常的行编写到我的日志中。这里的问题是行号是将异常放在捕获块中而不是发生异常的实际线路的地方。

问题

try
{
  //line: 2
     throw new Exception();

}
catch(Exception ex)
{
    //line: 15
       Log.Here().Error(ex, "Hello, world!");
   //Serilog will log the exception line as line 15 instead of line 2 
   //which doesn't help me at all if I have 100s of lines of code 
   //that could throw an actual exception
}

这是我当前的serilog代码,

public static class LoggerExtensions
{
    public static ILogger Here(this ILogger logger,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0) {
        return logger
            .ForContext("MemberName", memberName)
            .ForContext("FilePath", sourceFilePath)
            .ForContext("LineNumber", sourceLineNumber);
    }
}

我在我的每个类中都使用这样的Serilog代码,还需要简化以接受任何T型T类,但这是另一天的另一个问题:

     Serilog.Log.ForContext<T>()

//类

private static Serilog.ILogger Log => Serilog.Log.ForContext<MyClass>();

// in the method
Log.Here().Information("Hello, world!");


var outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";

Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Warning()
            .Enrich.FromLogContext()
            .WriteTo.RollingFile("log/{Date}.log", outputTemplate, LogEventLevel.Warning)
            .WriteTo.Console(LogEventLevel.Warning, outputTemplate, theme: AnsiConsoleTheme.Literate)
            .CreateLogger();

部分解决方案

这是我用来找到最初发生异常的实际线路的代码。而不是在每个捕获块中一遍又一遍地使用这3行代码(stacktrace,frax,line),而是想找到一种使用它的方法,并自动将其正确附加到Serilog输出模板上。

catch(Exception ex)
{
   var stackTrace = new StackTrace(ex, true);
   var frame = stackTrace.GetFrame(0);
   var line = frame.GetFileLineNumber();// This is what I need as the actual line number
   Log.Here().Error(ex, $"Exception occured on line # {line}"); //This works but doesn't follow the output template pattern
}

I am using this code using serilog to get write the line number of the exception into my logs. The problem here is the line number is where the exception is thrown in the catch block and not the actual line where the exception occurred.

The Problem

try
{
  //line: 2
     throw new Exception();

}
catch(Exception ex)
{
    //line: 15
       Log.Here().Error(ex, "Hello, world!");
   //Serilog will log the exception line as line 15 instead of line 2 
   //which doesn't help me at all if I have 100s of lines of code 
   //that could throw an actual exception
}

This is my current Serilog code

public static class LoggerExtensions
{
    public static ILogger Here(this ILogger logger,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0) {
        return logger
            .ForContext("MemberName", memberName)
            .ForContext("FilePath", sourceFilePath)
            .ForContext("LineNumber", sourceLineNumber);
    }
}

I use like this in each of my classes which also needs to be streamlined to accept any type T but that is another question for another day:

     Serilog.Log.ForContext<T>()

// at the beginning of the class

private static Serilog.ILogger Log => Serilog.Log.ForContext<MyClass>();

// in the method
Log.Here().Information("Hello, world!");


var outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";

Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Warning()
            .Enrich.FromLogContext()
            .WriteTo.RollingFile("log/{Date}.log", outputTemplate, LogEventLevel.Warning)
            .WriteTo.Console(LogEventLevel.Warning, outputTemplate, theme: AnsiConsoleTheme.Literate)
            .CreateLogger();

The Partial Solution

Here is the code that I use to find the actual line where the exception originally occurred. Instead of using these 3 lines of code(stacktrace,frame,line) over and over and over in each catch block I want to find a way to use it once and automatically append it to the serilog output template correctly.

catch(Exception ex)
{
   var stackTrace = new StackTrace(ex, true);
   var frame = stackTrace.GetFrame(0);
   var line = frame.GetFileLineNumber();// This is what I need as the actual line number
   Log.Here().Error(ex, 
quot;Exception occured on line # {line}"); //This works but doesn't follow the output template pattern
}

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

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

发布评论

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

评论(2

半岛未凉 2025-02-17 04:11:05

只需将代码从捕获块移动到您的“ there()”方法中

public static class LoggerExtensions
{
    public static ILogger Here(this ILogger logger,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0) {
      
       var stackTrace = new StackTrace(ex, true);
       var frame = stackTrace.GetFrame(0);
       var line = frame.GetFileLineNumber();

        return logger
            .ForContext("MemberName", memberName)
            .ForContext("FilePath", sourceFilePath)
            .ForContext("LineNumber", **line**);
    }
}

,这样就简单地将方法称为相同

Log.Here(ex).Error(ex, "Hello, world!");

,或者您只需将日志直接写入该方法中

public static class LoggerExtensions
    {
        public static ILogger Here(this ILogger logger, Exception ex, string message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0) {
          
           var stackTrace = new StackTrace(ex, true);
           var frame = stackTrace.GetFrame(0);
           var line = frame.GetFileLineNumber();
            
                LogContext.PushProperty("MemberName", memberName)
                LogContext.PushProperty("FilePath", sourceFilePath)
                LogContext.PushProperty("LineNumber", **line**);
          Log.Error(ex, message);
        }
    }

,然后只需调用

Log.Here(ex, "Hello, world!");

Just move the code from the catch block into your "Here()" method as such

public static class LoggerExtensions
{
    public static ILogger Here(this ILogger logger,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0) {
      
       var stackTrace = new StackTrace(ex, true);
       var frame = stackTrace.GetFrame(0);
       var line = frame.GetFileLineNumber();

        return logger
            .ForContext("MemberName", memberName)
            .ForContext("FilePath", sourceFilePath)
            .ForContext("LineNumber", **line**);
    }
}

then simple just call the method as the same

Log.Here(ex).Error(ex, "Hello, world!");

or you can just write the log directly in the method as such

public static class LoggerExtensions
    {
        public static ILogger Here(this ILogger logger, Exception ex, string message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0) {
          
           var stackTrace = new StackTrace(ex, true);
           var frame = stackTrace.GetFrame(0);
           var line = frame.GetFileLineNumber();
            
                LogContext.PushProperty("MemberName", memberName)
                LogContext.PushProperty("FilePath", sourceFilePath)
                LogContext.PushProperty("LineNumber", **line**);
          Log.Error(ex, message);
        }
    }

and simply call as so

Log.Here(ex, "Hello, world!");
咽泪装欢 2025-02-17 04:11:05

caller信息 .NET 4.5。这将进行编译,这是必须手动检查堆栈跟踪的很大进步。

    public void Log(string message,
            [CallerFilePath] string filePath = "",
            [CallerLineNumber] int lineNumber = 0)
    {
        // Do logging
    }

Caller Information has been added to .NET 4.5. This will be compiled, a big improvement over having to examine the stack trace manually.

    public void Log(string message,
            [CallerFilePath] string filePath = "",
            [CallerLineNumber] int lineNumber = 0)
    {
        // Do logging
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文