Skip to content

Commit

Permalink
logger: API redesign; and some enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
sidcha committed Sep 3, 2023
1 parent 114df5b commit 2dfd014
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 83 deletions.
64 changes: 25 additions & 39 deletions include/utils/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <stdio.h>
#include <utils/utils.h>

#define LOGGER_NAME_MAXLEN 16

/**
* @brief A printf() like method that will be used to write out log lines.
*
Expand All @@ -21,12 +23,12 @@
typedef int (*log_puts_fn_t)(const char *buf);

typedef struct {
const char *module;
char name[LOGGER_NAME_MAXLEN];
const char *root_path;
int log_level;
uint32_t flags;
FILE *file;
log_puts_fn_t puts;
char *prefix;
} logger_t;

enum log_levels {
Expand All @@ -43,48 +45,32 @@ enum log_levels {

#define LOGGER_FLAG_NONE 0x00000000
#define LOGGER_FLAG_NO_COLORS 0x00000001
#define LOGGER_FLAG_HAS_PREFIX 0x00000002
#define LOGGER_FLAG_PREFIX_ALLOC 0x00000004

int logger_log(logger_t *ctx, int log_level, const char *tag, const char *fmt, ...);
/* Don't call this method directly. Use LOG_* macros below */
int __logger_log(logger_t *ctx, int log_level, const char *file,
unsigned long line, const char *fmt, ...);

int logger_init(logger_t *ctx, int log_level, const char *name,
const char *root_path, log_puts_fn_t puts_fn, FILE *file,
int flags);
void logger_get_default(logger_t *ctx);
void logger_set_default(logger_t *logger);
void logger_set_log_level(logger_t *ctx, int log_level);
void logger_set_put_fn(logger_t *ctx, log_puts_fn_t fn);
void logger_set_file(logger_t *ctx, FILE *f);
void logger_clear_prefix(logger_t *ctx);
void logger_set_prefix(logger_t *ctx, const char *prefix);

#define LOGGER_DEFINE(mod_name, lvl, fl) \
logger_t mod_name ## _logger_ctx = { \
.module = STR(mod_name), \
.log_level = lvl, \
.flags = fl, \
.file = NULL, \
.puts = NULL, \
}; \
logger_t *get_ ## mod_name ## _logger_ctx() { \
return &mod_name ## _logger_ctx; \
};

#define get_log_ctx(mod_name) get_ ## mod_name ## _logger_ctx()

#define LOGGER_DECLARE(mod_name, tag) \
static const char * const LOG_TAG __attribute__((unused)) = tag; \
extern logger_t *get_ ## mod_name ## _logger_ctx(); \
static inline logger_t *get_current_logger_ctx() { \
return get_ ## mod_name ## _logger_ctx(); \
}
void logger_set_name(logger_t *ctx, const char *name);

#define LOG_EM(...) logger_log(get_current_logger_ctx(), LOG_EMERG, LOG_TAG, __VA_ARGS__)
#define LOG_ALERT(...) logger_log(get_current_logger_ctx(), LOG_ALERT, LOG_TAG, __VA_ARGS__)
#define LOG_CRIT(...) logger_log(get_current_logger_ctx(), LOG_CRIT, LOG_TAG, __VA_ARGS__)
#define LOG_ERR(...) logger_log(get_current_logger_ctx(), LOG_ERR, LOG_TAG, __VA_ARGS__)
#define LOG_INF(...) logger_log(get_current_logger_ctx(), LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOG_WRN(...) logger_log(get_current_logger_ctx(), LOG_WARNING,LOG_TAG, __VA_ARGS__)
#define LOG_NOT(...) logger_log(get_current_logger_ctx(), LOG_NOTICE, LOG_TAG, __VA_ARGS__)
#define LOG_DBG(...) logger_log(get_current_logger_ctx(), LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOG_PRINT(...) logger_log(get_current_logger_ctx(), LOG_INFO, LOG_TAG, __VA_ARGS__)
#ifndef USE_CUSTOM_LOGGER
#define LOG_EM(...) __logger_log(NULL, LOG_EMERG, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_ALERT(...) __logger_log(NULL, LOG_ALERT, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_CRIT(...) __logger_log(NULL, LOG_CRIT, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_ERR(...) __logger_log(NULL, LOG_ERR, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INF(...) __logger_log(NULL, LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_WRN(...) __logger_log(NULL, LOG_WARNING,__FILE__, __LINE__, __VA_ARGS__)
#define LOG_NOT(...) __logger_log(NULL, LOG_NOTICE, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_DBG(...) __logger_log(NULL, LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#endif

#define LOG_SET_PREFIX(str) logger_set_prefix(get_current_logger_ctx(), str);
#define LOG_CLEAR_PREFIX() logger_clear_prefix(get_current_logger_ctx())
#define LOG_PRINT(...) __logger_log(NULL, LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)

#endif /* _LOGGER_H_ */
139 changes: 95 additions & 44 deletions src/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <time.h>

#include <utils/logger.h>

Expand All @@ -24,6 +25,15 @@
#define WHT "\x1B[37m"
#define RESET "\x1B[0m"

logger_t default_logger = {
.file = NULL,
.flags = LOGGER_FLAG_NONE,
.log_level = LOG_INFO,
.name = "GLOBAL",
.puts = puts,
.root_path = NULL,
};

static const char *log_level_colors[LOG_MAX_LEVEL] = {
RED, RED, RED, RED,
YEL, MAG, GRN, RESET
Expand All @@ -34,36 +44,6 @@ static const char *log_level_names[LOG_MAX_LEVEL] = {
"WARN ", "NOTIC", "INFO ", "DEBUG"
};

void logger_clear_prefix(logger_t *ctx)
{
ctx->prefix = NULL;
ctx->flags &= ~LOGGER_FLAG_HAS_PREFIX;
}

void logger_set_prefix(logger_t *ctx, const char *prefix)
{
logger_clear_prefix(ctx);
if (prefix) {
ctx->prefix = (char *)prefix;
ctx->flags |= LOGGER_FLAG_HAS_PREFIX;
}
}

void logger_set_log_level(logger_t *ctx, int log_level)
{
ctx->log_level = log_level;
}

void logger_set_put_fn(logger_t *ctx, log_puts_fn_t fn)
{
ctx->puts = fn;
}

void logger_set_file(logger_t *ctx, FILE *f)
{
ctx->file = f;
}

static inline void logger_log_set_color(logger_t *ctx, const char *color)
{
int ret, len;
Expand All @@ -79,37 +59,59 @@ static inline void logger_log_set_color(logger_t *ctx, const char *color)
}
}

static const char *get_rel_path(logger_t *ctx, const char *abs_path)
{
const char *p, *q;

if (!ctx->root_path || abs_path[0] != '/')
return abs_path;

p = ctx->root_path;
q = abs_path;
while (*p != '\0' && *q != '\0' && *p == *p) {
p++;
q++;
}
while (*q != '\0' && *q == '/')
q++;
return q;
}

static const char *get_tstamp()
{
static char time_buf[24];
struct tm gmt;
time_t now = time(NULL);

gmtime_r(&now, &gmt);
strftime(time_buf, sizeof(time_buf), "%Y-%m-%dT%H:%M:%S", &gmt);
return time_buf;
}

#define LOG_BUF_LEN 128

__attribute__((format(printf, 4, 5)))
int logger_log(logger_t *ctx, int log_level, const char *tag,
const char *fmt, ...)
__attribute__((format(printf, 5, 6)))
int __logger_log(logger_t *ctx, int log_level, const char *file, unsigned long line,
const char *fmt, ...)
{
int len = 0;
va_list args;
char buf[LOG_BUF_LEN + 2]; /* +2 for tailing '\n' and '\0' */

assert(ctx);
assert(ctx->file || ctx->puts);
if (!ctx)
ctx = &default_logger;

if (log_level < LOG_EMERG ||
log_level >= LOG_MAX_LEVEL ||
log_level > ctx->log_level)
return 0;

/* print module and log_level prefix */
len = snprintf(buf, LOG_BUF_LEN, "%s: %s: %s: ", ctx->module, tag,
log_level_names[log_level]);
len = snprintf(buf, LOG_BUF_LEN, "%s: [%s] [%s] %s:%lu: ", ctx->name, get_tstamp(),
log_level_names[log_level], get_rel_path(ctx, file), line);
if (len > LOG_BUF_LEN)
goto out;

/* Any other prefix set by user */
if (ctx->flags & LOGGER_FLAG_HAS_PREFIX) {
len += snprintf(buf + len, LOG_BUF_LEN - len, "%s: ", ctx->prefix);
if (len > LOG_BUF_LEN)
goto out;
}

/* Print the actual message */
va_start(args, fmt);
len += vsnprintf(buf + len, LOG_BUF_LEN - len, fmt, args);
Expand Down Expand Up @@ -137,3 +139,52 @@ int logger_log(logger_t *ctx, int log_level, const char *tag,

return len;
}

void logger_get_default(logger_t *ctx)
{
memcpy(ctx, &default_logger, sizeof(default_logger));
}

void logger_set_default(logger_t *logger)
{
default_logger = *logger;
}

void logger_set_log_level(logger_t *ctx, int log_level)
{
ctx->log_level = log_level;
}

void logger_set_put_fn(logger_t *ctx, log_puts_fn_t fn)
{
ctx->puts = fn;
}

void logger_set_file(logger_t *ctx, FILE *f)
{
ctx->file = f;
}

void logger_set_name(logger_t *ctx, const char *name)
{
if (!name)
return;
strncpy(ctx->name, name, LOGGER_NAME_MAXLEN);
ctx->name[LOGGER_NAME_MAXLEN - 1] = '\0';
}

int logger_init(logger_t *ctx, int log_level, const char *name,
const char *root_path, log_puts_fn_t puts_fn, FILE *file,
int flags)
{
if (!puts_fn && !file)
return -1;

ctx->log_level = log_level;
ctx->root_path = root_path;
ctx->puts = puts_fn;
ctx->file = file;
ctx->flags = flags;
logger_set_name(ctx, name);
return 0;
}

0 comments on commit 2dfd014

Please sign in to comment.