Serilog 在 Android Release 把对象记成类名,检查裁剪开关
Android Release 的 Serilog 日志可能失去对象字段,保留反射元数据仍无效。4.3.1/4.4.0 会在 PublishTrimmed 下关闭默认结构化分支;可为明确类型写限定字段的解构策略,而不是全局反射所有对象。
同一份 Android.NET 应用,Debug 发往 Seq 的日志含对象字段,Release 却只剩类名;用 ByTransforming 转成匿名对象后,又可能变成一整段字符串。若已确认开启裁剪,要检查 Serilog 自己的结构化功能开关,而不只检查业务类型的属性是否被保留。
这条现象有 Android.NET 9、Serilog 4.3.0/4.3.1、Serilog.Sinks.Seq 9.0.0 的具体组合。当前正式 Serilog 4.4.0 的相关转换与构建目标仍相同;不能把所有 Release 日志差异都归因于 Seq 序列化或网络传输。
元数据存在,默认转换分支也可能不可用
Serilog 在 PublishTrimmed=true 时,通过构建目标将 Serilog.Capturing.IsStructureValueSupported 设为 false。PropertyValueConverter 的默认结构转换受此开关保护,相关代码可以在裁剪时被去掉。
因此,给业务程序集或类型加保留声明,不等于重新启用这段已经被功能开关关闭的实现。也不能只在运行时尝试把开关设回 true,就认定发布产物中被移除的代码和所有反射信息会回来。
普通对象没能进入结构转换后,后备分支可能调用 ToString() 并记录为标量。匿名对象的 ToString 看起来像带字段的文本,但它仍是字符串;Seq 中“看上去有 JSON”不代表事件里真有可查询的结构字段。
为明确的日志类型直接构造结构值
对已知且确实需要记录的类型,可以让自定义策略直接产生 Serilog 的 StructureValue,不再依赖默认反射扫描。下面的 C# 示例仅选取两个获准字段,类型名和字段请按应用真实日志模型调整:
using Serilog.Core;
using Serilog.Events;
public sealed record AuditEvent(int OrderId, string Stage);
public sealed class AuditEventPolicy : IDestructuringPolicy
{
public bool TryDestructure(
object value,
ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue result)
{
if (value is not AuditEvent item)
{
result = null!;
return false;
}
result = new StructureValue(new[]
{
new LogEventProperty("OrderId", new ScalarValue(item.OrderId)),
new LogEventProperty("Stage", new ScalarValue(item.Stage))
});
return true;
}
}
在现有 LoggerConfiguration 调用 CreateLogger 之前登记;以下是接入片段,原来的 sink、级别和过滤配置继续由应用构造:
loggerConfiguration.Destructure.With(new AuditEventPolicy());
再通过既有 logger 使用解构标记记录这个类型:
logger.Information("Audit {@Event}", new AuditEvent(42, "accepted"));
Serilog 会先尝试已登记的解构策略,再走默认的结构转换。因此,这条路径不要求先把对象变成匿名对象,也没有遍历任意对象的所有公开属性。策略只匹配 AuditEvent,其他类型返回 false,继续交给原来的处理链。
如果需要嵌套字段、集合或其他类型,应逐项明确其输出契约,不要把这段代码扩大为无差别反射解构器。也不要把整个业务实体直接投影到日志,顺带增加原本没有批准输出的字段。
用真实 Release 产物检查结构,而非显示文本
带 {@Event} 的模板与普通 {Event} 含义不同,接入时保留解构标记,并确认策略登记在真正使用的 logger 上。若使用 DI 或宿主统一建 logger,只在旁边新建一个配置对象不会影响现有日志入口。
验收沿原 Android Release 发布流程进行,查看接收端的原始事件数据:Event 应是包含 OrderId 与 Stage 的结构值,字段可按预期查询,而不只是显示为一段字符串。再检查不匹配类型仍走原规则、字段范围没有扩大、日志级别与输出位置未变。
关闭裁剪可以作为区分构建路径的受控对照,但它改变应用体积与发布特性,不能当作所有 Android 产品的通用交付方案。若后续采用新的正式 Serilog 实现,先复核实际发布产物的开关、转换入口和事件结构,再决定是否移除专用策略。


