153 lines
4.0 KiB
C
153 lines
4.0 KiB
C
#include "logger.h"
|
|
|
|
#include "logger_module.h"
|
|
#include "module_system.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
|
|
#define BZ_GET_LOGGER_MODULE() ((BzLoggerModule *) bzModuleRetrieve(BZ_MODULE_LOGGER))
|
|
|
|
bool bzLoggerInit() {
|
|
if (bzModuleIsAllocated(BZ_MODULE_LOGGER))
|
|
return false;
|
|
|
|
BzLoggerModule *logger = bzModuleAllocate(BZ_MODULE_LOGGER, sizeof(*logger));
|
|
if (logger == NULL)
|
|
return false;
|
|
|
|
logger->level = BZ_LOG_INFO;
|
|
logger->silent = false;
|
|
setvbuf(stdout, logger->buffer, _IOFBF, sizeof(logger->buffer));
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
void bzLoggerDeinit() {
|
|
BzLoggerModule *logger = BZ_GET_LOGGER_MODULE();
|
|
bzModuleFree(BZ_MODULE_LOGGER);
|
|
}
|
|
|
|
void bzLoggerEnableDefaultLog(bool enable) {
|
|
BZ_GET_LOGGER_MODULE()->silent = !enable;
|
|
}
|
|
|
|
void bzLoggerSetLevel(BzLoggerLevel level) {
|
|
BZ_GET_LOGGER_MODULE()->level = level;
|
|
}
|
|
|
|
BzLoggerLevel bzLoggerGetLevel() {
|
|
return BZ_GET_LOGGER_MODULE()->level;
|
|
}
|
|
|
|
|
|
static const char *LEVEL_STRINGS[] = {
|
|
"TRACE",
|
|
"DEBUG",
|
|
"INFO",
|
|
"WARNING",
|
|
"ERROR",
|
|
"FATAL"
|
|
};
|
|
static const char *LEVEL_COLORS[] = {
|
|
"\x1b[90m", // TRACE -> Bright black
|
|
"\x1b[96m", // DEBUG -> Bright cyan
|
|
"\x1b[32m", // INFO -> Green
|
|
"\x1b[33m", // WARN -> Yellow
|
|
"\x1b[31m", // ERROR -> Red
|
|
"\x1b[91m", // FATAL -> Bright red
|
|
};
|
|
|
|
static void bzLoggerStdOutCallback(BzLoggerEvent *ev) {
|
|
fprintf(stdout, "%s %s%-5s\x1b[0m ",ev->time,
|
|
LEVEL_COLORS[ev->level], LEVEL_STRINGS[ev->level]);
|
|
if (ev->file) {
|
|
fprintf(stdout, "\x1b[90m(%s:%d)\x1b[0m ",
|
|
ev->file, ev->line);
|
|
}
|
|
vfprintf(stdout, ev->fmt, ev->va);
|
|
fprintf(stdout, "\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
static void bzLoggerFileCallback(BzLoggerEvent *ev) {
|
|
FILE *fp = ev->userData;
|
|
fprintf(fp, "%s %-5s ", ev->time, LEVEL_STRINGS[ev->level]);
|
|
if (ev->file) {
|
|
fprintf(fp, "(%s:%d): ", ev->file, ev->line);
|
|
}
|
|
vfprintf(fp, ev->fmt, ev->va);
|
|
fflush(fp);
|
|
}
|
|
|
|
void bzLoggerLog(BzLoggerLevel level, const char *file, int line, const char *fmt, ...) {
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
bzLoggerLogV(level, file, line, fmt, args);
|
|
va_end(args);
|
|
}
|
|
void bzLoggerLogV(BzLoggerLevel level, const char *file, int line, const char *fmt, va_list va) {
|
|
BzLoggerEvent event = {NULL, NULL, level, file, line, fmt};
|
|
const int loggerLevel = bzLoggerGetLevel();
|
|
|
|
time_t t = time(NULL);
|
|
struct tm *lt = localtime(&t);
|
|
char timeBuf[16];
|
|
size_t lastIdx = strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", lt);
|
|
// TODO: Assert
|
|
timeBuf[lastIdx] = '\0';
|
|
event.time = timeBuf;
|
|
|
|
if (!BZ_GET_LOGGER_MODULE()->silent && level >= loggerLevel) {
|
|
event.userData = stderr;
|
|
va_copy(event.va, va);
|
|
bzLoggerStdOutCallback(&event);
|
|
va_end(event.va);
|
|
}
|
|
|
|
for (int i = 0; i < BZ_LOGGER_MAX_CALLBACKS; ++i) {
|
|
BzLoggerCallback cb = BZ_GET_LOGGER_MODULE()->callbacks[i];
|
|
if (!cb.callback) break;
|
|
|
|
if (level >= cb.level) {
|
|
event.userData = cb.userData;
|
|
|
|
va_copy(event.va, va);
|
|
cb.callback(&event);
|
|
va_end(event.va);
|
|
}
|
|
}
|
|
}
|
|
void bzLoggerOnlyLog(BzLoggerLevel level, const char *fmt, ...) {
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
bzLoggerOnlyLogV(level, fmt, args);
|
|
va_end(args);
|
|
}
|
|
void bzLoggerOnlyLogV(BzLoggerLevel level, const char *fmt, va_list va) {
|
|
bzLoggerLogV(level, NULL, -1, fmt, va);
|
|
}
|
|
|
|
|
|
bool bzLoggerAddFP(void *fp, BzLoggerLevel level) {
|
|
return bzLoggerAddCB(&(BzLoggerCallback) {
|
|
.callback = bzLoggerFileCallback,
|
|
.level = level,
|
|
.userData = fp
|
|
});
|
|
}
|
|
|
|
bool bzLoggerAddCB(const BzLoggerCallback *callback) {
|
|
for (int i = 0; i < BZ_LOGGER_MAX_CALLBACKS; ++i) {
|
|
BzLoggerCallback *cbSlot = &BZ_GET_LOGGER_MODULE()->callbacks[i];
|
|
|
|
if (cbSlot->callback == NULL) {
|
|
*cbSlot = *callback;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} |