DAWN/src/utils/utils.c
Ian Clowes 4df0c986f1 treewide: improve logging
Provide multi-priority syslog() based logging to improve user and
developer experience. Add dawnlog_* functions and macros to convert
printf() family and perror() logging to syslog() family. Removed
unnecessary sprintf() for building log strings (embed format directly).
Add local config settings for log level. Add command line parameters for
log level and destination. Set default log level to suppress a lot of
previously noisy messages. Restore some previously removed noisy
messages as DEBUG level in case they help in future. Eliminate DAWN_NO_OUTPUT static code checks which are no longer used.

Signed-off-by: Ian Clowes <clowes_ian@hotmail.com>
2022-01-17 10:10:47 +01:00

130 lines
3 KiB
C

#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>
#include <stdio.h>
#include "utils.h"
int string_is_greater(char *str, char *str_2) {
int length_1 = strlen((char *) str);
int length_2 = strlen((char *) str_2);
int length = length_1 < length_2 ? length_1 : length_2;
for (int i = 0; i < length; i++) {
if (str[i] > str_2[i]) {
return 1;
}
if (str[i] < str_2[i]) {
return 0;
}
}
return length_1 > length_2;
}
// Size implied by https://man7.org/linux/man-pages/man3/strerror.3.html
char dawnlog_pbuf[1024] = "NOT SET";
static int _logdest = DAWNLOG_DEST_SYSLOG; // Assume daemon, logging to syslog
static int _logmin = DAWNLOG_ALWAYS; // Anything of lower priority is suppressed
void dawnlog_dest(int logdest)
{
_logdest = logdest;
}
void dawnlog_minlevel(int level)
{
// Don't allow certain prioriites to be suppressed
if (level < DAWNLOG_ALWAYS)
{
_logmin = level;
}
}
int dawnlog_showing(int level)
{
return(level >= _logmin);
}
void dawnlog(int level, const char* fmt, ...)
{
if ((level & DAWNLOG_PRIMASK) >= _logmin)
{
// Attempt to replicate what perror() does...
// dawnlog_buf is already referenced by macro expanded format string, so set it to a value
if ((level & DAWNLOG_PERROR) == DAWNLOG_PERROR)
{
strerror_r(errno, dawnlog_pbuf, 1024);
}
va_list ap;
va_start(ap, fmt);
int sl = LOG_NOTICE; // Should always be mapped to a different value
char *iotag = "default: ";
switch (level)
{
case DAWNLOG_ERROR:
sl = LOG_ERR;
iotag = "error: ";
break;
case DAWNLOG_WARNING:
sl = LOG_WARNING;
iotag = "warning: ";
break;
case DAWNLOG_ALWAYS:
sl = LOG_INFO;
iotag = "info: ";
break;
case DAWNLOG_INFO:
sl = LOG_INFO;
iotag = "info: ";
break;
case DAWNLOG_TRACE:
sl = LOG_DEBUG;
iotag = "trace: ";
break;
case DAWNLOG_DEBUG:
sl = LOG_DEBUG;
iotag = "debug: ";
break;
}
if (_logdest == DAWNLOG_DEST_SYSLOG)
{
vsyslog(sl, fmt, ap);
}
else
{
int l = strlen(fmt);
if (l)
{
FILE* f = (level == DAWNLOG_ERROR || level == DAWNLOG_WARNING) ? stderr : stdout;
fprintf(f, "%s", iotag);
vfprintf(f, fmt, ap);
// Messages created for syslog() may not have a closing newline, so add one if using stdio
if (fmt[l - 1] != '\n')
fprintf(f, "\n");
}
}
va_end(ap);
}
}
/* Return pointer to filename part of full path */
const char* dawnlog_basename(const char* file)
{
char* xfile = strrchr(file, '/');
return(xfile ? xfile + 1 : file);
}