summaryrefslogtreecommitdiffhomepage
path: root/subr.rtl/rtl_log.subr
blob: 69e620bfe70e66afc69bcc15014a19a1b6bbe996 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#
# Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Lucía Andrea Illanes Albornoz <lucia@luciaillanes.de>
# set +o errexit -o noglob -o nounset is assumed.
#

#
# Private globals
#

RTLP_LOG_FNAME="";
RTLP_LOG_NO_ATTR=0;
RTLP_LOG_TAGS="";
RTLP_LOG_TERMINAL_COLOURS="$(tput colors 2>/dev/null)";

#
# Private subroutines
#

#
# rtlp_log_msg_get_attr() - get attributes e.g. ANSI escape sequences for single log tag
# @_rattr:	out reference to attributes e.g. ANSI escape sequences
# @_tag:	tag to log message at
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtlp_log_msg_get_attr() {
	local	_rplmga_rattr="${1#\$}" _rplmga_tag="${2}"	\
		_rplmga_attr="" _rplmga_attr_state=""		\
		_rplmga_term_colour=0;

	if [ "${RTLP_LOG_TERMINAL_COLOURS}" = 256 ]; then
		set -- 256 "";
	else
		set -- "";
	fi;

	for _rplmga_term_colour in "${@}"; do
		eval _rplmga_attr='${LOG_TAG_'"${_rplmga_tag}${_rplmga_term_colour:+_${_rplmga_term_colour}}"':-}';

		if [ "${_rplmga_attr:+1}" = 1 ]; then
			break;
		else
			eval _rplmga_attr_state='${RTLP_ATTR_STATE_'"${_rplmga_tag}"':-}';
			if [ "${_rplmga_attr_state:+1}" != 1 ]; then
				_rplmga_attr_state=0;
			else
				: $((_rplmga_attr_state += 1));
			fi;
			eval "RTLP_ATTR_STATE_${_rplmga_tag}=${_rplmga_attr_state}";

			if [ "$((${_rplmga_attr_state} % 2))" -eq 0 ]; then
				eval _rplmga_attr='${LOG_TAG_'"${_rplmga_tag}"'_even'"${_rplmga_term_colour:+_${_rplmga_term_colour}}"':-}';
			else
				eval _rplmga_attr='${LOG_TAG_'"${_rplmga_tag}"'_odd'"${_rplmga_term_colour:+_${_rplmga_term_colour}}"':-}';
			fi;

			if [ "${_rplmga_attr:+1}" = 1 ]; then
				break;
			fi;
		fi;
	done;

	eval ${_rplmga_rattr}='${_rplmga_attr}';
	return 0;
};

#
# rtlp_log_printfV() - print single message to log file
# @_attr:	attributes e.g. ANSI escape sequences to log message with
# @_fmt_pfx:	printf(1) format string prefix
# @_fmt:	printf(1) format string
# @...:		parameters to printf(1) w/ @_fmt
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtlp_log_printfV() {
	local	_rplp_attr="${1}" _rplp_fmt_pfx="${2}"	\
		_rplp_fmt="${3#*;}" _rplp_fmt_argc="${3%%;*}";
	shift 3;

	if [ "${#}" -ne "${_rplp_fmt_argc}" ]; then
		if [ "${_rplp_fmt_argc}" -eq 0 ]; then
			shift "${#}";
		else
			rtlp_log_printfV "" "" "0;==> FIXME TODO XXX MESSAGE STRING ARGUMENT COUNT MISMATCH\n";
		fi;
	fi;
	_rplp_msg="$(printf "${_rplp_fmt_pfx}${_rplp_fmt}" "${@}")";

	if [ "${RTLP_LOG_FNAME:+1}" = 1 ]; then
		printf "%s\n" "${_rplp_msg}" >> "${RTLP_LOG_FNAME}";
	fi;
	if [ "${RTLP_LOG_NO_ATTR:-0}" -eq 0 ]; then
		printf "\033[0m\033[${_rplp_attr}m%s\033[0m\n" "${_rplp_msg}";
	else
		printf "%s\n" "${_rplp_msg}";
	fi;
	return 0;
};

#
# Public subroutines
#

#
# rtl_log_clear_tags() - clear all log tags
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtl_log_clear_tags() {
	RTLP_LOG_TAGS="";
	return 0;
};

#
# rtl_log_enable_tagsV() - enable log tags
# @...:		list of tags to enable as positional parameters
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtl_log_enable_tagsV() {
	local IFS=","; set -- ${*};

	while [ "${#}" -gt 0 ]; do
		if ! rtl_lmatch \$RTLP_LOG_TAGS "${1}" ","; then
			RTLP_LOG_TAGS="${RTLP_LOG_TAGS:+${RTLP_LOG_TAGS},}${1}";
		fi; shift;
	done;
	return 0;
};

#
# rtl_log_env_vars() - log all environment variables to log file
# @_tag:	tag to log environment variables at
# @_type:	type string printed in log message header
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtl_log_env_vars() {
	local	_rlev_tag="${1}" _rlev_type="${2}"	\
		_rlev_arg_len_max=0 _rlev_list="" _rlev_msg="" _rlev_msg_="";
	shift 2;

	rtl_log_msgV "${_rlev_tag}" "${MSG_rtl_log_vars_header}" "${_rlev_type}";
	_rlev_list="${@}"; rtl_lmax \$_rlev_list \$_rlev_arg_len_max;
	while [ "${#}" -gt 0 ]; do
		rtl_get_var_unsafe \$_rlev_msg "${1#*=}";
		rtl_llift2 \$_rlev_msg \$_rlev_msg_ "" " ";
		rtl_log_msgV "${_rlev_tag}"					\
			"2;%${_rlev_arg_len_max}.${_rlev_arg_len_max}s=%s"	\
			"${1%%=*}" "${_rlev_msg_}";
		shift;
	done;
	return 0;
};

#
# rtl_log_msgV() - log message to log file
# @_tag:	tag to log message at
# @_fmt:	printf(1) format string
# @...:		parameters to printf(1) w/ @_fmt
#
# Returns:	zero (0) on success, non-zero (>0) on failure
# N.B.:		Optional attributes e.g. ANSI escape sequences w/ which the the log message is to
#		be printed are taken from the variable corresponding to @_tag named "LOG_TAG_<@_tag>",
#		if present/set.
#
#		@_tag must have previously been enabled w/ rtl_log_enable_tagsV() to be logged at all.
#
rtl_log_msgV() {
	local	_rlm3_tag="${1}" _rlm3_fmt="${2}"	\
		_rlm3_attr="" _rlm3_date_now=0 _rlm3_exitfl=0
	shift 2;

	if [ "x${_rlm3_tag}" = "xfatalexit" ]; then
		_rlm3_tag="fatal"; _rlm3_exitfl=1;
	fi;

	if [ "${_rlm3_tag}" = "fatal" ]\
	|| rtl_lmatch \$RTLP_LOG_TAGS "${_rlm3_tag}" ",";
	then
		rtlp_log_msg_get_attr \$_rlm3_attr "${_rlm3_tag}";
		rtl_date \$_rlm3_date_now;
		rtlp_log_printfV "${_rlm3_attr}" "==> ${_rlm3_date_now} " "${_rlm3_fmt}" "${@}";
		if [ "${_rlm3_exitfl}" -eq 1 ]; then
			exit 1;
		fi;
	fi;
	return 0;
};

#
# rtl_log_set_fname() - set log file pathname
# @_fname:	pathname to new log file
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtl_log_set_fname() {
	RTLP_LOG_FNAME="${1}";
	return 0;
};

#
# rtl_log_set_no_attr() - set or clear no ANSI escape sequences in log file flag
# @_flag:	either 0 to set or 1 to clear no ANSI escape sequences in log file flag
#
# Returns:	zero (0) on success, non-zero (>0) on failure
#
rtl_log_set_no_attr() {
	RTLP_LOG_NO_ATTR="${1}";
	return 0;
};

# vim:filetype=sh textwidth=0