我在ASP.NET Core 3.1中使用Serilog elasticsearch接收器(版本8.4.1,elastic 7.8.0),配置如下:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Serilog.AspNetCore": "Information"
}
},
"Enrich": [ "FromLogContext" ],
"WriteTo": [
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "SourceContext = 'Serilog.AspNetCore.RequestLoggingMiddleware'"
}
}
],
"WriteTo": [
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://localhost:9200",
"indexFormat": "request-logs-{0:yyyy.MM.dd}",
"period": 1,
"connectionTimeout": 5,
"typeName": "_doc",
"inlineFields": true,
"restrictToMinimumLevel": "Information"
}
}
]
}
}
}
]
}
}
我正在使用Serilog.AspNetCore的RequestLogging
app.UseSerilogRequestLogging();
并使用需要对GeoSpatial和IP属性进行特殊映射的对象来丰富自定义中间件中的IDiagnosticContext
。
HttpDiagnostics diagnostics = new HttpDiagnostics
{
Host = host.ToString(),
IsHttps = isHttps,
LocalIp = localIpAddress,
LocalPort = localPort,
Protocol = protocol,
RemoteIp = remoteIpAddress,
RemotePort = remotePort,
RequestContentLength = requestContentLength,
RequestContentType = requestContentType,
Scheme = scheme,
UserAgent = userAgent,
ResponseContentLength = responseContentLength,
ResponseContentType = responseContentType
};
this.diagnosticContext.Set("Http", diagnostics, true);
我以对logevent中的字段进行正确映射而结束的方法是:使用我的自定义对象重塑LogEvent类型,并使用NEST客户端为索引模板创建映射。
ElasticClient client = new ElasticClient(new Uri(settings.Uri));
PutIndexTemplateResponse response = client.Indices.PutTemplate(
settings.Name,
p => p.IndexPatterns(settings.IndexPattern)
.Settings(s => s.DefaultPipeline("geoip"))
.Map<SerilogDiagnosticsLogEvent>(m => m.AutoMap()));
索引模板映射已正确创建
{
"_doc": {
"properties": {
"traceId": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"level": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"requestMethod": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"message": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"sourceContext": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"parentId": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"elapsed": {
"type": "double"
},
"spanId": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"@timestamp": {
"type": "date"
},
"requestId": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"http": {
"type": "object",
"properties": {
"responseContentLength": {
"type": "long"
},
"requestContentLength": {
"type": "long"
},
"geoIp": {
"type": "object",
"properties": {
"cityName": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"countryIsoCode": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"regionName": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"location": {
"type": "geo_point"
},
"continentName": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
}
}
},
"remoteIp": {
"type": "ip"
},
"localPort": {
"type": "integer"
},
"scheme": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"remotePort": {
"type": "integer"
},
"userAgent": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"protocol": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"responseContentType": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"host": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"isHttps": {
"type": "boolean"
},
"localIp": {
"type": "ip"
},
"requestContentType": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
}
}
},
"connectionId": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"messageTemplate": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"requestPath": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"statusCode": {
"type": "integer"
}
}
}
}
因此,现在我期望Serilog索引的文档将使用我创建的索引模板的映射。但是实际发生的是,创建的索引没有使用模板中的正确映射。因此,IP字段被索引为字符串,这导致GeoIp管道无法在这些字段上工作。
现在我要问自己:我的配置有问题吗? Serilog是否始终使用THEIR映射为日志事件建立索引?如何在logevent中将正确的映射应用于自定义属性?
答案 0 :(得分:0)
因此,如本Github问题https://github.com/serilog/serilog-sinks-elasticsearch/issues/366 ...
中所述证明使用NEST客户端创建的索引模板映射,使用驼峰式表示属性名称,而LogEvent上的自定义属性以pascal形式表示,这触发了弹性搜索的动态映射并导致重复的映射项
编辑
您可以通过使用映射属性注释模型的属性并将名称设置为pascal-case来解决此问题。