Skip to content

Instantly share code, notes, and snippets.

@xanathar
Created April 10, 2025 20:56
Show Gist options
  • Save xanathar/70d4e51b6e181d57a3b78770d7d498b6 to your computer and use it in GitHub Desktop.
Save xanathar/70d4e51b6e181d57a3b78770d7d498b6 to your computer and use it in GitHub Desktop.
Plot log file aggregated by time using gnuplot
#!/bin/bash
# Check if a file was provided
if [ $# -lt 1 ] || [ $# -gt 3 ]; then
echo "Usage: $0 <logfile> [start_time] [end_time]"
echo "Example: $0 logfile.log '2023-01-01 00' '2023-01-02 23'"
echo "Note: If start_time and end_time are not provided, they will be automatically"
echo " extracted from the first and last lines of the log file."
exit 1
fi
LOGFILE=$1
START_TIME=$2
END_TIME=$3
# Extract start and end times automatically if not provided
if [ -z "$START_TIME" ] || [ -z "$END_TIME" ]; then
# Extract timestamp from first line for start time
if [ -z "$START_TIME" ]; then
FIRST_LINE=$(head -n 1 "$LOGFILE")
if [[ $FIRST_LINE =~ ^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}):[0-9]{2} ]]; then
AUTO_START_TIME="${BASH_REMATCH[1]}"
START_TIME="$AUTO_START_TIME"
echo "Automatically set start time to: $START_TIME"
else
echo "Warning: Could not extract start time from first line"
fi
fi
# Extract timestamp from last line for end time
if [ -z "$END_TIME" ]; then
LAST_LINE=$(tail -n 1 "$LOGFILE")
if [[ $LAST_LINE =~ ^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}):[0-9]{2} ]]; then
AUTO_END_TIME="${BASH_REMATCH[1]}"
# If start and end times are the same, add 1 minute to end time to avoid empty range
if [ "$AUTO_START_TIME" = "$AUTO_END_TIME" ]; then
# Add one minute to the end time
END_TIME="$AUTO_END_TIME:59"
echo "Start and end times were identical. Automatically adjusted end time to: $END_TIME"
else
END_TIME="$AUTO_END_TIME"
echo "Automatically set end time to: $END_TIME"
fi
else
echo "Warning: Could not extract end time from last line"
fi
fi
fi
# Create a temporary file for the processed data
TEMPFILE=$(mktemp)
# Extract timestamps from log and count occurrences per time unit
# Assuming the timestamp is in the format "YYYY-MM-DD HH:MM:SS" or similar at the start of each line
awk '{
# Extract timestamp using regex
# This regex looks for a pattern like "YYYY-MM-DDThh:mm:ss" at the start of the line
if (match($0, /^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}):[0-9]{2}/, timestamp_parts)) {
# timestamp_parts[1] contains the YYYY-MM-DDThh:mm part (aggregation by minute)
minute_timestamp = timestamp_parts[1];
# Count lines per minute
count[minute_timestamp]++;
}
}
END {
# Output the counts
for (time in count) {
print time, count[time];
}
}' "$LOGFILE" | sort > "$TEMPFILE"
# Create a gnuplot script
GNUPLOT_SCRIPT=$(mktemp)
cat > "$GNUPLOT_SCRIPT" << EOL
set terminal png size 1200,800
set output 'log_activity.png'
set title 'Log Activity Over Time' font ",12"
set xlabel 'Time' offset 0,-5
set ylabel 'Number of Log Entries'
set xdata time
set timefmt '%Y-%m-%dT%H:%M'
set format x '%Y-%m-%dT%H:%M'
# Rotate the x-axis labels vertically to prevent overlapping
set xtics rotate by 90 offset 0,-5 font ",8"
set xtics nomirror
# Add more bottom margin to accommodate the vertical labels
set bmargin 10
set grid
set key off
set style fill solid 0.5
EOL
# Set time range for x-axis if provided
if [ ! -z "$START_TIME" ] && [ ! -z "$END_TIME" ]; then
# Add a small buffer to the range to avoid empty range errors
echo "set xrange [\"$START_TIME\":\"$END_TIME\"]" >> "$GNUPLOT_SCRIPT"
elif [ ! -z "$START_TIME" ]; then
echo "set xrange [\"$START_TIME\":]" >> "$GNUPLOT_SCRIPT"
elif [ ! -z "$END_TIME" ]; then
echo "set xrange [:\"$END_TIME\"]" >> "$GNUPLOT_SCRIPT"
else
# If no range was set or extracted, don't set xrange explicitly
echo "# No explicit xrange - using auto range" >> "$GNUPLOT_SCRIPT"
fi
# Add the plot command
echo "plot '$TEMPFILE' using 1:2 with boxes" >> "$GNUPLOT_SCRIPT"
# Run gnuplot
gnuplot "$GNUPLOT_SCRIPT"
# Clean up temporary files
rm "$TEMPFILE" "$GNUPLOT_SCRIPT"
echo "Chart has been generated as log_activity.png"
xdg-open log_activity.png
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment