如何修改Serilog日志事件的时区?需切换至非默认系统时区
修改Serilog日志的时区设置
你遇到的问题确实存在:CultureInfo仅影响日期时间的显示格式,无法转换时区。要让Serilog用指定时区记录日志,需要对Timestamp做时区转换处理,以下是两种可行方案:
方案1:自定义格式化器(无需额外依赖)
通过实现ITextFormatter接口,在格式化日志事件时将Timestamp转换为目标时区:
- 定义自定义格式化器:
using Serilog; using Serilog.Events; using Serilog.Formatting; using System; using System.IO; public class TimeZoneTextFormatter : ITextFormatter { private readonly ITextFormatter _innerFormatter; private readonly TimeZoneInfo _targetTimeZone; public TimeZoneTextFormatter(ITextFormatter innerFormatter, TimeZoneInfo targetTimeZone) { _innerFormatter = innerFormatter; _targetTimeZone = targetTimeZone; } public void Format(LogEvent logEvent, TextWriter output) { // 将UTC时间转换为目标时区(若日志Timestamp是本地时间,改用TimeZoneInfo.ConvertTime) var convertedTimestamp = TimeZoneInfo.ConvertTimeFromUtc(logEvent.Timestamp.UtcDateTime, _targetTimeZone); // 创建替换了Timestamp的新日志事件 var adjustedLogEvent = new LogEvent( convertedTimestamp, logEvent.Level, logEvent.Exception, logEvent.MessageTemplate, logEvent.Properties ); _innerFormatter.Format(adjustedLogEvent, output); } }
- 配置Logger时使用该格式化器:
// 指定目标时区,例如东京时区 var targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"); // 基于原输出模板创建默认格式化器 var innerFormatter = new Serilog.Formatting.Display.MessageTemplateTextFormatter( "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}", null); Log.Logger = new LoggerConfiguration() .WriteTo.File( path: "Logs/logs-.txt", rollingInterval: RollingInterval.Month, formatter: new TimeZoneTextFormatter(innerFormatter, targetTimeZone)) .CreateLogger();
方案2:使用Serilog.Expressions扩展包(更简洁)
通过Serilog.Expressions包提供的内置函数直接在输出模板中转换时区,步骤如下:
- 安装NuGet包:
dotnet add package Serilog.Expressions
- 修改Logger配置:
Log.Logger = new LoggerConfiguration() .WriteTo.File( path: "Logs/logs-.txt", rollingInterval: RollingInterval.Month, // 使用TimeZoneConvert函数转换时区,替换为你需要的时区ID outputTemplate: "{TimeZoneConvert(Timestamp, 'Tokyo Standard Time'):yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}") .CreateLogger();
注意事项
- 时区ID可通过
TimeZoneInfo.GetSystemTimeZones()获取所有系统支持的时区列表。 - 若你的日志
Timestamp是系统本地时间(未启用Enrich.WithUtcTimestamp()),转换时需注意逻辑适配,避免时区转换错误。
内容的提问来源于stack exchange,提问作者Mateusz
相关产品推荐
相关产品推荐

