如何使用jq过滤器迭代提取每个{}块中的元素
实现Prometheus指标块的逐块迭代提取与处理
需求说明
现有以下两个Prometheus指标块:
{ __name__: sc_pcd_g2version, container: mgmtbroker, endpoint: vxexporter, instance: 10.42.24.132:9116, job: prometheus, namespace: delivery, pod: chn1-d1-ac-0, service: prometheus } { __name__: sc_pcd_g2version, container: mgmtbroker, endpoint: vxexporter, instance: 10.42.3.110:9116, job: prometheus, namespace: delivery, pod: chn1-d1-ia-0, service: prometheus }
需要通过jq过滤器迭代处理,第一次提取第一个{}块,第二次提取第二个{}块,并完善Shell代码实现逐块提取和每个指标的状态判断逻辑。
完善后的Shell代码
function get_prometheus_vector_value { local _RESULT # 动态获取向量元素总数 local count=$(echo "$1" | jq -r '. | length') for ((i=0; i<count; i++)); do # 提取每个元素的value(Prometheus向量value格式为[时间戳, 值]) echo $(echo "$1" | jq -r '.['$i'].value?') done } function get_prometheus_vector_metric { local _RESULT # 动态获取向量元素总数 local count=$(echo "$1" | jq -r '. | length') for ((i=0; i<count; i++)); do # 提取每个元素的metric元数据,转为紧凑格式 echo $(echo "$1" | jq -r '.['$i'].metric?' | xargs) done } # 设置退出处理函数 trap on_exit EXIT TERM # 处理命令行参数 process_command_line "$@" # 获取Prometheus原始查询结果 PROMETHEUS_RAW_RESULT="$( get_prometheus_raw_result )" # 解析Prometheus结果 if [[ "${PROMETHEUS_QUERY_TYPE}" = "scalar" ]]; then PROMETHEUS_RESULT=$( get_prometheus_scalar_result "$PROMETHEUS_RAW_RESULT" ) PROMETHEUS_METRIC=UNKNOWN else # 获取所有向量值,每行对应一个指标的value PROMETHEUS_VALUES=$( get_prometheus_vector_value "$PROMETHEUS_RAW_RESULT" ) # 获取所有指标元数据,每行对应一个指标的metric块 PROMETHEUS_METRICS=$( get_prometheus_vector_metric "$PROMETHEUS_RAW_RESULT" ) # 配对值和元数据,逐行处理每个指标 paste <(echo "$PROMETHEUS_VALUES") <(echo "$PROMETHEUS_METRICS") | while read -r val metric; do # 提取实际指标值(取value数组的第二个元素) PROMETHEUS_RESULT=$(echo "$val" | jq -r '.[1]') printf '当前指标值: %s\n' "${PROMETHEUS_RESULT}" # 格式化指标元数据为标准JSON块 FORMATTED_METRIC=$(echo "$metric" | jq -Rr 'scan("({[^}]*})") | .[0]') printf '当前指标元数据: %s\n' "${FORMATTED_METRIC}" # 数值校验与Nagios状态判断 if [[ ${PROMETHEUS_RESULT} =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then if eval [[ ${PROMETHEUS_RESULT} ${COMPARISON_METHOD} ${CRITICAL_LEVEL} ]]; then NAGIOS_STATUS=CRITICAL NAGIOS_SHORT_TEXT="${METRIC_NAME} 数值为 ${PROMETHEUS_RESULT}" elif eval [[ ${PROMETHEUS_RESULT} ${COMPARISON_METHOD} ${WARNING_LEVEL} ]]; then NAGIOS_STATUS=WARNING NAGIOS_SHORT_TEXT="${METRIC_NAME} 数值为 ${PROMETHEUS_RESULT}" else NAGIOS_STATUS=OK NAGIOS_SHORT_TEXT="${METRIC_NAME} 数值为 ${PROMETHEUS_RESULT}" fi else if [[ "${NAN_OK}" = "true" && "${PROMETHEUS_RESULT}" = "NaN" ]]; then NAGIOS_STATUS=OK NAGIOS_SHORT_TEXT="${METRIC_NAME} 数值为 ${PROMETHEUS_RESULT}" else NAGIOS_SHORT_TEXT="无法解析Prometheus响应" NAGIOS_LONG_TEXT="${METRIC_NAME} 的返回值为 ${PROMETHEUS_RESULT}" fi fi # 添加元数据到输出文本(如果开启) if [[ "${NAGIOS_INFO}" = "true" ]]; then NAGIOS_SHORT_TEXT="${NAGIOS_SHORT_TEXT} | 指标元数据: ${FORMATTED_METRIC}" fi # 添加性能数据(如果开启) if [[ "${PERFDATA}" = "true" ]]; then NAGIOS_SHORT_TEXT="${NAGIOS_SHORT_TEXT} | query_result=${PROMETHEUS_RESULT}" fi # 输出当前指标的处理结果 printf '%s: %s\n' "${NAGIOS_STATUS}" "${NAGIOS_SHORT_TEXT}" done fi
核心修改说明
- 动态迭代支持:通过
jq获取向量元素总数,不再硬编码循环次数,适配任意数量的指标块。 - 指标数据配对:将每个指标的value和metric分别按行输出,用
paste命令一一配对,确保处理时数据对应准确。 - 数值解析修复:针对Prometheus向量返回的
[timestamp, value]格式,提取第二个元素作为实际指标值。 - 循环逻辑修正:使用
while read逐行处理配对后的指标数据,实现每个{}块的单独提取与处理。 - 语法错误修复:移除原代码中无效的元数据提取语句,改为通过
jq scan准确提取每个{}块。
内容的提问来源于stack exchange,提问作者sree
相关产品推荐
相关产品推荐

