Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Azure service fabric ELK堆栈未将内部destructured属性作为destructured接收,而是作为转义字符串接收_Azure Service Fabric_Elastic Stack_Serilog_Elk - Fatal编程技术网

Azure service fabric ELK堆栈未将内部destructured属性作为destructured接收,而是作为转义字符串接收

Azure service fabric ELK堆栈未将内部destructured属性作为destructured接收,而是作为转义字符串接收,azure-service-fabric,elastic-stack,serilog,elk,Azure Service Fabric,Elastic Stack,Serilog,Elk,我不确定这是否是Serilog、ELK、服务结构、代码或配置问题 我正在编写一个服务结构无状态服务。我的日志配置行如下所示: Logger = new LoggerConfiguration() .WriteTo.EventFlow(loggingOptions.DiagnosticPipeline) .Destructure.With<JsonNetDestructuringPolicy>()

我不确定这是否是Serilog、ELK、服务结构、代码或配置问题

我正在编写一个服务结构无状态服务。我的日志配置行如下所示:

            Logger = new LoggerConfiguration()
                .WriteTo.EventFlow(loggingOptions.DiagnosticPipeline)
                .Destructure.With<JsonNetDestructuringPolicy>()
                .Enrich.FromLogContext()
                .CreateLogger()
                .ForContext(properties);
但是,当其中一个内部对象也被解构时,它将作为转义JSON字符串发送,而不是被解构,属性名称周围没有引号:

"payload": {
  "Data": {
    "Property1": "Prop Value",
    "DestructuredProp": "{InnerProperty: \"Inner Value\"}"
  }
}
我所期望的是:

"payload": {
  "Data": {
    "Property1": "Prop Value",
    "DestructuredProp": {
      "InnerProperty": "Inner Value"
    }
  }
}
我不知道为什么内部属性名不加引号,或者为什么整个值被转义和引用,而不是被分解。 我已经确认我的解构代码正在执行。例如,我可以在属性名周围手动添加引号,但这只会在内部值中产生更多转义引号

我自己的代码直接从C#解构它。我认为这可能是我的解构代码中的一个bug,所以我四处寻找并发现了更多的问题,所以我尝试了用JObject.fromObject()转换我的对象,但同样的事情也发生在它身上

我很确定我应该能用Serilog做到这一点。我认为如果它不能做超过一层的深度,就不会有深度限制设置。为什么这样不行?我曾尝试刷新Kibana中的字段索引,但JSON视图显示了转义字符串,因此我非常确定它被错误发送,这不是ELK问题

---编辑---

这是我尝试过的一个解构策略。我的初始对象是JsonEvent,它有一个字典,它没有进行分解,即使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类jsoneventdeststructuringpolicy:IDestructuringPolicy
{
public bool TrydStructure(对象值、ILogEventPropertyValueFactory属性值工厂、out LogEventPropertyValueResult)
{
if(值为JsonEvent JsonEvent)
{
var properties=新列表();
foreach(value.GetType().GetProperties()中的var属性)
{
var propertyValue=property.GetValue(value);
var isCollection=propertyValue为ICollection;
var isDictionary=属性值为字典;
if(isCollection)
LoggingContext.Message(“找到字典集合:“+property.Name”);
else if(isDictionary)
LoggingContext.Message(“找到的字典:“+property.Name”);
else if(property.Name.Equals(“参数”))
LoggingContext.Message(“找到的参数:+propertyValue.GetType());
if(propertyValue!=null)
添加(新的LogEventProperty(property.Name,propertyValueFactory.CreatePropertyValue(propertyValue,isCollection | | isDictionary));
}
结果=新结构值(属性);
返回true;
}
if(值为字典)
{
var properties=新列表();
foreach(字典中的var kvp)
{
如果(!string.IsNullOrWhiteSpace(kvp.Value))
添加(新的LogEventProperty(“\”+kvp.Key+“\”,propertyValueFactory.CreatePropertyValue(kvp.Value));
}
结果=新结构值(属性);
返回true;
}
结果=空;
返回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();
        }
publicstaticvoid消息(JsonEvent消息)
{
Logger.ForContext(GetEnrichers(message))
.信息(信息、事件);
}
私有静态IEnumerable getEnricher(JsonEvent消息)
{
返回新列表()
.Add(“数据”,消息,真)
.Add(“CorrelationId”,ServiceTracingContext.CorrelationId)
.Add(“CorrelationDateTime”,ServiceTracingContext.CorrelationDateTime)
.Add(“RouteTemplate”,ServiceTracingContext.RouteTemplate)
.ToArray();
}

您希望被分解的东西,需要在配置中明确配置为“始终分解结构”,或者标记为
{@data}
-默认情况下不会分解到每个对象对不起,我应该包含我尝试过的内容。我的代码和JSonnedDestructuringPolicy都使用
propertyValueFactory.CreatePropertyValue(value,true)
,因此它被告知对值进行解构。此外,我知道它正在调用我的解构策略,因为我修改了它,在属性名称周围添加了引号,认为麋鹿把事情搞砸了,因为它不是有效的JSON。因此,正在调用destructuring类,我通过自己创建LogEventProperty列表并将其放入StructureValue中,手动创建了Destructured数据。但是,StructureValue仍然被转换为单个字符串。嗯,顶层@确实会影响分解的深度(每个类的分解策略也有深度限制)-底线是,我认为您看到的是当达到最大分解深度时会发生什么(我在谷歌上搜索
serilog depth limit destructuring
或类似内容),因此该对象不在消息本身中。默认深度为5,这只是第二级,因此Serilog不应该限制它本身。我尝试手动将其设置为5。我不确定顺序是否重要,因此我将其设置在Destructure.With()的任一侧调用,但它仍然被转换为字符串。我想知道问题是否与Serilog.Enrichers.Context有关。这是否会导致深度被忽略?您希望被分解的内容需要在配置中显式配置为“always destructure”,或者标记为
{@data}        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();
        }