#!/usr/bin/env bash # Basic logging utility functions that can be used by scripts to log # to files. This helps keep console clean for TUI's. Will log # messages to all registered files, which allows each script to # declare their own logging file, but also print logs into parent # processes files, for ease of discovery. # # Supports warning and error flags. # # Errors and warnings get logged to the file and to the console. # # # EXAMPLE SETUP: # # source $SCRIPTS/hypr/logging # THIS=$(basename ${BASH_SOURCE[0]}) # # # Setup logging file and label. # setup-logging "/tmp/$THIS.log" $THIS # # function log() { # logging log --source ${BASH_SOURCE[0]} "$@" # } # # log "My log message." # log --warning "My warning message." # log --error "My error message." # set -e set -o nounset set -o pipefail LOG_DIR=${LOG_DIR:-/tmp/logs} LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-""} LOG_LABEL=${LOG_LABEL:-""} # Run in dry run mode, which just prints to the console and does # not log to the files. LOG_ENABLE_DRY_RUN=${LOG_ENABLE_DRY_RUN:-"0"} SCRIPTS=${SCRIPTS:-$HOME/.local/scripts} warn_flag="0" error_flag="0" __msg() { if [[ -z "$*" ]]; then echo -e "\e[31m[ERROR]:\e[0m No logs were supplied." exit 1 fi if [[ $warn_flag == "1" ]]; then echo -e "\e[33m[WARN]:\e[0m $*" elif [[ $error_flag == "1" ]]; then echo -e "\e[31m[ERROR]:\e[0m $*" else echo "$@" fi } __ensure_setup() { if [[ -z $LOG_FILE ]] || [[ -z $LOG_INVOCATION_ID ]] || [[ -z $LOG_LABEL ]] || [[ -z $LOG_DIR ]]; then echo -e "\e[31m[ERROR]:\e[0m Logging is not properly setup." echo "Perhaps you didn't call 'setup-logging' first." print_logger_env && exit 1 fi if [[ ! -d $LOG_DIR ]]; then mkdir -p "$LOG_DIR" fi } logging() { __ensure_setup # Reset flags log_flag="0" echo_flag="0" warn_flag="0" error_flag="0" source_file="" args=() while [[ $# -gt 0 ]]; do if [[ $1 == "-w" ]] || [[ $1 == "--warn" ]] || [[ $1 == "--warning" ]]; then warn_flag="1" elif [[ $1 == "-e" ]] || [[ $1 =~ ^--error ]]; then error_flag="1" elif [[ $1 =~ ^--echo ]]; then echo_flag="1" elif [[ $1 == "-s" ]] || [[ $1 =~ ^--source ]]; then shift source_file="$1" elif [[ $1 == "log" ]]; then log_flag="1" else args+=("$1") fi shift done if [[ -z $source_file ]]; then echo -e "\e[31m[ERROR]:\e[0m Must supply the source file the logs originate from." exit 1 fi if [[ -z "${args[*]}" ]]; then echo -e "\e[31m[ERROR]:\e[0m No log message supplied." exit 1 fi msg="$(__msg "${args[@]}")" if [[ $LOG_ENABLE_DRY_RUN == "0" ]] && [[ $log_flag == "1" ]]; then # Loop over log files logging message to each file. for i in "${!LOG_FILE[@]}"; do local file=${LOG_DIR}/${LOG_FILE[i]} local id=$LOG_INVOCATION_ID local label=${LOG_LABEL[i]:-"$LOG_LABEL"} local time time=$(date '+%D %H:%M:%S') if [[ -z $file ]] || [[ -z $id ]] || [[ -z $label ]]; then echo "Logging not properly setup." exit 1 fi local prefix="[id: $id][time: $time][source: \e[32m$source_file\e[0m][\e[34m$label\e[0m] :" local m="$prefix $msg" echo -e "$m" >>"$file" done # Also log errors and warning messages to the console. if [[ $error_flag == "1" ]] || [[ $warn_flag == "1" ]]; then echo -e "[id: $id]$msg" elif [[ $warn_flag == "1" ]]; then echo -e "[id: $id]$msg" elif [[ $echo_flag == "1" ]]; then echo -e "$msg" fi else # Dry run mode, so just log to the console echo -e "\e[34m[DRY RUN]:\e[0m $msg" fi } setup-logging() { label="" file="" if [[ "${#@}" == "1" ]]; then file="/tmp/$1.log" label="$1" else file="$1" label="$2" fi if [[ -z "$file" ]]; then echo -e "\e[31m[ERROR]:\e[0m Must supply a log file." exit 1 fi if [[ -z "$label" ]]; then echo -e "\e[31m[ERROR]:\e[0m Must supply a logger label." exit 1 fi # Only add files that aren't already in the LOG_FILE. if [[ ! $LOG_FILE =~ $file ]]; then LOG_FILE+=("$file") fi LOG_INVOCATION_ID=${LOG_INVOCATION_ID:-$RANDOM} if [[ -n $LOG_LABEL ]] && [[ ! $LOG_LABEL =~ $label ]]; then LOG_LABEL+=("${LOG_LABEL[@]}=>$label") elif [[ ! ${LOG_LABEL[*]} =~ $label ]]; then LOG_LABEL+=("$label") fi export LOG_DIR export LOG_FILE export LOG_LABEL export LOG_INVOCATION_ID } print_logger_env() { echo "LOG_FILE: ${LOG_FILE[*]}" echo "LOG_INVOCATION_ID: $LOG_INVOCATION_ID" echo "LOG_LABEL: ${LOG_LABEL[*]}" } export -f setup-logging export -f logging export -f print_logger_env