解析带有转义字符的 key=values 字符串

Parse string of key=values with escaped characters

提问人:Camões 提问时间:10/20/2023 最后编辑:Ken WhiteCamões 更新时间:10/25/2023 访问量:66

问:

Loki 以键值格式输出以下日志,其结构如下:key1=value1 key2=value2

level=info ts=2023-10-20T14:30:48.716410806Z caller=metrics.go:159 component=frontend org_id=fake traceID=58290ebda8d79180 latency=fast query=\"sum by (level) (count_over_time({k8s_namespace=\\\"ingress-nginx\\\"} |= ``[1s]))\" query_hash=110010092 query_type=metric range_type=range length=15m0.001s start_delta=15m0.833402507s end_delta=832.40267ms step=1s duration=61.999532ms status=200 limit=1000 returned_lines=0 throughput=4.2MB total_bytes=260kB total_bytes_structured_metadata=0B lines_per_second=4209 total_lines=261 post_filter_lines=261 total_entries=1 store_chunks_download_time=0s queue_time=819.962996ms splits=2 shards=32 cache_chunk_req=0 cache_chunk_hit=0 cache_chunk_bytes_stored=0 cache_chunk_bytes_fetched=0 cache_chunk_download_time=0s cache_index_req=0 cache_index_hit=0 cache_index_download_time=0s cache_stats_results_req=0 cache_stats_results_hit=0 cache_stats_results_download_time=0s cache_result_req=0 cache_result_hit=0 cache_result_download_time=0s source=logvolhist

在 fluentd 中,我尝试使用带有 as 和 as 的标记制表符分隔值解析器解析此日志,并获得以下结果:delimiter_pattern/\s+/label_delimiter=

{
  "level": "info",
  "caller": "metrics.go:159",
  "component": "frontend",
  "org_id": "fake",
  "traceID": "58290ebda8d79180",
  "latency": "fast",
  "query": "\"sum",
  "(count_over_time({k8s_namespace": "\\\"ingress-nginx\\\"}",
  "|": "",
  "query_hash": "110010092",
  "query_type": "metric",
  "range_type": "range",
  ...
}

对于键,此解析器只能捕获第一个单词,并使用后面的空格作为另一个键值的分隔符。query

我尝试了不同的正则表达式和两个插件解析器(https://shihadeh.dev/ruby-gems/Key-ValueParser/https://github.com/fluent-plugins-nursery/fluent-plugin-kv-parser),但到目前为止没有运气。

是获得正确的正则表达式,使用不同的解析器,尝试取消转义字符还是其他问题?

正则表达式 解析 日志记录 Fluentd 可观测性

评论

0赞 InSync 10/21/2023
我不知道 Fluentd,但确实 (?<key>\w+)=(?<value>[^“\s]+(?!\S)|\\“(?:[^\\”]|\\{3}“)*\\”) 对你有用吗?如果是,我会写一个答案。请注意,这假设示例中的每个字符都是两个字符的序列,而不是一个转义的双引号。\"
0赞 CAustin 10/21/2023
如果您只是想匹配分隔符:\s(?=\w+=(\\")?.+?(?(1)\1(?=\s)))
0赞 Mark 10/21/2023
这不就是JSON吗?为什么需要正则表达式
0赞 CAustin 10/21/2023
@Mark 输出为 JSON。输入是用空格分隔的键/值对的单行列表。
0赞 Camões 10/22/2023
@InSync 这会很好,但要在 fluentd 中使用正则表达式解析器,我需要定义命名的捕获组。我认为您提供的示例将输出{“key”:“level”, “value”:“info”}。

答:

1赞 Camões 10/25/2023 #1
\s(?=\w+=(\\")?.+?(?(1)\1(?=\s)))

从 @CAustin 的评论来看,这个正则表达式的效果比delimiter_pattern/\s+/

额外

这是针对我关于 Fluentd 和日志解析的具体情况。同时,在更好地分析了 Fluentd 和 Fluent bit 之后,由于解析功能,我可能会改用 Fluent bit。

敬启者 :p