You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grafana LogQL如何从JSON数组的键值对象中提取标签

解决方案

方案1:调整ASP.NET日志输出配置(优先推荐)

从根源解决Scopes数组嵌套的问题,无需修改业务代码,仅调整日志注册配置即可将Scope内的键值对直接扁平化输出到日志JSON根节点:

使用.NET内置JSON控制台日志

.ConfigureLogging(logging =>
{
    logging.ClearProviders();
    logging.AddJsonConsole(options =>
    {
        options.JsonWriterOptions = new JsonWriterOptions { Indented = false };
        options.IncludeScopes = true;
        // 关键配置:将Scope键值对直接展开到JSON根,不再嵌套在Scopes数组中
        options.FlattenScope = true;
    });
})

使用Serilog日志组件

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext() // 自动提取LogScope的键值对作为日志属性
    .WriteTo.Console(new JsonFormatter())
    .CreateLogger();

配置完成后输出的日志JSON将直接包含MsgId、EventName、EntityKeyValue等字段,查询时无需再从Scopes数组中解析,完美规避索引变动、Scope缺失的问题。


方案2:查询侧兼容处理(无法修改日志输出时使用)

如果没有权限调整日志输出配置,可以使用各托管日志服务的内置查询函数实现无索引提取,无需自定义插件:

Kusto(Azure Monitor/Application Insights)

YourLogTable
// 展开Scopes数组的所有元素
| mv-expand scope = Scopes
// 展开每个Scope的键值对为单独字段
| evaluate bag_unpack(scope)
// 按单条日志唯一标识分组,合并同一条日志的所有Scope属性,缺失字段自动留空
| summarize arg_max(TimeGenerated, *) by 日志唯一标识字段组合
// 直接使用提取后的字段
| project TimeGenerated, LogLevel, MsgId, EventName, EntityKeyValue

Loki(LogQL)

{job="你的服务job名"} 
| json 
// 遍历所有Scope提取目标字段作为标签
| label_format MsgId="{{ range .Scopes }}{{ if .MsgId }}{{ .MsgId }}{{ end }}{{ end }}",
                EventName="{{ range .Scopes }}{{ if .EventName }}{{ .EventName }}{{ end }}{{ end }}",
                EntityKeyValue="{{ range .Scopes }}{{ if .EntityKeyValue }}{{ .EntityKeyValue }}{{ end }}{{ end }}"

Elasticsearch(DSL)

使用runtime_fields动态提取字段,无需修改索引Mapping:

{
  "runtime_mappings": {
    "MsgId": {
      "type": "keyword",
      "script": "for (def scope : doc['Scopes']) { if (scope.containsKey('MsgId')) { emit(scope.MsgId); break; } }"
    },
    "EventName": {
      "type": "keyword",
      "script": "for (def scope : doc['Scopes']) { if (scope.containsKey('EventName')) { emit(scope.EventName); break; } }"
    }
  },
  "query": {"match_all": {}},
  "fields": ["MsgId", "EventName", "EntityKeyValue"]
}

以上方案的核心逻辑都是遍历Scopes数组的所有元素匹配目标键,无需固定数组索引,缺失字段自动返回空值,完全适配你提到的两个问题场景。

内容的提问来源于stack exchange,提问作者Robert L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:39:03