187 lines
4.7 KiB
C
187 lines
4.7 KiB
C
|
/*
|
||
|
* 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 *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]", timebuf2, prefixcolor, prefixtext, LOGGER_COLOR_NONE);
|
||
|
} else {
|
||
|
sprintf(prefixbuf, "%s [%s]", timebuf2, prefixtext);
|
||
|
}
|
||
|
|
||
|
va_start(argptr, format);
|
||
|
logger_debug_message(prefixbuf, format, argptr);
|
||
|
va_end(argptr);
|
||
|
}
|