.NET Core API中Serilog结合Azure Table Storage自定义日志字段
解决方案
完全不用编写自定义sink,Serilog的Azure Table Storage Sink本身就支持将对象属性扁平化存储为单独列,具体实现步骤如下:
1. 安装依赖包
确保项目中安装以下NuGet包:
Install-Package Serilog.AspNetCore Install-Package Serilog.Sinks.AzureTableStorage
2. 保留你的LogDetail类
维持自定义类的定义不变,示例如下:
public class LogDetail { public string CallingMethod { get; set; } public string AuthenticatedUser { get; set; } public string StackTrace { get; set; } public string CallingApp { get; set; } }
3. 配置Serilog启用属性扁平化
在Program.cs(或Startup.cs)中配置Serilog时,开启FlattenObjects选项,Sink会自动将对象的每个属性展开为单独列:
var builder = WebApplication.CreateBuilder(args); // 配置Serilog builder.Host.UseSerilog((context, config) => { config.WriteTo.AzureTableStorage( connectionString: context.Configuration["AzureTableStorage:ConnectionString"], storageTableName: "ApiLogs", flattenObjects: true // 关键配置:启用对象扁平化 ) .Enrich.FromLogContext() .ReadFrom.Configuration(context.Configuration); }); // 其他API配置逻辑 var app = builder.Build();
4. 记录日志时注入LogDetail属性
在需要记录日志的位置,通过LogContext.PushProperty将LogDetail的属性(或整个对象)添加到日志上下文:
方式一:逐个推送属性(无前缀列名)
var logDetail = new LogDetail { CallingMethod = "WeatherForecast.Get", AuthenticatedUser = User.Identity?.Name, StackTrace = Environment.StackTrace, CallingApp = "MyDotNetApi" }; using (LogContext.PushProperty("CallingMethod", logDetail.CallingMethod)) using (LogContext.PushProperty("AuthenticatedUser", logDetail.AuthenticatedUser)) using (LogContext.PushProperty("StackTrace", logDetail.StackTrace)) using (LogContext.PushProperty("CallingApp", logDetail.CallingApp)) { Log.Information("API request processed"); }
这种方式下,Azure Table中会直接生成CallingMethod、AuthenticatedUser等独立列。
方式二:推送整个对象(带前缀列名)
因为已启用flattenObjects,直接推送整个LogDetail对象,Sink会自动展开属性,生成带前缀的列名(如LogDetail_CallingMethod):
var logDetail = new LogDetail { CallingMethod = "WeatherForecast.Get", AuthenticatedUser = User.Identity?.Name, StackTrace = Environment.StackTrace, CallingApp = "MyDotNetApi" }; using (LogContext.PushProperty("LogDetail", logDetail, destructureObjects: true)) { Log.Information("API request processed"); }
5. 注意事项
- Azure Table Storage列名不能包含
/、\、#等特殊字符,确保LogDetail的属性名称符合要求 - 若属性值为复杂类型,扁平化后会自动转换为字符串形式
- 可结合Serilog的Enricher全局注入通用属性(如
AuthenticatedUser),避免重复代码
内容的提问来源于stack exchange,提问作者achilles
相关产品推荐
相关产品推荐

