Files
PixelDefense/engine/breeze/core/logger.c

139 lines
3.4 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;
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",
"WARN",
"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) {
va_list *ap = ev->apList;
fprintf(stderr, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
ev->time, LEVEL_STRINGS[ev->level], LEVEL_COLORS[ev->level], ev->file, ev->line);
vfprintf(stderr, ev->fmt, *ap);
fprintf(stderr, "\n");
fflush(stderr);
}
static void bzLoggerFileCallback(BzLoggerEvent *ev) {
FILE *fp = ev->userData;
va_list *ap = ev->apList;
fprintf(fp, "%s %-5s %s:%d: ", ev->time, LEVEL_STRINGS[ev->level], ev->file, ev->line);
vfprintf(fp, ev->fmt, *ap);
fflush(fp);
}
void bzLoggerLog(BzLoggerLevel level, const char *file, int line, const char *fmt, ...) {
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_list ap;
va_start(ap, fmt);
event.apList = &ap;
bzLoggerStdOutCallback(&event);
va_end(ap);
}
for (int i = 0; i < BZ_LOGGER_MAX_CALLBACKS; ++i) {
BzLoggerCallback cb = BZ_GET_LOGGER_MODULE()->callbacks[i];
if (level <= cb.level) {
event.userData = cb.userData;
va_list ap;
va_start(ap, fmt);
event.apList = &ap;
cb.callback(&event);
va_end(ap);
}
}
}
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;
}