从消息和异常中删除新行
Remove new lines from Message and Exception
我在 Asp 点网核心应用程序中使用 Serilog。我希望我的日志文件是人类可读的,但也能够很容易地被解析。
我遇到的问题是用换行符记录异常。某些 Microsoft 活动的消息包含换行符。
我希望能够用每行一个事件来解析日志文件。
我可以编写自己的 ITextFormatter 实现,用 \r\n 替换新行,但这意味着我需要复制 MessageTemplateTextFormatter 和其他 类.[=10 中的大部分逻辑=]
您没有指定如何记录异常,但假设您使用的是:
Log.Error("An error occurred: {Exception}", exception);
然后将使用 ToString() 呈现异常。在那种情况下,你不能简单地这样做:
Log.Error("An error occurred: {Exception}", exception.ToString().Replace(System.Environment.NewLine, "\r\n"));
当然,如果您需要在多个地方执行此操作,您可以将其重构为一个方法(也许是一个扩展方法)。
在深入研究了一段时间之后,我得出了一个答案。 Andy West 的回答为我指明了正确的方向。
这里有两个不同的问题:消息中的 CRLF 和异常中的 CRLF。
我能够通过将输出模板中的“{Message}”更改为“{Message:j}”来解决消息问题。
更改异常有点棘手。我不得不添加一个浓缩剂:
class ExceptionEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.Exception == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedException", logEvent.Exception.ToString().Replace("\r\n", "\r\n"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
}
这添加了新的 属性 调用 EscapedException。必须使用 .Enrich.With().
将其添加到配置中
然后我在 outputTemplate 中将“{Exception}”替换为“{EscapedException}”。
此技术将删除所有 CRLF。首先是一个新的 ITextFormatter。
public class RemoveCrLf : ITextFormatter
{
private const int DefaultWriteBuffer = 256;
private readonly ITextFormatter _textFormatter;
/// <summary>
///
/// </summary>
/// <param name="textFormatter"></param>
public RemoveCrLf(ITextFormatter textFormatter)
{
_textFormatter = textFormatter;
}
/// <summary>
///
/// </summary>
/// <param name="logEvent"></param>
/// <param name="output"></param>
public void Format(LogEvent logEvent, TextWriter output)
{
var buffer = new StringWriter(new StringBuilder(DefaultWriteBuffer));
_textFormatter.Format(logEvent, buffer);
var logText = buffer.ToString();
output.WriteLine(logText.Trim().Replace("\n","\n").Replace("\r","\r"));
output.Flush();
}
}
这样使用
configuration.WriteTo.Console(new RemoveCrLf(new MessageTemplateTextFormatter("[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Exception}")));
当然,根据需要自定义输出模板。
参考@Andrew Radford 的解决方案,该解决方案仅适用于 windows,但不适用于预期的 linux docker 环境。所以
我已经增强了消息和异常的解决方案。
我使用 Environment.NewLine 在 Regex 中进行大小写匹配,它将根据托管环境选择大小写。
为消息添加以下 class。
public class MessageEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.MessageTemplate == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedMessage", Regex.Replace(logEvent.MessageTemplate.ToString(), Environment.NewLine, "[Newline]"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
}
使用以下 class 作为例外。
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.Exception == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedException", Regex.Replace(logEvent.Exception.ToString(), Environment.NewLine, "[Newline]"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
然后将这两个 helper classes 添加到 program.cs
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.With(new ExceptionEnricher())
.Enrich.With(new MessageEnricher())
.Enrich.FromLogContext()
.CreateLogger();
更新应用程序设置输出模板
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u4} {SourceContext:l} : {EscapedMessage}{NewLine}{EscapedException}{NewLine}"
我在 Asp 点网核心应用程序中使用 Serilog。我希望我的日志文件是人类可读的,但也能够很容易地被解析。
我遇到的问题是用换行符记录异常。某些 Microsoft 活动的消息包含换行符。
我希望能够用每行一个事件来解析日志文件。
我可以编写自己的 ITextFormatter 实现,用 \r\n 替换新行,但这意味着我需要复制 MessageTemplateTextFormatter 和其他 类.[=10 中的大部分逻辑=]
您没有指定如何记录异常,但假设您使用的是:
Log.Error("An error occurred: {Exception}", exception);
然后将使用 ToString() 呈现异常。在那种情况下,你不能简单地这样做:
Log.Error("An error occurred: {Exception}", exception.ToString().Replace(System.Environment.NewLine, "\r\n"));
当然,如果您需要在多个地方执行此操作,您可以将其重构为一个方法(也许是一个扩展方法)。
在深入研究了一段时间之后,我得出了一个答案。 Andy West 的回答为我指明了正确的方向。
这里有两个不同的问题:消息中的 CRLF 和异常中的 CRLF。
我能够通过将输出模板中的“{Message}”更改为“{Message:j}”来解决消息问题。
更改异常有点棘手。我不得不添加一个浓缩剂:
class ExceptionEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.Exception == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedException", logEvent.Exception.ToString().Replace("\r\n", "\r\n"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
}
这添加了新的 属性 调用 EscapedException。必须使用 .Enrich.With().
将其添加到配置中然后我在 outputTemplate 中将“{Exception}”替换为“{EscapedException}”。
此技术将删除所有 CRLF。首先是一个新的 ITextFormatter。
public class RemoveCrLf : ITextFormatter
{
private const int DefaultWriteBuffer = 256;
private readonly ITextFormatter _textFormatter;
/// <summary>
///
/// </summary>
/// <param name="textFormatter"></param>
public RemoveCrLf(ITextFormatter textFormatter)
{
_textFormatter = textFormatter;
}
/// <summary>
///
/// </summary>
/// <param name="logEvent"></param>
/// <param name="output"></param>
public void Format(LogEvent logEvent, TextWriter output)
{
var buffer = new StringWriter(new StringBuilder(DefaultWriteBuffer));
_textFormatter.Format(logEvent, buffer);
var logText = buffer.ToString();
output.WriteLine(logText.Trim().Replace("\n","\n").Replace("\r","\r"));
output.Flush();
}
}
这样使用
configuration.WriteTo.Console(new RemoveCrLf(new MessageTemplateTextFormatter("[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Exception}")));
当然,根据需要自定义输出模板。
参考@Andrew Radford 的解决方案,该解决方案仅适用于 windows,但不适用于预期的 linux docker 环境。所以 我已经增强了消息和异常的解决方案。
我使用 Environment.NewLine 在 Regex 中进行大小写匹配,它将根据托管环境选择大小写。
为消息添加以下 class。
public class MessageEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.MessageTemplate == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedMessage", Regex.Replace(logEvent.MessageTemplate.ToString(), Environment.NewLine, "[Newline]"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
}
使用以下 class 作为例外。
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent.Exception == null)
return;
var logEventProperty = propertyFactory.CreateProperty("EscapedException", Regex.Replace(logEvent.Exception.ToString(), Environment.NewLine, "[Newline]"));
logEvent.AddPropertyIfAbsent(logEventProperty);
}
然后将这两个 helper classes 添加到 program.cs
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.With(new ExceptionEnricher())
.Enrich.With(new MessageEnricher())
.Enrich.FromLogContext()
.CreateLogger();
更新应用程序设置输出模板
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u4} {SourceContext:l} : {EscapedMessage}{NewLine}{EscapedException}{NewLine}"