hamnet70/impl/src/logger.c
Thomas Kolb 2e91fd7c42 Apply free software+documentation licenses
All code is now licensed under GPLv3+. The documentation is licensed under
CC BY-SA 4.0.

This is now officially free software! \o/
2024-08-23 11:53:40 +02:00

193 lines
4.8 KiB
C

/*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Copyright (C) 2024 Thomas Kolb
*/
/*
* Copyright (c) 2015-2024 Thomas Kolb
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <malloc.h>
#include <time.h>
#include <sys/time.h>
#include <stdarg.h>
#include "logger.h"
// define constants
const char *LOGGER_STR_FATAL = "FATAL";
const char *LOGGER_STR_ERR = "ERROR";
const char *LOGGER_STR_WARN = "WARN ";
const char *LOGGER_STR_INFO = "INFO ";
const char *LOGGER_STR_DEBUG = "DEBUG";
const char *LOGGER_STR_DUMP = "DUMP ";
const char *LOGGER_COLOR_FATAL = "\033[1;31m";
const char *LOGGER_COLOR_ERR = "\033[1;31m";
const char *LOGGER_COLOR_WARN = "\033[1;33m";
const char *LOGGER_COLOR_INFO = "\033[1;32m";
const char *LOGGER_COLOR_DEBUG = "\033[1m";
const char *LOGGER_COLOR_DUMP = "\033[1;30m";
const char *LOGGER_COLOR_NONE = "\033[0m";
// global variables
int logger_verbosity;
int logger_use_colors;
void logger_init(void)
{
logger_verbosity = 2147483647;
logger_use_colors = 1;
}
void logger_shutdown(void)
{
// reserved for future use
}
void logger_enable_colors(int enable)
{
logger_use_colors = enable;
}
void logger_set_verbosity(int verbosity)
{
logger_verbosity = verbosity;
}
void logger_debug_message(const char *prefix, const char *fmt, va_list ap)
{
/* Guess we need no more than 100 bytes. */
int n, size = 100;
char *p, *np;
va_list internal_ap;
if ((p = (char*)malloc(size)) == NULL) {
fprintf(stderr, "[%s] FATAL: Cannot allocate string buffer while processing arguments.\n", LOGGER_STR_ERR);
return;
}
while (1) {
/* Try to print in the allocated space. */
va_copy(internal_ap, ap);
n = vsnprintf(p, size, fmt, internal_ap);
va_end(internal_ap);
/* If that worked, return the string. */
if (n > -1 && n < size) {
break;
}
/* Else try again with more space. */
if (n > -1) { /* glibc 2.1 */
size = n+1; /* precisely what is needed */
} else { /* glibc 2.0 */
size *= 2; /* twice the old size */
}
if ((np = (char*)realloc (p, size)) == NULL) {
free(p);
fprintf(stderr, "[%s] FATAL: Cannot reallocate string buffer while processing arguments.\n", LOGGER_STR_ERR);
return;
} else {
p = np;
}
}
// fprintf is thread-safe, so this always results in clean log lines.
// See flockfile(3).
fprintf(stderr, "%s %s\n", prefix, p);
free(p);
}
void logger_log(int level, const char *module_name, const char *format, ...)
{
va_list argptr;
char timebuf[32];
char timebuf2[32];
char prefixbuf[64];
const char *prefixcolor = "", *prefixtext = "";
if(level > logger_verbosity) {
return;
}
struct timeval tv;
gettimeofday(&tv, NULL);
strftime(timebuf, 32, "%Y-%m-%d %H:%M:%S.%%03d", localtime(&(tv.tv_sec)));
snprintf(timebuf2, 32, timebuf, tv.tv_usec/1000);
if(level >= LVL_DUMP) {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_DUMP;
}
prefixtext = LOGGER_STR_DUMP;
} else if(level >= LVL_DEBUG) {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_DEBUG;
}
prefixtext = LOGGER_STR_DEBUG;
} else if(level >= LVL_INFO) {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_INFO;
}
prefixtext = LOGGER_STR_INFO;
} else if(level >= LVL_WARN) {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_WARN;
}
prefixtext = LOGGER_STR_WARN;
} else if(level >= LVL_ERR) {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_ERR;
}
prefixtext = LOGGER_STR_ERR;
} else {
if(logger_use_colors) {
prefixcolor = LOGGER_COLOR_FATAL;
}
prefixtext = LOGGER_STR_FATAL;
}
if(logger_use_colors) {
sprintf(prefixbuf, "%s [%s%s%s %-8s]", timebuf2, prefixcolor, prefixtext, LOGGER_COLOR_NONE, module_name);
} else {
sprintf(prefixbuf, "%s [%s %-8s]", timebuf2, prefixtext, module_name);
}
va_start(argptr, format);
logger_debug_message(prefixbuf, format, argptr);
va_end(argptr);
}