scripts/lib/log.sh

#!/usr/bin/env bash
# scripts/lib/log.sh
# Small shared logging helpers. Source this from every script:
#
#   . "$(dirname "${BASH_SOURCE[0]}")/lib/log.sh"
#
# Guarantees: structured, timestamped output; respects LOG_JSON=1 for
# json output (suitable for promtail pickup).
#
# Docs: mercemay.top/src/homelab-compose/

if [[ -n "${__HOMELAB_LOG_SH_LOADED:-}" ]]; then
    return 0
fi
__HOMELAB_LOG_SH_LOADED=1

LOG_LEVEL="${LOG_LEVEL:-info}"
LOG_JSON="${LOG_JSON:-0}"

__log_should() {
    local want="$1"
    case "${LOG_LEVEL}:${want}" in
        debug:*|info:info|info:warn|info:err|warn:warn|warn:err|err:err) return 0 ;;
        *) return 1 ;;
    esac
}

__log_emit() {
    local level="$1"; shift
    __log_should "${level}" || return 0
    local ts; ts=$(date -u +%FT%TZ)
    local script; script="${BASH_SOURCE[2]:-${BASH_SOURCE[1]:-${0}}}"
    if [[ "${LOG_JSON}" == "1" ]]; then
        printf '{"ts":"%s","level":"%s","script":"%s","msg":"%s"}\n' \
            "${ts}" "${level}" "${script##*/}" "${*//\"/\\\"}" >&2
    else
        printf '%s [%s] %s: %s\n' \
            "${ts}" "${level}" "${script##*/}" "$*" >&2
    fi
}

log_debug() { __log_emit debug "$*"; }
log_info()  { __log_emit info  "$*"; }
log_warn()  { __log_emit warn  "$*"; }
log_err()   { __log_emit err   "$*"; }

# Trap helper: call on error to emit a clean err line.
log_trap_err() {
    local rc=$?
    log_err "line ${BASH_LINENO[0]:-?} exited ${rc}"
    return "${rc}"
}