dotfiles/bin/lj

156 lines
3.6 KiB
Bash
Executable file

#!/usr/bin/env zsh
# Create a mapping of log levels to their names
typeset -A _log_levels
_log_levels=(
'emergency' 0
'alert' 1
'critical' 2
'error' 3
'warning' 4
'notice' 5
'info' 6
'debug' 7
)
###
# Output usage information and exit
###
function _lumberjack_usage() {
echo "\033[0;33mUsage:\033[0;m"
echo " lj [options] [<level>] <message>"
echo
echo "\033[0;33mOptions:\033[0;m"
echo " -h, --help Output help text and exit"
echo " -v, --version Output version information and exit"
echo " -f, --file Set the logfile and exit"
echo " -l, --level Set the log level and exit"
echo
echo "\033[0;33mLevels:\033[0;m"
echo " emergency"
echo " alert"
echo " critical"
echo " error"
echo " warning"
echo " notice"
echo " info"
echo " debug"
}
###
# Output the message to the logfile
###
function _lumberjack_message() {
local level="$1" file="$2" logtype="$3" msg="${(@)@:4}"
# If the file string is empty, output an error message
if [[ -z $file ]]; then
echo "\033[0;31mNo logfile has been set for this process. Use \`lumberjack --file /path/to/file\` to set it\033[0;m"
exit 1
fi
# If the level is not set, assume 5 (notice)
if [[ -z $level ]]; then
level=5
fi
case $logtype in
# If a valid logtype is passed
emergency|alert|critical|error|warning|notice|info|debug )
# We do nothing here
;;
# In all other cases
* )
# Second argument was not a log level, so manually set it to notice
# and include the first parameter in the message
logtype='notice'
msg="${(@)@:3}"
;;
esac
if [[ $_log_levels[$logtype] > $level ]]; then
# The message being recorded is for a higher log level than the one
# currently being recorded, so gracefully exit
exit 0
fi
# Output the message to the logfile
echo "[$(echo $logtype | tr '[a-z]' '[A-Z]')] [$(date '+%Y-%m-%d %H:%M:%S')] $msg" >> $file
}
###
# The main lumberjack process
###
function _lumberjack() {
local help version logfile loglevel dir statefile state
# Create the state directory if it doesn't exist
dir="${ZDOTDIR:-$HOME}/.lumberjack"
if [[ ! -d $dir ]]; then
mkdir -p $dir
fi
# If a statefile already exists, load the level and file
statefile="$dir/$PPID"
if [[ -f $statefile ]]; then
state=$(cat $statefile)
level="$state[1]"
file="${(@)state:2}"
fi
# Parse CLI options
zparseopts -D h=help -help=help \
v=version -version=version \
f:=logfile -file:=logfile \
l:=loglevel -level:=loglevel
# If the help option is passed, output usage information and exit
if [[ -n $help ]]; then
_lumberjack_usage
exit 0
fi
# If the version option is passed, output the version and exit
if [[ -n $version ]]; then
echo "0.1.1"
exit 0
fi
# If the logfile option is passed, set the current logfile
# for the parent process ID
if [[ -n $logfile ]]; then
shift logfile
file=$logfile
# Create the log file if it doesn't exist
if [[ ! -f $file ]]; then
touch $file
fi
fi
# If the loglevel option is passed, set the current loglevel
# for the parent process ID
if [[ -n $loglevel ]]; then
shift loglevel
level=$_log_levels[$loglevel]
fi
if [[ -z $level ]]; then
level=5
fi
# Check if we're setting options rather than logging
if [[ -n $logfile || -n $loglevel ]]; then
# Store the state
echo "$level $file" >! $statefile
# Exit gracefully
exit 0
fi
# Log the message
_lumberjack_message "$level" "$file" "$@"
}
_lumberjack "$@"