Last active 1727443491

a Caddy log parser that converts JSON logs into Apache CommonLog output

caddy_log_parser.sh Raw
1#!/bin/bash
2
3###
4### Caddy webserver JSON log parser
5###
6
7show_help() {
8 cat <<END
9Usage: $0 [-c|--common] [-C|--combined] [-f|--files] [-h|--help] filename
10
11Options:
12 -c, --common Apache Common Log Format (default)
13 -C, --combined Apache Combined Log Format
14 -f, --files Custom Log Format, focused on file transfers
15 -h, --help Show this help message and exit
16END
17}
18
19# Function to output logs in common log format
20output_common_log_format() {
21 jq -r '
22 . as $log |
23 $log.request.client_ip as $h |
24 "-" as $l |
25 ($log.user_id // "-") as $u |
26 ($log.ts | tostring | split(".") | .[1][:3]) as $ms |
27 ($log.ts | floor | todateiso8601 | sub("T"; " ") | sub("Z"; "." + $ms + " +0000")) as $t |
28 "\($log.request.method) \($log.request.uri) \($log.request.proto)" as $r |
29 $log.status as $s |
30 ($log.size // "-") as $b |
31 "\($h) \($l) \($u)[\($t)] \"\($r)\" \($s) \($b)"
32 ' "${1}"
33}
34
35# Function to output logs in combined log format
36output_combined_log_format() {
37 jq -r '
38 . as $log |
39 $log.request.client_ip as $h |
40 "-" as $l |
41 ($log.user_id // "-") as $u |
42 ($log.ts | tostring | split(".") | .[1][:3]) as $ms |
43 ($log.ts | floor | todateiso8601 | sub("T"; " ") | sub("Z"; "." + $ms + " +0000")) as $t |
44 "\($log.request.method) \($log.request.uri) \($log.request.proto)" as $r |
45 $log.status as $s |
46 ($log.size // "-") as $b |
47 ($log.request.headers.Referer[0] // "-") as $referrer |
48 ($log.request.headers["User-Agent"][0] // "-") as $user_agent |
49 "\($h) \($l) \($u)[\($t)] \"\($r)\" \($s) \($b) \"\($referrer)\" \"\($user_agent)\""
50 ' "${1}"
51}
52
53output_file_log_format() {
54 jq -r '
55 . as $log |
56 $log.request.client_ip as $h |
57 "-" as $l |
58 ($log.user_id // "-") as $u |
59 ($log.ts | tostring | split(".") | .[1][:3]) as $ms |
60 ($log.ts | floor | todateiso8601 | sub("T"; " ") | sub("Z"; "." + $ms + " +0000")) as $t |
61 "\($log.request.method) \($log.request.uri) \($log.request.proto)" as $r |
62 $log.status as $s |
63 ($log.size // "-") as $b |
64 ($log.request.headers.Referer[0] // "-") as $referrer |
65 ($log.request.headers["User-Agent"][0] // "-") as $user_agent |
66 "\($h) \($l) \($u)[\($t)] \"\($r)\" \($s) \($b) \"\($referrer)\" \"\($user_agent)\""
67 ' "${1}"
68}
69
70# Function to list served files
71list_served_files() {
72 jq -r '
73 .request.client_ip as $client_ip |
74 (.ts | floor | todateiso8601 | sub("T"; " ") | sub("Z"; " +0000")) as $datetime |
75 .status as $status_code |
76 (.size // "-") as $size |
77 .request.uri as $filename |
78 "\($client_ip) [\($datetime)] \($status_code) \($size) \"\($filename)\""
79 ' "${1}"
80}
81
82# Default to common log format
83format="common"
84
85# Parse command line options
86while [[ "$#" -gt 0 ]]; do
87 case $1 in
88 -c|--common)
89 format="common"
90 shift
91 ;;
92 -C|--combined)
93 format="combined"
94 shift
95 ;;
96 -f|--files)
97 format="files"
98 shift
99 ;;
100 -h|--help)
101 show_help
102 exit 0
103 ;;
104 *)
105 input="${1}"
106 shift
107 ;;
108 esac
109done
110
111# Check if a filename is provided
112if [ -z "${input}" ]; then
113 echo -e "Error: No input file provided. \n"
114 show_help
115 exit 1
116fi
117
118
119# Output the logs in the chosen format
120if [ "$format" = "common" ]; then
121 output_common_log_format "${input}"
122elif [ "$format" = "files" ]; then
123 list_served_files "${input}"
124else
125 output_combined_log_format "${input}"
126fi
127
128# Apache Commong Log format:
129# "%h %l %u %t \"%r\" %>s %b"
130
131# Apache Combined LogFormat:
132# "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
133
134# %h is the remote host (client IP)
135# %l is the remote logname (not used, so we'll use -)
136# %u is the authenticated user
137# %t is the time the request was received
138# %r is the request line from the client ("method uri proto")
139# %>s is the status code
140# %b is the size of the object returned to the client

Powered by Opengist Load: 9ms