.net 如何在Serilog中使用ExpressionTemplate格式化所有日期时间条目?

4szc88ey  于 2023-01-18  发布在  .NET
关注(0)|答案(1)|浏览(186)

我目前正在使用ExpressionTemplate自定义日志格式,但无法找到正确的方式来格式化所有日期时间类型的条目。

builder.Host.UseSerilog((context, services, configuration) => 
{
    configuration.ReadFrom.Configuration(context.Configuration);
    configuration.ReadFrom.Services(services);
    configuration.Enrich.FromLogContext();
    configuration.WriteTo.Console(new ExpressionTemplate("{ {Time:ToString(UtcDateTime(@t),'yyyy-MM-dd HH:mm:ss.ff'), @mt, @r, @l, @x, ..@p} }\n"));
});

...

using(var scope = app.Services.CreateScope())
{
    var logger = scope.ServiceProvider.GetService<ILogger<Program>>();
    logger.LogInformation("{@Now}, {@UtcNow}", DateTime.Now, DateTime.UtcNow);
}

//{"Time":"2023-01-12 02:48:35.44","@mt":"{@Now}, {@UtcNow}","@l":"Information","Now":"2023-01-12T11:48:35.0203770+09:00","UtcNow":"2023-01-12T02:48:35.4406010Z","SourceContext":"Program"}

如您所见,“Time”使用ToString进行了正确的格式化,但其他的没有,我希望它像.. {"Time":"2023-01-12 02:48:35.44","@mt":"{@Now}, {@UtcNow}","@l":"Information","Now":"**2023-01-12 02:48:35.44**","UtcNow":"**2023-01-12 02:48:35.44**","SourceContext":"Program"}
我试过IFormatProvider来解决这个问题,

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, services, configuration) => 
{
    configuration.ReadFrom.Configuration(context.Configuration);
    configuration.ReadFrom.Services(services);
    configuration.Enrich.FromLogContext();
    configuration.WriteTo.Console(new ExpressionTemplate("{ {Time:ToString(UtcDateTime(@t),'yyyy-MM-dd HH:mm:ss.ff'), @mt, @r, @l, @x, ..@p} }\n", new CustomDateFormat()));
});

public class CustomDateFormat : IFormatProvider, ICustomFormatter
{
   public object GetFormat(Type formatType)
   {
      if (formatType == typeof(ICustomFormatter))
         return this;
      else
         return null;
   }

   public string Format(string fmt, object arg, IFormatProvider formatProvider)
   {
        if (arg is DateTime dt) return dt.ToString("yyyy-MM-dd HH:mm:ss.ff");

        if (arg is DateOnly dateOnly) return dateOnly.ToString("yyyy-MM-dd");

        if (arg is TimeOnly timeOnly) return timeOnly.ToString("HH:mm:ss.fff");

        //is timespan
        return ((TimeSpan)arg).ToString();
   }
}

但结果是一样的。我如何使用ExpressionTemplate格式化所有日期时间条目?

km0tfn4u

km0tfn4u1#

您可以使用ILogEventEnricher并创建自己的DateTimeFormatter丰富器。

public class DateTimeFormatter : ILogEventEnricher
{
    private readonly string _dateTimeFormat;
    public DateTimeFormatter(string dateTimeFormat)
    {
        _dateTimeFormat = dateTimeFormat;
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var properties = logEvent.Properties.ToList();
        foreach (var property in properties)
        {
            if (property.Value is ScalarValue scalarValue && scalarValue.Value is DateTime dateTime)
            {
                logEvent.RemovePropertyIfPresent(property.Key);
                logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(property.Key, dateTime.ToString(_dateTimeFormat)));
            }
        }
    }
}

然后像这样将DateTimeFormatter传入LoggerConfiguration
x一个一个一个一个x一个一个二个x

相关问题