我有以下格式的数据。键在所有元素之间都是唯一的。
{
"backend1": {
"product1": {
"subservice1": {
"env1": {
"KMS": "0.21",
"DynamoDB": "235.91",
"ElastiCache": "108.85",
"Elastic Load Balancing": "324.29"
},
"env2": {
"KMS": "0.21",
"Elastic Load Balancing": "3.78"
}
}
}
},
"backend2": {
"product2": {
"subservice2": {
"env1": {
"KMS": "0.21",
"ElastiCache": "108.85",
"Elastic Load Balancing": "41.18"
},
"env2": {
"KMS": "0.21",
"Elastic Load Balancing": "3.78"
}
}
}
}
}
我想遍历键并将JSON转换为Prometheus度量格式。
aws_cost{env="env1",aws_service="KMS",product="product1",backend="backend1",subservice="subservice1"} 0.21
aws_cost{env="env1",aws_service="DynamoDB",product="product1",backend="backend1",subservice="subservice1"} 235.91
aws_cost{env="env1",aws_service="ElastiCache",product="product1",backend="backend1",subservice="subservice1"} 108.85
.....
我发现可以使用.[] | .[] | .[] | .[]
来获得不同索引处的键,但是我不知道如何使用嵌套的for循环来生成上述数据。我愿意接受其他解决方案。
答案 0 :(得分:3)
由于对象的键确定了不同的值,因此,如果将这些值传入流中,则可以做得很好。然后,只需解析路径的各个部分并构建结果即可。
流,解析然后输出。
$ jq --stream -r '
select(length == 2) as [[$backend, $product, $subservice, $env, $aws_service], $value]
| {$env, $aws_service, $product, $backend, $subservice}
| "aws_cost{\([to_entries[] | "\(.key)=\(.value|tojson)"] | join(","))} \($value)"
' input.json
aws_cost{env="env1",aws_service="KMS",product="product1",backend="backend1",subservice="subservice1"} 0.21
aws_cost{env="env1",aws_service="DynamoDB",product="product1",backend="backend1",subservice="subservice1"} 235.91
aws_cost{env="env1",aws_service="ElastiCache",product="product1",backend="backend1",subservice="subservice1"} 108.85
aws_cost{env="env1",aws_service="Elastic Load Balancing",product="product1",backend="backend1",subservice="subservice1"} 324.29
aws_cost{env="env2",aws_service="KMS",product="product1",backend="backend1",subservice="subservice1"} 0.21
aws_cost{env="env2",aws_service="Elastic Load Balancing",product="product1",backend="backend1",subservice="subservice1"} 3.78
aws_cost{env="env1",aws_service="KMS",product="product2",backend="backend2",subservice="subservice2"} 0.21
aws_cost{env="env1",aws_service="ElastiCache",product="product2",backend="backend2",subservice="subservice2"} 108.85
aws_cost{env="env1",aws_service="Elastic Load Balancing",product="product2",backend="backend2",subservice="subservice2"} 41.18
aws_cost{env="env2",aws_service="KMS",product="product2",backend="backend2",subservice="subservice2"} 0.21
aws_cost{env="env2",aws_service="Elastic Load Balancing",product="product2",backend="backend2",subservice="subservice2"} 3.78
答案 1 :(得分:1)
我想出了两种方法,一种有点深奥,另一种有点蛮力。我同时提供了两者,以便您可以选择自己喜欢的(并尝试同时理解两者)。
神秘:
. as $data |
paths(scalars) | . as $path |
"aws_cost{env=\"\($path[3])\",aws_service=\"\($path[4])\",product=\"\($path[1])\",backend=\"\($path[0])\",subservice=\"\($path[2])\"} \($data | getpath($path))"
paths(scalars)
生成到输入中所有叶节点(不是对象或数组)的路径。每个路径都是一个像["backend1","product1","subservice1","env1","KMS"]
这样的数组。您可以看到我们的处理方法–使用路径本身来格式化标签列表,并使用getpath
来获取实际值。使用了一些as
改组,以便getpath
有权操作.
。
蛮力:
to_entries[] | .key as $backend | .value |
to_entries[] | .key as $product | .value |
to_entries[] | .key as $subservice | .value |
to_entries[] | .key as $env | .value |
to_entries[] | .key as $service |
"aws_cost{env=\"\($env)\",aws_service\"\($service)\",product=\"\($product)\",backend=\"\($backend)\",subservice=\"\($subservice)\"} \(.value)"
to_entries
将对象转换成key
/ value
对的数组。例如,{"a":1,"b":2}
变为[{"key":"a","value:1},{"key":"b","value":2}]
。我们可以使用它来遍历每个级别的键,使用as
捕获键以供以后使用,然后将值放在.
中以进行进一步迭代。然后,当我们到达最底层时,它只是字符串格式。
任何一种都应与jq -r
一起运行,以使输出字符串不会被重新编码为JSON。