2024-01-04 08:26:42 +00:00
# This script provides a logging function 'log' that can be sourced in other scripts.
2024-11-28 06:06:21 +00:00
# It logs messages to both the terminal and a specified logfile, supporting multiple log levels.
# The log function takes three parameters: log level, log message, and optionally the logfile. If no logfile is specified, it writes to retrodeck/logs/retrodeck.log.
#
# Supported logging levels (controlled by the variable 'logging_level'):
# - none: No logs are produced.
# - info: Logs informational messages (i) and errors (e).
# - warn: Logs warnings (w), informational messages (i), and errors (e).
# - debug: Logs all message types (d, w, i, e).
#
2024-03-21 21:01:17 +00:00
# Type of log messages:
2024-11-28 06:06:21 +00:00
# - d: Debug message (logged only in debug level).
# - i: Informational message (logged in debug, info, and warn levels).
# - w: Warning message (logged in debug and warn levels).
# - e: Error message (logged in all levels except none).
#
2024-01-04 08:26:42 +00:00
# Example usage:
2024-11-28 06:06:21 +00:00
# log w "foo" -> Logs a warning with message "foo" to the default log file retrodeck/logs/retrodeck.log.
# log e "bar" -> Logs an error with message "bar" to the default log file retrodeck/logs/retrodeck.log.
# log i "baz" rekku.log -> Logs an informational message "baz" to the specified log file retrodeck/logs/rekku.log.
#
# The function auto-detects if the shell is sh and avoids colorizing the output in that case.
2024-01-04 08:26:42 +00:00
log( ) {
2024-11-28 06:06:21 +00:00
# Exit early if logging_level is "none"
if [ [ $logging_level = = "none" ] ] ; then
return
fi
2024-01-05 09:59:18 +00:00
2024-11-28 06:06:21 +00:00
local level = " $1 " # Logging level of the current message
local message = " $2 " # Message to log
local logfile = " ${ 3 :- $rd_logs_folder /retrodeck.log } " # Log file, default to retrodeck.log
2024-11-29 02:23:09 +00:00
local timestamp = " $( date +[ %Y-%m-%d\ %H:%M:%S.%3N] ) " # Timestamp for the log entry
2024-11-28 06:06:21 +00:00
local colorize_terminal = true
2024-03-22 21:10:26 +00:00
2024-11-29 02:23:09 +00:00
# Determine the calling function or use [FWORK]
local caller = " ${ FUNCNAME [1] :- [FWORK] } "
caller = " ${ caller ^^ } " # Convert to uppercase
2024-11-28 06:06:21 +00:00
# Check if the shell is sh (not bash or zsh) to avoid colorization
if [ " ${ SHELL ##*/ } " = "sh" ] ; then
colorize_terminal = false
fi
2024-03-22 21:10:26 +00:00
2024-11-28 06:06:21 +00:00
# Function to check if the current message level should be logged
should_log( ) {
case " $logging_level " in
debug) return 0 ; ; # Always log everything
info) [ [ " $level " = = "i" || " $level " = = "e" ] ] && return 0 ; ;
warn) [ [ " $level " != "d" ] ] && return 0 ; ;
error) [ [ " $level " = = "e" ] ] && return 0 ; ;
esac
return 1
}
2024-03-22 21:10:26 +00:00
2024-11-28 06:06:21 +00:00
if should_log; then
# Define message colors based on level
2024-10-18 13:29:25 +00:00
case " $level " in
2024-10-18 13:40:28 +00:00
d)
2024-11-28 06:06:21 +00:00
color = "\e[32m[DEBUG]"
prefix = "[DEBUG]"
2024-10-18 13:29:25 +00:00
; ;
2024-11-28 06:06:21 +00:00
e)
color = "\e[31m[ERROR]"
prefix = "[ERROR]"
2024-10-18 13:29:25 +00:00
; ;
2024-10-18 13:40:28 +00:00
w)
2024-11-28 06:06:21 +00:00
color = "\e[33m[WARN]"
prefix = "[WARN]"
2024-10-18 13:29:25 +00:00
; ;
2024-10-18 13:40:28 +00:00
i)
2024-11-28 06:06:21 +00:00
color = "\e[34m[INFO]"
prefix = "[INFO]"
2024-10-18 13:29:25 +00:00
; ;
2024-10-18 13:40:28 +00:00
*)
2024-11-28 06:06:21 +00:00
color = "\e[37m[LOG]"
prefix = "[LOG]"
2024-10-18 13:29:25 +00:00
; ;
esac
2024-03-22 21:10:26 +00:00
2024-11-28 06:06:21 +00:00
# Construct the log message
if [ " $colorize_terminal " = true ] ; then
2024-11-29 02:23:09 +00:00
colored_message = " $color [ $caller ] $message \e[0m "
2024-11-28 06:06:21 +00:00
else
2024-11-29 02:23:09 +00:00
colored_message = " $timestamp $prefix [ $caller ] $message "
2024-11-28 06:06:21 +00:00
fi
2024-11-29 02:23:09 +00:00
log_message = " $timestamp $prefix [ $caller ] $message "
2024-11-28 06:06:21 +00:00
2024-10-18 13:25:54 +00:00
# Display the message in the terminal
echo -e " $colored_message " >& 2
2024-03-22 21:10:26 +00:00
2024-10-18 13:25:54 +00:00
# Write the log message to the log file
if [ ! -f " $logfile " ] ; then
2024-11-30 13:39:30 +00:00
#echo "$timestamp [WARN] Log file not found in \"$logfile\", creating it" >&2 # Disabled it as it's always appearing because of log rotation
2024-10-18 13:25:54 +00:00
touch " $logfile "
fi
echo " $log_message " >> " $logfile "
2024-03-22 21:10:26 +00:00
fi
2024-01-05 09:59:18 +00:00
}
2024-11-30 13:39:30 +00:00
# The rotate_logs function manages log file rotation to limit the number of logs retained.
# It compresses the current log file into a .tar.gz archive, increments the version of
# older log files (e.g., retrodeck.1.tar.gz to retrodeck.2.tar.gz), and deletes the oldest
# archive if it exceeds the maximum limit (default: 3 rotated logs). After rotation,
# the original log file is cleared for continued logging.
rotate_logs( ) {
local logfile = " ${ 1 :- $rd_logs_folder /retrodeck.log } " # Default log file
local max_logs = 3 # Maximum number of rotated logs to keep
# Rotate existing logs
for ( ( i = max_logs; i>0; i--) ) ; do
if [ [ -f " ${ logfile } . ${ i } .tar.gz " ] ] ; then
if ( ( i = = max_logs ) ) ; then
# Remove the oldest log if it exceeds the limit
rm -f " ${ logfile } . ${ i } .tar.gz "
else
# Rename log file to the next number
mv " ${ logfile } . ${ i } .tar.gz " " ${ logfile } . $(( i+1)) .tar.gz "
fi
fi
done
# Compress the current log file if it exists
if [ [ -f " $logfile " ] ] ; then
# Compress without directory structure and suppress tar output
tar -czf " ${ logfile } .1.tar.gz " -C " $( dirname " $logfile " ) " " $( basename " $logfile " ) " --remove-files & >/dev/null
fi
}