feat(lnm): add logging framework

new-lnm-integration
Jef Roosens 2023-12-11 15:00:34 +01:00
parent e44b7d0e5f
commit 3aa0ace863
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
4 changed files with 171 additions and 6 deletions

View File

@ -0,0 +1,47 @@
#ifndef LNM_LOG
#define LOG
#include <stdarg.h>
#include "lnm/common.h"
typedef struct lnm_logger lnm_logger;
typedef enum lnm_log_level {
lnm_log_level_debug = 0,
lnm_log_level_info,
lnm_log_level_notice,
lnm_log_level_warning,
lnm_log_level_error,
lnm_log_level_critical
} lnm_log_level;
extern const char *lnm_log_level_names[];
/**
* Initialize the global logger.
*/
lnm_err lnm_log_init_global();
/**
* Register stdout as one of the streams for the global logger.
*/
lnm_err lnm_log_register_stdout(lnm_log_level level);
void lnm_log(lnm_log_level level, const char *section, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#define lnm_ldebug(section, fmt, ...) \
lnm_log(lnm_log_level_debug, section, fmt, __VA_ARGS__)
#define lnm_linfo(section, fmt, ...) \
lnm_log(lnm_log_level_info, section, fmt, __VA_ARGS__)
#define lnm_lnotice(section, fmt, ...) \
lnm_log(lnm_log_level_notice, section, fmt, __VA_ARGS__)
#define lnm_lwarning(section, fmt, ...) \
lnm_log(lnm_log_level_warning, section, fmt, __VA_ARGS__)
#define lnm_lerror(section, fmt, ...) \
lnm_log(lnm_log_level_error, section, fmt, __VA_ARGS__)
#define lnm_lcritical(section, fmt, ...) \
lnm_log(lnm_log_level_critical, section, fmt, __VA_ARGS__)
#endif

View File

@ -0,0 +1,26 @@
#ifndef LNM_LOG_INTERNAL
#define LNM_LOG_INTERNAL
#include "lnm/log.h"
typedef enum lnm_logger_stream_type {
lnm_logger_stream_type_file = 0
} lnm_logger_stream_type;
typedef struct lnm_logger_stream {
void *ptr;
lnm_logger_stream_type type;
lnm_log_level level;
} lnm_logger_stream;
struct lnm_logger {
struct {
lnm_logger_stream **arr;
size_t len;
} streams;
};
lnm_err lnm_logger_stream_register(lnm_logger *logger,
lnm_logger_stream *stream);
#endif

86
lnm/src/lnm_log.c 100644
View File

@ -0,0 +1,86 @@
#include <stdio.h>
#include <time.h>
#include "lnm/common.h"
#include "lnm/log_internal.h"
const char *lnm_log_level_names[] = {"DEBUG ", "INFO ", "NOTICE ",
"WARNING ", "ERROR ", "CRITICAL"};
lnm_logger *global_logger = NULL;
lnm_err lnm_log_init_global() {
global_logger = calloc(1, sizeof(lnm_logger));
return global_logger == NULL ? lnm_err_failed_alloc : lnm_err_ok;
}
lnm_err lnm_logger_stream_register(lnm_logger *logger,
lnm_logger_stream *stream) {
lnm_logger_stream **new =
logger->streams.len == 0
? malloc(sizeof(lnm_logger_stream *))
: realloc(logger->streams.arr,
(logger->streams.len + 1) * sizeof(lnm_logger_stream *));
if (new == NULL) {
return lnm_err_failed_alloc;
}
new[logger->streams.len] = stream;
logger->streams.arr = new;
logger->streams.len++;
return lnm_err_ok;
}
lnm_err lnm_log_register_stdout(lnm_log_level level) {
lnm_logger_stream *stream = malloc(sizeof(lnm_logger_stream));
if (stream == NULL) {
return lnm_err_failed_alloc;
}
stream->type = lnm_logger_stream_type_file;
stream->ptr = stdout;
stream->level = level;
LNM_RES2(lnm_logger_stream_register(global_logger, stream), free(stream));
return lnm_err_ok;
}
void lnm_vlog(lnm_log_level level, const char *section, const char *fmt,
va_list ap) {
char date_str[32];
time_t now = time(NULL);
strftime(date_str, sizeof(date_str) - 1, "%Y-%m-%d %H:%M:%S",
localtime(&now));
for (size_t i = 0; i < global_logger->streams.len; i++) {
lnm_logger_stream *stream = global_logger->streams.arr[i];
if (level < stream->level) {
continue;
}
switch (stream->type) {
case lnm_logger_stream_type_file:
fprintf(stream->ptr, "[%s][%s][%s] ", date_str,
lnm_log_level_names[level], section);
vfprintf(stream->ptr, fmt, ap);
fprintf(stream->ptr, "\n");
break;
}
va_end(ap);
}
}
void lnm_log(lnm_log_level level, const char *section, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
lnm_vlog(level, section, fmt, ap);
va_end(ap);
}

View File

@ -3,6 +3,7 @@
#include <time.h>
#include "lnm/http/loop.h"
#include "lnm/log.h"
#include "lander.h"
#include "log.h"
@ -61,7 +62,8 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) {
#define ENV(var, env_var) \
const char *var = getenv(env_var); \
if (var == NULL) { \
critical(1, "Missing environment variable %s", env_var); \
lnm_lcritical("main", "Missing environment variable %s", env_var); \
exit(1); \
}
#define ENV_OPT(var, env_var, default) \
@ -71,9 +73,11 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) {
}
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
srand(time(NULL));
lnm_log_init_global();
lnm_log_register_stdout(lnm_log_level_debug);
ENV(api_key, "LANDER_API_KEY");
ENV_OPT(port_str, "LANDER_PORT", "18080");
ENV_OPT(data_dir_s, "LANDER_DATA_DIR", ".");
@ -81,7 +85,8 @@ int main() {
int port = atoi(port_str);
if (port <= 0 || port >= 1 << 16) {
critical(1, "Invalid TCP port %s", port_str);
lnm_lcritical("main", "Invalid TCP port %s", port_str);
exit(1);
}
lander_gctx *c_gctx = lander_gctx_init();
@ -90,13 +95,14 @@ int main() {
lsm_str *data_dir;
lsm_str_init_copy(&data_dir, (char *)data_dir_s);
info("Initializing store from path '%s'", data_dir_s);
lnm_linfo("main", "Initializing store from path '%s'", data_dir_s);
if (lsm_store_load(&c_gctx->store, data_dir) != lsm_error_ok) {
critical(2, "Failed to load existing store.");
lnm_lcritical("main", "%s", "Failed to load existing store.");
}
info("Store loaded containing %lu entries", lsm_store_size(c_gctx->store));
lnm_linfo("main", "Store loaded containing %lu entries",
lsm_store_size(c_gctx->store));
lnm_http_loop *hl = loop_init(c_gctx, api_key);
lnm_http_loop_run(hl, port);