无法将JSON格式API响应转换为Prometheus可读格式求助
问题描述
我有一个JSON格式的API响应,想要转换成Prometheus可读的指标格式,但用jq尝试转换后失败,Prometheus报错:"INVALID" is not a valid start token。API响应内容如下:
{ "version": "3.0.0", "gauges": { "gc.G1-Old-Generation.count": { "value": 0 }, "gc.G1-Old-Generation.time": { "value": 0 }, "gc.G1-Young-Generation.count": { "value": 30 }, "gc.G1-Young-Generation.time": { "value": 427 }, "jvm.name": { "value": "7@hubstorage" }, "jvm.uptime": { "value": 44799 }, "jvm.vendor": { "value": "Azul Systems, Inc. OpenJDK 64-Bit Server VM 11.0.8+10-LTS (11)" }, "memory.heap.committed": { "value": 208666624 }, "memory.heap.init": { "value": 65011712 }, "memory.heap.max": { "value": 1035993088 }, "memory.heap.usage": { "value": 0.11967882164094129 }, "memory.heap.used": { "value": 123986432 }, "memory.non-heap.committed": { "value": 114434048 }, "memory.non-heap.init": { "value": 7667712 }, "memory.non-heap.max": { "value": -1 }, "memory.non-heap.usage": { "value": -108223704 }, "memory.non-heap.used": { "value": 108223704 }, "memory.pools.CodeHeap-'non-nmethods'.committed": { "value": 2555904 }, "memory.pools.CodeHeap-'non-nmethods'.init": { "value": 2555904 }, "memory.pools.CodeHeap-'non-nmethods'.max": { "value": 5832704 }, "memory.pools.CodeHeap-'non-nmethods'.usage": { "value": 0.23114905196629212 }, "memory.pools.CodeHeap-'non-nmethods'.used": { "value": 1348224 }, "memory.pools.CodeHeap-'non-profiled-nmethods'.committed": { "value": 3670016 }, "memory.pools.CodeHeap-'non-profiled-nmethods'.init": { "value": 2555904 }, "memory.pools.CodeHeap-'non-profiled-nmethods'.max": { "value": 122912768 }, "memory.pools.CodeHeap-'non-profiled-nmethods'.usage": { "value": 0.029816007398027193 }, "memory.pools.CodeHeap-'non-profiled-nmethods'.used": { "value": 3664768 }, "memory.pools.CodeHeap-'profiled-nmethods'.committed": { "value": 12517376 }, "memory.pools.CodeHeap-'profiled-nmethods'.init": { "value": 2555904 }, "memory.pools.CodeHeap-'profiled-nmethods'.max": { "value": 122912768 }, "memory.pools.CodeHeap-'profiled-nmethods'.usage": { "value": 0.10141253998933618 }, "memory.pools.CodeHeap-'profiled-nmethods'.used": { "value": 12464896 }, "memory.pools.Compressed-Class-Space.committed": { "value": 12267520 }, "memory.pools.Compressed-Class-Space.init": { "value": 0 }, "memory.pools.Compressed-Class-Space.max": { "value": 1073741824 }, "memory.pools.Compressed-Class-Space.usage": { "value": 0.010960675776004791 }, "memory.pools.Compressed-Class-Space.used": { "value": 11768936 }, "memory.pools.G1-Eden-Space.committed": { "value": 118489088 }, "memory.pools.G1-Eden-Space.init": { "value": 15728640 }, "memory.pools.G1-Eden-Space.max": { "value": -1 }, "memory.pools.G1-Eden-Space.usage": { "value": 0.6548672566371682 }, "memory.pools.G1-Eden-Space.used": { "value": 77594624 }, "memory.pools.G1-Old-Gen.committed": { "value": 82837504 }, "memory.pools.G1-Old-Gen.init": { "value": 49283072 }, "memory.pools.G1-Old-Gen.max": { "value": 1035993088 }, "memory.pools.G1-Old-Gen.usage": { "value": 0.0376950159729251 }, "memory.pools.G1-Old-Gen.used": { "value": 39051776 }, "memory.pools.G1-Survivor-Space.committed": { "value": 7340032 }, "memory.pools.G1-Survivor-Space.init": { "value": 0 }, "memory.pools.G1-Survivor-Space.max": { "value": -1 }, "memory.pools.G1-Survivor-Space.usage": { "value": 1 }, "memory.pools.G1-Survivor-Space.used": { "value": 7340032 }, "memory.pools.Metaspace.committed": { "value": 83423232 }, "memory.pools.Metaspace.init": { "value": 0 }, "memory.pools.Metaspace.max": { "value": -1 }, "memory.pools.Metaspace.usage": { "value": 0.9467012738130309 }, "memory.pools.Metaspace.used": { "value": 78976880 }, "memory.total.committed": { "value": 323100672 }, "memory.total.init": { "value": 72679424 }, "memory.total.max": { "value": 1035993087 }, "memory.total.used": { "value": 232210136 }, "threads.blocked.count": { "value": 0 }, "threads.count": { "value": 34 }, "threads.daemon.count": { "value": 14 }, "threads.deadlock.count": { "value": 0 }, "threads.deadlocks": { "value": [] }, "threads.new.count": { "value": 0 }, "threads.runnable.count": { "value": 11 }, "threads.terminated.count": { "value": 0 }, "threads.timed_waiting.count": { "value": 17 }, "threads.waiting.count": { "value": 6 } }, "counters": { "counter": { "count": 1 } }, "histograms": { "histogram": { "count": 3, "max": 100, "mean": 41.66666666666666, "min": 5, "p50": 20, "p75": 100, "p95": 100, "p98": 100, "p99": 100, "p999": 100, "stddev": 41.69998667732268 } }, "meters": { "meter": { "count": 201, "m15_rate": 38.666674566183616, "m1_rate": 22.433012859955905, "m5_rate": 35.77324719371856, "mean_rate": 4.944024762580441, "units": "events/second" } }, "timers": {} }
解决方案
Prometheus只接受文本格式的指标(每行一个指标,格式为metric_name{labels} value),直接返回JSON会触发"INVALID" is not a valid start token错误。以下是用jq将JSON转换为Prometheus可读格式的完整命令:
curl -s "你的API地址" | jq -r ' # 处理数值型Gauges,替换指标名中的特殊字符 .gauges | to_entries[] | select(.value.value | type == "number") | (.key | gsub("[\\-'\''\"]"; "_")) + " " + (.value.value | tostring), # 将JVM字符串信息转换为Prometheus info类型指标 "jvm_info{name=\"\(.gauges."jvm.name".value)\", vendor=\"\(.gauges."jvm.vendor".value | gsub("\""; "\\\""))\"} 1", # 处理Counters .counters | to_entries[] | (.key + "_count") + " " + (.value.count | tostring), # 处理Histograms,转换为Prometheus Summary格式(包含分位数) .histograms | to_entries[] | (.key + "_count") + " " + (.value.count | tostring), (.key + "_sum") + " " + ((.value.mean * .value.count) | tostring), (.key + "_min") + " " + (.value.min | tostring), (.key + "_max") + " " + (.value.max | tostring), (.key + "_stddev") + " " + (.value.stddev | tostring), (.key + "{quantile=\"0.5\"}") + " " + (.value.p50 | tostring), (.key + "{quantile=\"0.75\"}") + " " + (.value.p75 | tostring), (.key + "{quantile=\"0.95\"}") + " " + (.value.p95 | tostring), (.key + "{quantile=\"0.98\"}") + " " + (.value.p98 | tostring), (.key + "{quantile=\"0.99\"}") + " " + (.value.p99 | tostring), (.key + "{quantile=\"0.999\"}") + " " + (.value.p999 | tostring), # 处理Meters .meters | to_entries[] | (.key + "_count") + " " + (.value.count | tostring), (.key + "_m1_rate") + " " + (.value.m1_rate | tostring), (.key + "_m5_rate") + " " + (.value.m5_rate | tostring), (.key + "_m15_rate") + " " + (.value.m15_rate | tostring), (.key + "_mean_rate") + " " + (.value.mean_rate | tostring) '
关键说明
- 指标名规范:Prometheus不允许指标名包含
-、'等特殊字符,所以用gsub将这些字符替换为_。 - 字符串指标处理:JVM名称、厂商这类字符串值,转换为Prometheus的
info类型指标(值固定为1,信息存在标签中)。 - Histogram转换:原JSON中的histogram包含分位数,这里转换为Prometheus的Summary格式,保留分位数统计。
- 错误原因:
"INVALID" is not a valid start token是因为Prometheus收到的不是预期的文本指标格式,必须确保转换后的输出每行都是符合规范的指标行。
Prometheus采集配置
要让Prometheus采集转换后的指标,可通过以下两种方式:
- 使用Exec Exporter:配置Exec Exporter执行上述curl+jq命令,暴露指标端口给Prometheus。
- Node Exporter Textfile Collector:将转换后的指标写入Node Exporter的textfile目录,由Node Exporter暴露给Prometheus。
内容的提问来源于stack exchange,提问作者shaheer01
相关产品推荐
相关产品推荐

