#!/bin/bash # This bash script builds an awk script. The awk script tries to match # (provided) patterns and compares them against given thresholds condition # (e.g., threshold is "< 10"). function die() { echo $@ 1>&2; exit 1; } # Print every line, because the logs are piped into this script, but a user is # typically also interested into the raw logs. SCRIPT=' { print $0 } ' NUM=0 # for each pair of /, add corresponding rules. while [ $# -gt 0 ]; do [ $# -ne 1 ] || die "unmatched /" PATTERN=${1} COND=${2} shift 2 # Add a rule that searches for a PATTERN + number, and checks against # CONDition. If the condition does not hold, it is counted as a failure. In # both cases, the result is logged in an array to output at the end of the # script. # # To search for the number, first substr() returns what has been matched # (PATTERN + number), and sub() deletes PATTERN and whitespace, resulting in # the number (measurement). To force number into a numeric context, we add 0, # as awk would otherwise compare a string to a number (example: # gawk 'BEGIN { meas = "117"; if (meas > 96) { } else { print "fail";}}' # printfs "fail"). # # Example: pattern "PHY proc tx", condition "< 200" # The awk script tries to match every line for "PHY proc tx _NUMBER_" (where # number is a decimal), and compares _NUMBER_ against condition "< 200", # i.e., "_NUMBER_ < 200". # If the condition holds, will set "CHECK PHY proc tx _NUMBER_ < 200 SUCCESS". # If the condition fails, will set "CHECK PHY proc tx _NUMBER_ < 200 FAIL". SCRIPT+=' match($0, /'${PATTERN}' +([0-9]+(\.[0-9]+)?)/) { meas = substr($0, RSTART, RLENGTH); sub(/'${PATTERN}' +/, "", meas); if ((meas+0) '${COND}') { r = "SUCCESS"; } else { r = "FAIL"; } RESULTS['${NUM}']=sprintf("CHECK %-35s %7.2f %-8s %s", "'${PATTERN}'", meas, " '${COND}'", r); } ' # Generate an additional rule for the end of the logs: if the pattern is not # found, it is counted as a failure and logged appropriately. # Following the above example "PHY proc tx" and "< 200": if such log is not # found, will set "CHECK PHY proc tx < 200 NOTFOUND" SCRIPT+=' END { if (!RESULTS['${NUM}']) { RESULTS['${NUM}']=sprintf("CHECK %-35s %-7s NOTFOUND", "'${PATTERN}'", "'${COND}'"); } } ' let NUM=${NUM}+1 done # After passing through all logs, print all results, and exit with return code # (0 on success, i.e..all conditions checked, otherwise 1 on failure). SCRIPT+=' END { RC = 0; for (i = 0; i < '${NUM}'; ++i) { print RESULTS[i] if (!(RESULTS[i] ~ /SUCCESS$/)) RC = 1; } exit RC } ' # Read from separate file descriptor 3: this allows us to pipe the actual log # to analyze into awk (by using the script like so: analyze-timing.sh < log) awk -f /dev/fd/3 3<<< ${SCRIPT}