azure-service-fabric - ELK 堆栈未将内部解构属性接收为已解构,但作为转义字符串
问题描述
我不确定这是否是 Serilog、ELK、Service Fabric、代码或配置问题。
我正在编写 Service Fabric 无状态服务。我的日志记录配置行是这样的:
Logger = new LoggerConfiguration()
.WriteTo.EventFlow(loggingOptions.DiagnosticPipeline)
.Destructure.With<JsonNetDestructuringPolicy>()
.Enrich.FromLogContext()
.CreateLogger()
.ForContext(properties);
...其中 properties 是 PropertyEnricher 数组,Policy 来自Destructurama 的 JsonNetDestructuringPolicy。
我有一个成功解构的自定义对象基类,所以如果我称它为数据,那么在 ELK 的 JSON 选项卡中我看到:
"payload": {
"Data": {
"Property1": "Prop Value",
"Property2": "Prop2 Value"
}
}
但是,当其中一个内部对象也被解构时,它会作为转义的 JSON 字符串发送,而不是被解构,属性名称周围没有引号:
"payload": {
"Data": {
"Property1": "Prop Value",
"DestructuredProp": "{InnerProperty: \"Inner Value\"}"
}
}
我的预期是:
"payload": {
"Data": {
"Property1": "Prop Value",
"DestructuredProp": {
"InnerProperty": "Inner Value"
}
}
}
我不知道为什么没有给内部属性名称加上引号,或者为什么整个值被转义和引用而不是解构。我已经验证我的解构代码正在执行。例如,我可以手动在属性名称周围添加引号,但这只会导致内部值中出现更多转义引号。
我自己的代码直接从 C# 解构它。我认为这可能是我的解构代码中的一个错误,所以我环顾四周,发现了Destructurama 的 JsonNetDestructuringPolicy,所以我尝试了,用 JObject.fromObject() 转换我的对象,但同样的事情发生了。
我很确定我应该能够用 Serilog 做到这一点。如果它不能做超过一层的深度,我认为不会有深度限制设置。为什么这不起作用?我尝试在 Kibana 中刷新字段索引,但 JSON 视图显示了转义字符串,所以我很确定它发送不正确,并且不是 ELK 问题。
- -编辑 - -
这是我尝试过的解构策略。我的初始对象是 JsonEvent,它有一个没有解构的 Dictionary,即使成功调用了 Dictionayr 策略。
public class JsonEventDestructuringPolicy : IDestructuringPolicy
{
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
{
if (value is JsonEvent jsonEvent)
{
var properties = new List<LogEventProperty>();
foreach (var property in value.GetType().GetProperties())
{
var propertyValue = property.GetValue(value);
var isCollection = propertyValue is ICollection<Dictionary<string,string>>;
var isDictionary = propertyValue is Dictionary<string,string>;
if (isCollection)
LoggingContext.Message("Found collection of dictionary: " + property.Name);
else if (isDictionary)
LoggingContext.Message("Found dictionary: " + property.Name);
else if (property.Name.Equals("Parameters"))
LoggingContext.Message("Found Parameters: " + propertyValue.GetType());
if (propertyValue != null)
properties.Add(new LogEventProperty(property.Name, propertyValueFactory.CreatePropertyValue(propertyValue, isCollection || isDictionary)));
}
result = new StructureValue(properties);
return true;
}
if (value is Dictionary<string, string> dictionary)
{
var properties = new List<LogEventProperty>();
foreach (var kvp in dictionary)
{
if (!string.IsNullOrWhiteSpace(kvp.Value))
properties.Add(new LogEventProperty("\"" + kvp.Key + "\"", propertyValueFactory.CreatePropertyValue(kvp.Value)));
}
result = new StructureValue(properties);
return true;
}
result = null;
return false;
}
}
它被这样调用:
public static void Message(JsonEvent message)
{
Logger.ForContext(GetEnrichers(message))
.Information(message.Event);
}
private static IEnumerable<ILogEventEnricher> GetEnrichers(JsonEvent message)
{
return new List<ILogEventEnricher>()
.Add("Data", message, true)
.Add("CorrelationId", ServiceTracingContext.CorrelationId)
.Add("CorrelationDateTime", ServiceTracingContext.CorrelationDateTime)
.Add("RouteTemplate", ServiceTracingContext.RouteTemplate)
.ToArray();
}
解决方案
推荐阅读
- cors - 无法从 google drive API 检索高质量图像
- sql-server - 我可以声明 TOP 从另一个表中提取值吗
- wordpress - 如何在 woocommerce 中获取当前产品的类别?
- kdb - 函数在 kdb/q 中不返回值
- jquery - Ajax Query 不适用于 Laravel 中的范围滑块
- python - 运行`pythonw xx.py`时批处理停止运行
- spring - 匹配的通配符是严格的,但找不到元素“context:include-filter”的声明
- vb.net - 尝试查找然后以 VB 形式打开文件
- google-app-engine - GAE 邮件发送配额 = 100/天?
- angular - 单元测试失败:错误:超时 - 在指定的超时内未调用异步回调