Serilog 创建的默认文件编码是 utf-8 without BOM。如何在 appsettings.json 中配置 Serilog 以以 UTF-8-BOM 编码创建日志文件?
如果我添加 "encoding": "utf-8",则会收到错误“InvalidOperationException:未找到类型 UTF8。”
"WriteTo:Async": {
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
"Args": {
"path": "Logs/Log-.txt",
"rollOnFileSizeLimit": true,
"fileSizeLimitBytes": 5242880,
"retainedFileCountLimit": 31,
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] ({ThreadID}) [{SourceContext}] {Message}{NewLine}{Exception}",
"encoding": "utf-8",
"formatter": {
"type": "Serilog.Templates.ExpressionTemplate, Serilog.Expressions"
}
}
}
]
}
}
您指定编码的方式不正确。您必须提供一个有效的完全限定的现有编码类名称或继承现有的或创建一个自定义的。
在这种情况下,您只需要创建
System.Text.UTF8Encoding.
的派生类,请按照以下步骤操作:
System.Text.UTF8Encoding.
的派生类,在我们设置 true
参数的基本构造函数上传递 encoderShouldEmitUTF8Identifier
,这会将编码行为更改为 UTF-8 BOM 编码。using System.Text;
namespace MyApplication
{
public class UTF8WithBOMEncoding : UTF8Encoding
{
public UTF8WithBOMEncoding() : base(true) { }
}
}
appsettings.json
上指定要使用的编码类的 完整限定类名称和程序集名称 。如果您不提供这两个元素,内部类型解析将失败。{
"Name": "File",
"Args": {
"encoding": "MyApplication.UTF8WithBOMEncoding, MyApplication",
}
}
TL;DR 这说明这只是类型解析行为的解释
类型解析发生在这行代码中Serilog.Settings.Configuration - StringArgumentValue.cs.
var type = FindType(argumentValue.Trim());
if (type == null)
{
throw new InvalidOperationException($"Type {argumentValue} was not found.");
}
FindType
方法使用Type.GetType
方法,根据Microsoft文档,此方法将尝试解析当前正在执行的程序集或mscorlib.dll
或System.Private.CoreLib.dll.
中的类型搜索
internal static Type? FindType(string typeName)
{
var type = Type.GetType(typeName);
if (type == null)
{
if (!typeName.Contains(','))
{
type = Type.GetType($"{typeName}, Serilog");
}
}
return type;
}
因为我们的应用程序使用 Serilog 包来解析 Serilog 配置,所有操作都发生在 Serilog 程序集的上下文中,这是因为我们必须显式提供自定义编码类存在的程序集名称。