Filter JSON logs and count errors with jq
Use jq to select errors from JSON Lines logs, keep useful fields, and count failures by service.
how-to3 steps
Updated
in short
Use select to filter one log event at a time. For a small file, slurp the records and group them to count errors by service.
Use the small fixture below to check the workflow before applying it to your own project.
Tools used
Before you start
- A Bash or Zsh terminal on Linux or macOS
- The listed tools installed and available on PATH
Steps
Step 1: Create three log events
Each line is a complete JSON object.
shtrmn_guide_dir="$(mktemp -d)" cd "$trmn_guide_dir" cat > events.jsonl <<'EOF' {"service":"api","status":200,"message":"ok"} {"service":"api","status":500,"message":"timeout"} {"service":"worker","status":503,"message":"unavailable"} EOFStep 2: Select error events
The compact output keeps one matching event per line.
shjq -c 'select(.status >= 500) | {service, status, message}' events.jsonloutput{"service":"api","status":500,"message":"timeout"} {"service":"worker","status":503,"message":"unavailable"}Step 3: Count errors by service
Slurp loads the whole file into memory. Use this grouping example on bounded files, not an endless log stream.
shjq -sc 'map(select(.status >= 500)) | group_by(.service) | map({service: .[0].service, errors: length})' events.jsonloutput[{"service":"api","errors":1},{"service":"worker","errors":1}]
Further reading
[jq manual](https://jqlang.org/manual/)
FAQ
- Why does malformed input fail?
- jq expects valid JSON values. Remove non-JSON prefixes or parse them before filtering.
- Does this change the file?
- No. Both commands read events.jsonl and write their results to standard output.