Enhancements — Log Analyzer¶
Extend the core analyzer once the basic report works.
Enhancement 1 — Date Range Filtering¶
Analyze only a specific time window:
# Add options: --from "2024-01-15 08:00" --to "2024-01-15 10:00"
FROM_DATE=""
TO_DATE=""
filter_by_date() {
local from="$1" to="$2"
# Apache log date format: 15/Jan/2024:08:30:00
awk -v from="$from" -v to="$to" '
function parse_date(d, months, m, dt) {
months["Jan"]=1; months["Feb"]=2; months["Mar"]=3; months["Apr"]=4
months["May"]=5; months["Jun"]=6; months["Jul"]=7; months["Aug"]=8
months["Sep"]=9; months["Oct"]=10; months["Nov"]=11; months["Dec"]=12
# Extract day/month/year:HH:MM:SS from [15/Jan/2024:08:30:00
gsub(/[\[\]]/, "", d)
split(d, dt, /[\/:]/)
return sprintf("%04d%02d%02d%02d%02d%02d",
dt[3], months[dt[2]], dt[1], dt[4], dt[5], dt[6])
}
{
ts = parse_date($4)
if ((from == "" || ts >= from) && (to == "" || ts <= to))
print
}' "$LOGFILE"
}
Usage:
Enhancement 2 — Hourly Traffic Heatmap¶
Visualize traffic distribution across hours of the day:
print_hourly_heatmap() {
report "── Hourly Traffic ───────────────────────"
awk '{
# Extract hour from [15/Jan/2024:08:30:00
match($4, /:([0-9]{2}):/, h)
hours[h[1]]++
}
END {
max = 0
for (h in hours) if (hours[h] > max) max = hours[h]
for (h = 0; h < 24; h++) {
count = hours[sprintf("%02d", h)] + 0
bar_len = int(count / max * 30)
bar = ""
for (i = 0; i < bar_len; i++) bar = bar "#"
printf " %02d:00 | %-30s %d\n", h, bar, count
}
}' "$LOGFILE" >&3
}
Sample output:
── Hourly Traffic ───────────────────────
00:00 | ### 142
01:00 | ## 89
09:00 | ############################## 1204
...
Enhancement 3 — Suspicious IP Detection¶
Flag IPs with unusually high error rates or request volume:
detect_suspicious_ips() {
local threshold="${1:-100}"
report "── Suspicious IPs (>${threshold} 4xx/5xx errors) ───"
awk -v thresh="$threshold" '
$9 ~ /^[45]/ { errors[$1]++ }
END {
for (ip in errors)
if (errors[ip] >= thresh)
printf " %-20s %d error requests\n", ip, errors[ip]
}' "$LOGFILE" | sort -rn -k2 >&3
}
Enhancement 4 — Response Time Analysis¶
If your log format includes response time (common in Nginx with $request_time):
# Nginx log format with response time as field $NF
print_response_times() {
awk '{
rt = $NF + 0
sum += rt; count++
if (rt > max) { max = rt; slow_line = $0 }
}
END {
printf " Avg response time: %.3fs\n", sum/count
printf " Max response time: %.3fs\n", max
printf " Slowest request: %s %s\n", $7, $9
}' "$LOGFILE" >&3
}
Enhancement 5 — GeoIP Lookup¶
Look up the country for each top IP (requires geoiplookup or mmdbinspect):
print_ip_geo() {
report "── Top IPs with Country ─────────────────"
awk '{print $1}' "$LOGFILE" | sort | uniq -c | sort -rn | head -10 |
while read -r count ip; do
local country
country=$(geoiplookup "$ip" 2>/dev/null | awk -F': ' '{print $2}' | head -1 || echo "Unknown")
printf " %-20s %-25s %7d reqs\n" "$ip" "$country" "$count" >&3
done
}
Enhancement 6 — HTML Report¶
Generate a self-contained HTML page:
generate_html_report() {
local out="${1:-report.html}"
local total status_data ip_data path_data
total=$(wc -l < "$LOGFILE")
status_data=$(awk '{print $9}' "$LOGFILE" | sort | uniq -c | sort -rn)
ip_data=$(awk '{print $1}' "$LOGFILE" | sort | uniq -c | sort -rn | head -10)
path_data=$(awk '{print $7}' "$LOGFILE" | sort | uniq -c | sort -rn | head -10)
cat > "$out" << HTMLEOF
<!DOCTYPE html>
<html>
<head>
<title>Log Report — $(hostname) — $(date '+%Y-%m-%d')</title>
<style>
body { font-family: monospace; background: #0f172a; color: #f1f5f9; padding: 2em; }
h1 { color: #2dd4bf; }
table { border-collapse: collapse; width: 100%; margin: 1em 0; }
th, td { border: 1px solid #334155; padding: 8px 12px; text-align: left; }
th { background: #1e293b; color: #94a3b8; }
tr:nth-child(even) { background: #1e293b; }
.ok { color: #2dd4bf; } .warn { color: #f59e0b; } .err { color: #ef4444; }
</style>
</head>
<body>
<h1>Log Analysis Report</h1>
<p>File: <strong>$LOGFILE</strong> Total lines: <strong>$total</strong></p>
<h2>Status Codes</h2>
<table>
<tr><th>Code</th><th>Count</th></tr>
$(echo "$status_data" | awk '{printf "<tr><td>%s</td><td>%s</td></tr>\n", $2, $1}')
</table>
</body>
</html>
HTMLEOF
echo "HTML report: $out"
}