3 ==================================================================================
4 Copyright (c) 2019-2020 Nokia
5 Copyright (c) 2018-2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 Abstract: Implements a common logging interface.
24 Some thoughts and theory....
25 Libraries should write human readable messages to standard error
26 when errors, warnings, or general information messages are called
27 for. These messages should NEVER be written to standard output,
28 and should never be mixed with an application's log messages which
29 are assumed to contain potentially sensitive information, such as
30 user names, and should not be written to standard error.
32 For libraries such as RMR, where speed and latency are absolutely
33 critical, logging should only be done from non-critical path code,
34 or when an error has already compromised the ability to be performant.
35 Thus, it is expected that most calls to the functions here are of
37 if( DEBUG ) rmr_logger( vlevel, fmt, parms);
39 such that the call to rmr_logger() is removed from the code unless
40 compiled with the DEBUG flag set. Code such as
41 if( vlevel >= WARNING ) {
42 rmr_logger( fmt, parms )
45 is unacceptable because it adds unnecessary checking for the current
46 verbosity level setting in line.
49 With respect to formatting messages written to stderr: they should NOT
50 be written with json, or anyother form of mark up. Idealy, they should
51 use a syntax similar to system log:
52 <timestamp> <pid> <situation> <message>
54 where timestamp is UNIX time, pid is the process id, situation is error,
55 warning, etc, and message is obviously the text.
57 Thus, the default messages geneated are "plain." Because some might feel
58 that messages need to be formatted, the code here provides for the gross
59 encapsulation of standard error text into json (best wishes for the poor
60 sap who is left having to read the output on some dark and stormy night).
61 To enable this, the environment veriable RMR_HRLOG=0 must be set to
62 turn off human readable logs.
64 Author: E. Scott Daniels
68 #ifndef _logger_static_c
69 #define _logger_static_c
83 #include <rmr_agnostic.h>
84 #include <rmr_logging.h>
86 static int log_initialised = 0;
87 static int log_vlevel = RMR_VL_ERR;
88 static int log_hrlogging = 1;
89 static int log_pid = 0;
90 static char* log_situations[RMR_VL_DEBUG+1];
93 Initialise logging. Returns the current log level.
95 extern int rmr_vlog_init( ) {
98 if( (data = getenv( ENV_LOG_HR )) != NULL ) {
99 log_hrlogging = atoi( data );
102 if( (data = getenv( ENV_LOG_VLEVEL )) != NULL ) {
103 log_vlevel = atoi( data );
104 if( log_vlevel < 0 ) {
107 if( log_vlevel > RMR_VL_DEBUG ) {
108 log_vlevel = RMR_VL_DEBUG;
114 log_situations[RMR_VL_DEBUG] = LOG_DEBUG;
115 log_situations[RMR_VL_INFO] = LOG_INFO;
116 log_situations[RMR_VL_WARN] = LOG_WARN;
117 log_situations[RMR_VL_ERR] = LOG_ERROR;
118 log_situations[RMR_VL_CRIT] = LOG_CRIT;
126 Write a variable message formatted in the same vein as *printf.
127 We add a header to each log message with time, pid and message
128 situation (error, warning, etc.).
130 extern void rmr_vlog( int write_level, char* fmt, ... ) {
131 va_list argp; // first arg in our parms which is variable
134 char* body; // pointer into msg, past header
136 if( write_level > log_vlevel ) { // write too big, skip
140 if( ! log_initialised ) {
144 if( write_level > RMR_VL_DEBUG || write_level < 0 ) {
145 write_level = RMR_VL_DEBUG;
148 hlen = snprintf( msg, sizeof( msg ), "%ld %d/RMR [%s] ", (long) time( NULL ), log_pid, log_situations[write_level] );
151 va_start( argp, fmt ); // suss out parm past fmt
153 vsnprintf( body, sizeof( msg ) - (hlen+2), fmt, argp ); // add in user message formatting it along the way
154 fprintf( stderr, "%s", msg ); // we grew from printfs so all existing msg have \n; assume there
158 This ensures that the message is written regardless of the current log level
159 setting. This allows for route table collection verbose levels to be taken
160 into consideration separately from the err/warn/debug messages. Component
161 verbosity would be better and should be implemented.
164 extern void rmr_vlog_force( int write_level, char* fmt, ... ) {
165 va_list argp; // first arg in our parms which is variable
168 char* body; // pointer into msg, past header
170 if( ! log_initialised ) {
174 if( log_vlevel <= 0 ) { // cant force if off completely to allow for total silience
178 if( write_level > RMR_VL_DEBUG || write_level < 0 ) {
179 write_level = RMR_VL_DEBUG;
182 hlen = snprintf( msg, sizeof( msg ), "%ld %d/RMR [%s] ", (long) time( NULL ), log_pid, log_situations[write_level] );
185 va_start( argp, fmt ); // suss out parm past fmt
187 vsnprintf( body, sizeof( msg ) - (hlen+2), fmt, argp ); // add in user message formatting it along the way
188 fprintf( stderr, "%s", msg ); // we grew from printfs so all existing msg have \n; assume there
191 // -------------------- public functions that are needed -----------------
194 Allow user control to logging level control. Accepts a new log level
195 from the user programme. Messages which have a write level setting
196 which is >= to the new level will be written. Setting the new value
197 to RMR_VL_OFF disables all logging (not advised).
199 extern void rmr_set_vlevel( int new_level ) {
200 if( new_level >= 0 ) {
201 log_vlevel = new_level;