jenkins-pipelines/scripts/lib/log_utils.sh

214 lines
5.7 KiB
Bash

# bash
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
if [[ -z "$__LOG_UTILS_INCLUDED" ]] ; then
__LOG_UTILS_INCLUDED=1
#
# Usage: dump_stack [FRAME_OFFSET]
#
dump_stack() {
local -i index
local -i max_index="${#BASH_SOURCE[@]}"
local -a line_numbers=($LINENO "${BASH_LINENO[@]}")
for ((index=${1:-0}; index < max_index; ++index)) {
echo " at ${BASH_SOURCE[$index]} line ${line_numbers[$index]}"
}
}
#
# Usage: print_log [OPTIONS...] LINES...
#
# Print a log message; each LINE is printed on a separate line and should
# be quoted in scripts.
#
# --dump-stack include stack trace in output
# --frame-offset=N frame offset for stack trace (default: 0)
# --prefix=PREFIX include PREFIX in front of each LINE
# --location include caller function name in front of each LINE
# --epilog=EPILOG include EPILOG in output
# --loud be loud
# -i,--increment-frame-offset
# add one to frame-offset (additive)
#
# --error set --prefix --loud + TTY codes as necessary
# --warning --warn
# --notice
# --info
#
__print_log_usage() {
local func="${FUNCNAME[1]}"
echo "
################################################################################
ERROR: ${func}: invalid syntax
$(dump_stack 2)
Usage: $func [OPTIONS...] LINES...
See ${BASH_SOURCE[0]} near line ${LINENO} for more info.
################################################################################
"
}
print_log() {
(
set +x
local -i frame_offset=1
local -i frame_offset_offset=0
local -i dump_stack_frame_offset
local -i dump_stack=0
local line_prefix
local epilog
local -i include_location=0
local loud
local loud_prefix loud_suffix
local loud_line_prefix
local preset_line_prefix
# color codes
local tty_error tty_warning tty_notice tty_info
local tty_on tty_off
if [[ -t 1 ]] ; then
tty_error=$'\033[1;31m'
tty_warning=$'\033[0;33m'
tty_notice=$'\033[0;32m'
tty_off=$'\033[0m'
fi
# parse command line
local opts
local -a rsync_opts
opts="$(\
getopt -n "${FUNCNAME[0]}" -o "+i" \
-l dump-stack \
-l frame-offset: \
-l increment-frame-offset \
-l prefix: \
-l location\
-l epilog: \
-l loud \
-l error \
-l warning -l warn \
-l notice \
-l info \
-- "$@"
)"
if [[ $? -ne 0 ]] ; then
__print_log_usage
exit 1
fi
eval set -- "${opts}"
while true ; do
case "$1" in
--dump-stack)
dump_stack=1
shift
;;
--frame-offset)
frame_offset="$2"
shift 2
;;
-i | --increment-frame-offset)
let ++frame_offset_offset
shift
;;
--prefix)
line_prefix="$2"
shift 2
;;
--location)
include_location=1
shift
;;
--epilog)
epilog="$2"
shift 2
;;
--loud)
loud="yes"
shift
;;
--error)
loud="yes"
preset_line_prefix='ERROR: '
tty_on="$tty_error"
shift
;;
--warning | --warn)
loud="yes"
preset_line_prefix='WARNING: '
tty_on="$tty_warning"
shift
;;
--notice)
loud="yes"
tty_on="$tty_notice"
shift
;;
--info)
preset_line_prefix='# '
shift
;;
--)
shift
break
;;
-*)
__print_log_usage
exit 1
;;
*)
break
;;
esac
done
if [[ "$#" -lt 1 ]] ; then
__print_log_usage
exit 1
fi
if [[ -z "$line_prefix" ]] ; then
line_prefix="$preset_line_prefix"
fi
if [[ "$loud" = "yes" ]] ; then
local nl=$'\n'
loud_line_prefix=$'### '
loud_prefix="${nl}${nl}${loud_line_prefix}${nl}"
loud_suffix="${loud_line_prefix}${nl}${nl}"
fi
let frame_offset+=frame_offset_offset
local location
if [[ $include_location -eq 1 ]] ; then
local -i funcname_index=$frame_offset
local func="${FUNCNAME[$funcname_index]}"
if [[ -n "$func" && "$func" != "main" ]] ; then
location="$func: "
fi
fi
echo -n "$loud_prefix"
while [[ "$#" -gt 0 ]] ; do
local line="$1" ; shift || true
echo "${loud_line_prefix}${location}${tty_on}${line_prefix}${line}${tty_off}"
done
shift || true
if [[ $dump_stack -eq 1 ]] ; then
let dump_stack_frame_offset=frame_offset+1
dump_stack $dump_stack_frame_offset | awk -v PREFIX="${loud_line_prefix}" -v SUFFIX="" '{print PREFIX, $0, SUFFIX}'
fi
if [[ -n "$epilog" ]] ; then
echo -n "$epilog"
fi
echo -n "$loud_suffix"
) >&2
}
fi # include guard