Serilog中没有异常堆栈跟踪的日志



我在MVC5应用程序中使用SerilogSerilog.Exceptions进行结构化日志记录。

我想从& Exception"的值中删除堆栈跟踪。日志中的字段。我知道我在RollingFile接收器中使用new JsonFormatter(),因此异常对象,例如ex,被格式化为ex.ToString(),整个对象被原样写入。

我使用new DestructuringOptionsBuilder().WithDefaultDestructurers()在"ExceptionDetails"中显示堆栈跟踪

是否可能只看到异常的名称作为" exception "字段的日志,而不是整个堆栈跟踪和其他细节作为ex.ToString(),而写到JSON文件接收器?

下面是我的异常日志:

{
"Timestamp": "2021-09-02T15:04:02.4469999+05:00",
"Level": "Error",
"MessageTemplate": "Unhandled Exception",
"Exception": "System.NullReferenceException: Object reference not set to an instance of an object.rn   at AppV2.Controllers.BaseController.Initialize(RequestContext requestContext) in E:\Workspace\AppV2\AppV2\Controllers\BaseController.cs:line 115rn   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)rn   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()rn   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)rn   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)",
"Properties": {
"UserName": "adminuser@mail.com",
"ThreadId": 5,
"Caller": "AppV2.Extensions.Logger.LogError(System.Exception, System.String, System.Object[])",
"MachineName": "DESKTOP-GHV3V41",
"HttpRequestId": "e9922caf-7e25-47f8-9941-263ba1ec4278",
"HttpRequestNumber": 1,
"HttpRequestClientHostIP": "::1",
"HttpRequestType": "GET",
"HttpRequestRawUrl": "/",
"ExceptionDetails": {
"Type": "System.NullReferenceException",
"HResult": -2147467261,
"Message": "Object reference not set to an instance of an object.",
"Source": "Boilerplate.Web.Mvc5.Sample",
"StackTrace": "   at AppV2.Controllers.BaseController.Initialize(RequestContext requestContext) in E:\Workspace\AppV2\AppV2\Controllers\BaseController.cs:line 115rn   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)rn   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()rn   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)rn   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)",
"TargetSite": "Void Initialize(System.Web.Routing.RequestContext)"
}
}
}

这是我的Logger类:

public class Logger
{
private static readonly ILogger logger;
static Logger()
{
logger = new LoggerConfiguration()
.Enrich.WithUserName(anonymousUsername: "Not Authenticated")
.Enrich.FromLogContext()
.Enrich.With(new ThreadEnrich())
.Enrich.WithCaller()
.Enrich.WithMachineName()
.Enrich.WithHttpRequestId()
.Enrich.WithHttpRequestNumber()
.Enrich.WithHttpRequestClientHostIP()
.Enrich.WithHttpRequestType()
.Enrich.WithHttpRequestRawUrl()
.Enrich.WithMvcRouteData()
.Enrich.WithExceptionDetails(
new DestructuringOptionsBuilder()
.WithDefaultDestructurers())
.Enrich.WithDemystifiedStackTraces()
.WriteTo.RollingFile(new JsonFormatter(),
HttpContext.Current.Server.MapPath($"~/logs/log-.json"),
LogEventLevel.Debug,
fileSizeLimitBytes: 655360)
.CreateLogger();
}
public static void LogInformation(string info, object[] data = null)
{
logger.Information(info, data);
}
public static void LogDebug(string debug, object[] data = null)
{
logger.Debug(debug, data);
}
public static void LogWarning(string warning, object[] data = null, Exception e = null)
{
logger.Warning(e, warning, data);
}
public static void LogError(Exception e, string error, object[] data = null)
{
logger.Error(e, error, data);
}
}

任何关于我的Logger课程的建议也欢迎。

无论存在什么日志属性,"formatter "Serilog如何将标准日志信息(包括异常)转换为文本。

为了摆脱冗余,你需要使用JsonFormatter以外的东西。

如果您使用Serilog.Expressions,那么使用ExpressionTemplate很容易做到这一点。Serilog.Sinks.File的示例用法(其他接收器类似):

const string logTemplate = "{ { Timestamp: @t, Message: @m, Level: @l, Exception: ExceptionDetail, ..Rest() } }n";
Log.Logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.WriteTo.File(new ExpressionTemplate(logTemplate), "app.log")
.CreateLogger();

旧答案(不含Serilog.Expressions):

这是我使用的一个格式化器,它只是移动了&;exceptiondetails &;

namespace Serilog.Exceptions.Formatting;
using System.IO;
using Serilog.Events;
using Serilog.Exceptions.Core;
using Serilog.Formatting;
using Serilog.Formatting.Json;
/// <summary>
/// A JSON text formatter using structured properties for exceptions.
/// </summary>
/// <remarks>
/// Avoids the redundancy of <see cref="JsonFormatter"/> when used with <see cref="ExceptionEnricher"/>.
/// </remarks>
public class StructuredExceptionFormatter : ITextFormatter
{
private readonly string rootName;
private readonly JsonValueFormatter valueFormatter = new(typeTagName: null);
/// <summary>
/// Initializes a new instance of the <see cref="StructuredExceptionFormatter"/> class.
/// </summary>
/// <param name="rootName">The root name used by the enricher, if different from the default.</param>
public StructuredExceptionFormatter(string? rootName = null)
{
this.rootName = rootName ?? new DestructuringOptionsBuilder().RootName;
}
public void Format(LogEvent logEvent, TextWriter output)
{
output.Write("{"Timestamp":"");
output.Write(logEvent.Timestamp.UtcDateTime.ToString("O"));
output.Write("","Message":");
var message = logEvent.MessageTemplate.Render(logEvent.Properties);
JsonValueFormatter.WriteQuotedJsonString(message, output);
output.Write(","Level":"");
output.Write(logEvent.Level);
output.Write('"');
var propCount = logEvent.Properties.Count;
if (logEvent.Properties.TryGetValue(this.rootName, out var exceptionProperty))
{
output.Write(","Exception":");
this.valueFormatter.Format(exceptionProperty, output);
propCount--;
}
if (propCount > 0)
{
output.Write(","Properties":{");
var comma = false;
foreach (var property in logEvent.Properties)
{
if (property.Key == this.rootName)
{
continue;
}
if (comma)
{
output.Write(',');
}
else
{
comma = true;
}
JsonValueFormatter.WriteQuotedJsonString(property.Key, output);
output.Write(':');
this.valueFormatter.Format(property.Value, output);
}
output.Write("}");
}
output.WriteLine('}');
}
}

它将显示你的异常如下:

{
"Timestamp": "2021-09-02T15:04:02.4469999+05:00",
"Level": "Error",
"Message": "Unhandled Exception",
"Exception": {
"Type": "System.NullReferenceException",
"HResult": -2147467261,
"Message": "Object reference not set to an instance of an object.",
"Source": "Boilerplate.Web.Mvc5.Sample",
"StackTrace": "   at AppV2.Controllers.BaseController.Initialize(RequestContext requestContext) in E:\Workspace\AppV2\AppV2\Controllers\BaseController.cs:line 115rn   at System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState)rn   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)rn   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)rn   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()rn   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)rn   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)",
"TargetSite": "Void Initialize(System.Web.Routing.RequestContext)"
},
"Properties": {
"UserName": "adminuser@mail.com",
"ThreadId": 5,
"Caller": "AppV2.Extensions.Logger.LogError(System.Exception, System.String, System.Object[])",
"MachineName": "DESKTOP-GHV3V41",
"HttpRequestId": "e9922caf-7e25-47f8-9941-263ba1ec4278",
"HttpRequestNumber": 1,
"HttpRequestClientHostIP": "::1",
"HttpRequestType": "GET",
"HttpRequestRawUrl": "/"
}
}

我研究了一下,我认为你应该检查一下Serilog过滤器。例如,您可以过滤事件字段、源,甚至过滤具有特定值的数据。你可以通过在你的日志配置代码或JSON文件中配置相应的过滤器来做到这一点。

更多信息请参考此链接https://github.com/serilog/serilog-filters-expressions

最新更新