feat(lnm): add logging framework
This commit is contained in:
parent
e44b7d0e5f
commit
3aa0ace863
4 changed files with 171 additions and 6 deletions
47
lnm/include/lnm/log.h
Normal file
47
lnm/include/lnm/log.h
Normal 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
|
||||
26
lnm/src/_include/lnm/log_internal.h
Normal file
26
lnm/src/_include/lnm/log_internal.h
Normal 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
Normal file
86
lnm/src/lnm_log.c
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue