2

{ __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 }

There are two block below how to iterate the below data block using jq filter which should pick on first iteration { 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 }

On second iteration, it should pick the second one { 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 }

The response of the above which needs to be later selected each {} block

The required output filtered and captured below. Now i am looking to select the first element {} block and then next iteration must select the next one.

function get_prometheus_vector_value {
  local _RESULT
  for i in 0 1
  do
    # return the value of the first element of the vector
    _RESULT=$(echo $1 | jq -r '.['$i'].value?')
    printf '%s' "${_RESULT}"
  done
}

function get_prometheus_vector_metric {

  local _RESULT
  for i in 0 1
  do
    # return the metric information of the first element of the vector
    _RESULT=$(echo $1 | jq -r '.['$i'].metric?' | xargs)
    printf '%s' "${_RESULT}"
  done
}

# set up exit function
trap on_exit EXIT TERM

# process the cli options
process_command_line "$@"

# get the raw query from prometheus
PROMETHEUS_RAW_RESULT="$( get_prometheus_raw_result )"


  # extract the metric value from the raw prometheus result
  if [[ "${PROMETHEUS_QUERY_TYPE}" = "scalar" ]]
  then
      PROMETHEUS_RESULT=$( get_prometheus_scalar_result "$PROMETHEUS_RAW_RESULT" )
      PROMETHEUS_METRIC=UNKNOWN
  else
      PROMETHEUS_VALUE=$( get_prometheus_vector_value "$PROMETHEUS_RAW_RESULT" )
      PROMETHEUS_RESULT=$( get_prometheus_scalar_result "$PROMETHEUS_VALUE" )
      printf 'PROMETHEUS_RESULT: %s\n' "${PROMETHEUS_RESULT}"

      PROMETHEUS_METRIC=$( get_prometheus_vector_metric "$PROMETHEUS_RAW_RESULT" )

      PROMETHEUS_METRIC=$(echo $PROMETHEUS_METRIC | jq -Rr 'scan("({[^}]*})")')
      printf 'PROMETHEUS_METRIC after scan: %s\n' "${PROMETHEUS_METRIC}"

  fi
for i in "$PROMETHEUS_METRIC"
do
  # check the value
  **PROMETHEUS_METRIC=$(echo $PROMETHEUS_METRIC) |jq .[1]**
  if [[ ${PROMETHEUS_RESULT} =~ ^-?[0-9]+$ ]]
  then
    if eval [[ ${PROMETHEUS_RESULT} -${COMPARISON_METHOD} ${CRITICAL_LEVEL} ]]
    then
      NAGIOS_STATUS=CRITICAL
      NAGIOS_SHORT_TEXT="${METRIC_NAME} is ${PROMETHEUS_RESULT}"
    elif eval [[ ${PROMETHEUS_RESULT} -${COMPARISON_METHOD} $WARNING_LEVEL ]]
    then
      NAGIOS_STATUS=WARNING
      NAGIOS_SHORT_TEXT="${METRIC_NAME} is ${PROMETHEUS_RESULT}"
    else
      NAGIOS_STATUS=OK
      NAGIOS_SHORT_TEXT="${METRIC_NAME} is ${PROMETHEUS_RESULT}"
    fi
  else
    if [[ "${NAN_OK}" = "true" && "${PROMETHEUS_RESULT}" = "NaN" ]]
    then
      NAGIOS_STATUS=OK
      NAGIOS_SHORT_TEXT="${METRIC_NAME} is ${PROMETHEUS_RESULT}"
    else
      NAGIOS_SHORT_TEXT="unable to parse prometheus response"
      NAGIOS_LONG_TEXT="${METRIC_NAME} is ${PROMETHEUS_RESULT}"
    fi
  fi
  if [[ "${NAGIOS_INFO}" = "true" ]]
  then
      NAGIOS_SHORT_TEXT="${NAGIOS_SHORT_TEXT}: ${PROMETHEUS_METRIC}"
  fi
  if [[ "${PERFDATA}" = "true" ]]
  then
      NAGIOS_SHORT_TEXT="${NAGIOS_SHORT_TEXT} | query_result=${PROMETHEUS_RESULT}"
  fi
exit
sree
  • 21
  • 2
  • 1
    Please edit your question (no comment, **no links**): What have you searched for, and what did you find? What have you tried, and how did it fail? – Cyrus May 20 '23 at 16:12
  • 2
    `jq` works with JSON, and that's not JSON... – Shawn May 20 '23 at 16:13
  • Please provide enough code so others can better understand or reproduce the problem. – Community May 20 '23 at 17:45
  • 1
    @shawn - jq can also read raw strings (I.e. convert text to JSON strings), which is the basis of @scree’s question, as exemplified by the use of `scan` in the linked jqplay snippets, so your comment is really rather unhelpful and even misleading. Please consider deleting it to avoid confusion and noise. – peak May 20 '23 at 18:54
  • See also [Why should eval be avoided in Bash, and what should I use instead?](https://stackoverflow.com/q/17529220/3422102) -- `eval` is only one-character away from `evil`. – David C. Rankin May 21 '23 at 05:28
  • @peak Thanks for this. But in the shll script PROMETHEUS_METRIC=$(echo $PROMETHEUS_METRIC | jq -Rr 'scan("({[^}]*})")') – sree May 21 '23 at 12:51
  • @peak Thanks for this. Let me Clarify the requirement that i am looking...in the attached shell script PROMETHEUS_METRIC=$(echo $PROMETHEUS_METRIC | jq -Rr 'scan("({[^}]*})")') returns the above two block in curly brace {{ __name__: ....} at the top. Now i want to add loop to iterate across these two block to return one at a time and next iteration the second one. Now it return two instead one at a time in a loop in shell script – sree May 21 '23 at 13:28
  • See update. If you don't need to convert your "blocks" to JSON and if each is on a single line, then you could use the `while read -r object` technique without jq; or you could use `sed -n 1p` and `sed -n 2p`. It really depends on what your ultimate expected output is. – peak May 21 '23 at 18:19

1 Answers1

0

The quasi-JSON to JSON step could be accomplished as follows:

jq -R '
  def rtrim: sub(" +$";"");
  def kvs:
     capture( "[, ]*(?<key>[^:]+) *: *(?<value>[^,]*)(?<etc>.*)" )
     | {key,value}, (.etc | kvs) ;

  scan( " *[{] *([^}]+)[}]" ) | first | rtrim | [kvs] | from_entries
'

With your sample input, this produces:

{
  "__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"
}

Some tweaking might be in order to handle various edge cases.

If the extraction step cannot be done in jq itself, then consider using jq's -c command-line option in conjunction with a bash while loop, along the lines of:

while read -r object ; do
   echo "$object"
done <  <( jq -Rc .... )
peak
  • 105,803
  • 17
  • 152
  • 177