logger changes from global static variables to one instance per stellar
This commit is contained in:
156
src/log/log.cpp
156
src/log/log.cpp
@@ -1,5 +1,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
@@ -7,8 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "toml.h"
|
||||
#include "log_private.h"
|
||||
|
||||
enum log_output
|
||||
{
|
||||
@@ -24,39 +26,38 @@ struct log_config
|
||||
char log_file[PATH_MAX];
|
||||
};
|
||||
|
||||
struct log_context
|
||||
struct logger
|
||||
{
|
||||
char config_file[PATH_MAX];
|
||||
struct log_config config;
|
||||
|
||||
int log_fd;
|
||||
int log_file_reopen_day;
|
||||
int log_file_opened_day;
|
||||
};
|
||||
|
||||
struct log_context g_log_context = {
|
||||
.config = {},
|
||||
.log_fd = -1,
|
||||
.log_file_reopen_day = 0,
|
||||
};
|
||||
|
||||
struct log_context *g_log_ctx = &g_log_context;
|
||||
|
||||
static unsigned char level_str[6][6] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
|
||||
static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
static unsigned char level_str[7][6] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "STATE"};
|
||||
|
||||
static inline void local_time(struct tm *local)
|
||||
thread_local struct logger *__thread_local_logger;
|
||||
|
||||
/******************************************************************************
|
||||
* Private API
|
||||
******************************************************************************/
|
||||
|
||||
static void local_time(struct tm *local)
|
||||
{
|
||||
time_t t;
|
||||
time(&t);
|
||||
localtime_r(&t, local);
|
||||
}
|
||||
|
||||
static inline enum log_level check_level(const char *level)
|
||||
static int str_to_level(const char *level)
|
||||
{
|
||||
if (level == NULL)
|
||||
{
|
||||
return LOG_NONE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcasecmp(level, "TRACE") == 0)
|
||||
{
|
||||
return LOG_TRACE;
|
||||
@@ -83,13 +84,11 @@ static inline enum log_level check_level(const char *level)
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOG_NONE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// return 0: success
|
||||
// return -1: failed
|
||||
static int parse_config(struct log_config *config, const char *cfg_file)
|
||||
static int config_parse(struct log_config *config, const char *config_file)
|
||||
{
|
||||
int ret = -1;
|
||||
FILE *fp = NULL;
|
||||
@@ -101,32 +100,31 @@ static int parse_config(struct log_config *config, const char *cfg_file)
|
||||
toml_table_t *section = NULL;
|
||||
toml_table_t *table = NULL;
|
||||
|
||||
fp = fopen(cfg_file, "r");
|
||||
fp = fopen(config_file, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "open config file %s failed, %s\n", cfg_file, strerror(errno));
|
||||
fprintf(stderr, "(logger) open config file %s failed, %s\n", config_file, strerror(errno));
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
table = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||
if (table == NULL)
|
||||
{
|
||||
fprintf(stderr, "parse config file %s failed, %s\n", cfg_file, errbuf);
|
||||
fprintf(stderr, "(logger) parse config file %s failed, %s\n", config_file, errbuf);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
section = toml_table_in(table, "log");
|
||||
if (section == NULL)
|
||||
{
|
||||
fprintf(stderr, "config file %s missing log section\n", cfg_file);
|
||||
fprintf(stderr, "(logger) config file %s missing log section\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
// output
|
||||
ptr = toml_raw_in(section, "output");
|
||||
if (ptr == NULL || toml_rtos(ptr, &ptr_output) != 0)
|
||||
{
|
||||
fprintf(stderr, "config file %s missing log.output\n", cfg_file);
|
||||
fprintf(stderr, "(logger) config file %s missing log.output\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
if (strcasecmp(ptr_output, "stderr") == 0)
|
||||
@@ -143,7 +141,7 @@ static int parse_config(struct log_config *config, const char *cfg_file)
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "config file %s invalid log.output\n", cfg_file);
|
||||
fprintf(stderr, "(logger) config file %s invalid log.output\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@@ -152,30 +150,28 @@ static int parse_config(struct log_config *config, const char *cfg_file)
|
||||
ptr = toml_raw_in(section, "file");
|
||||
if (ptr == NULL || toml_rtos(ptr, &ptr_file) != 0)
|
||||
{
|
||||
fprintf(stderr, "config file %s missing log.file\n", cfg_file);
|
||||
fprintf(stderr, "(logger) config file %s missing log.file\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
strcpy(config->log_file, ptr_file);
|
||||
}
|
||||
|
||||
// level
|
||||
ptr = toml_raw_in(section, "level");
|
||||
if (ptr == NULL || toml_rtos(ptr, &ptr_level) != 0)
|
||||
{
|
||||
fprintf(stderr, "config file %s missing log.level\n", cfg_file);
|
||||
fprintf(stderr, "(logger) config file %s missing log.level\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
config->level = check_level(ptr_level);
|
||||
if (config->level == LOG_NONE)
|
||||
config->level = (enum log_level)str_to_level(ptr_level);
|
||||
if (config->level == -1)
|
||||
{
|
||||
fprintf(stderr, "config file %s invalid log.level\n", cfg_file);
|
||||
fprintf(stderr, "config file %s invalid log.level\n", config_file);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
error_out:
|
||||
|
||||
if (ptr_output)
|
||||
{
|
||||
free(ptr_output);
|
||||
@@ -200,27 +196,25 @@ error_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
// return 0: success
|
||||
// return -1: failed
|
||||
static int log_reopen()
|
||||
static int log_file_reopen(struct logger *logger)
|
||||
{
|
||||
int new_fd;
|
||||
int old_fd;
|
||||
struct tm local;
|
||||
char buff[PATH_MAX * 2] = {0};
|
||||
local_time(&local);
|
||||
snprintf(buff, sizeof(buff), "%s.%d-%02d-%02d", g_log_ctx->config.log_file, local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
|
||||
snprintf(buff, sizeof(buff), "%s.%d-%02d-%02d", logger->config.log_file, local.tm_year + 1900, local.tm_mon + 1, local.tm_mday);
|
||||
|
||||
new_fd = open(buff, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
||||
if (new_fd == -1)
|
||||
{
|
||||
fprintf(stderr, "open() \"%s\" failed, %s\n", buff, strerror(errno));
|
||||
fprintf(stderr, "(logger) open() \"%s\" failed, %s\n", buff, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_log_ctx->log_file_reopen_day = local.tm_mday;
|
||||
old_fd = g_log_ctx->log_fd;
|
||||
g_log_ctx->log_fd = new_fd;
|
||||
logger->log_file_opened_day = local.tm_mday;
|
||||
old_fd = logger->log_fd;
|
||||
logger->log_fd = new_fd;
|
||||
|
||||
if (old_fd > 0)
|
||||
{
|
||||
@@ -234,56 +228,74 @@ static int log_reopen()
|
||||
* Public API
|
||||
******************************************************************************/
|
||||
|
||||
// return 0: success
|
||||
// return -1: failed
|
||||
int log_init(const char *config_file)
|
||||
struct logger *log_new(const char *config_file)
|
||||
{
|
||||
memset(g_log_ctx, 0, sizeof(struct log_context));
|
||||
|
||||
if (parse_config(&g_log_ctx->config, config_file) != 0)
|
||||
struct logger *logger = (struct logger *)calloc(1, sizeof(struct logger));
|
||||
if (logger == NULL)
|
||||
{
|
||||
return -1;
|
||||
fprintf(stderr, "(logger) logger calloc() failed, %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_log_context.config.output == LOG_OUTPUT_FILE || g_log_context.config.output == LOG_OUTPUT_BOTH)
|
||||
memcpy(&logger->config_file, config_file, strlen(config_file));
|
||||
if (config_parse(&logger->config, config_file) != 0)
|
||||
{
|
||||
if (log_reopen() != 0)
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (logger->config.output == LOG_OUTPUT_FILE || logger->config.output == LOG_OUTPUT_BOTH)
|
||||
{
|
||||
if (log_file_reopen(logger) != 0)
|
||||
{
|
||||
return -1;
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return logger;
|
||||
|
||||
error_out:
|
||||
log_free(logger);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void log_free()
|
||||
void log_free(struct logger *logger)
|
||||
{
|
||||
if (g_log_ctx->config.output == LOG_OUTPUT_FILE || g_log_ctx->config.output == LOG_OUTPUT_BOTH)
|
||||
if (logger)
|
||||
{
|
||||
if (g_log_ctx->log_fd > 0)
|
||||
if (logger->config.output == LOG_OUTPUT_FILE || logger->config.output == LOG_OUTPUT_BOTH)
|
||||
{
|
||||
close(g_log_ctx->log_fd);
|
||||
g_log_ctx->log_fd = -1;
|
||||
if (logger->log_fd > 0)
|
||||
{
|
||||
close(logger->log_fd);
|
||||
logger->log_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
free(logger);
|
||||
logger = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int log_level_check(enum log_level level)
|
||||
int log_level_check(struct logger *logger, enum log_level level)
|
||||
{
|
||||
return level >= g_log_ctx->config.level;
|
||||
return level >= logger->config.level;
|
||||
}
|
||||
|
||||
void log_level_reload(const char *config_file)
|
||||
void log_level_reload(struct logger *logger)
|
||||
{
|
||||
struct log_config config;
|
||||
if (parse_config(&config, config_file) != 0)
|
||||
struct log_config config = {};
|
||||
if (config_parse(&config, logger->config_file) == 0)
|
||||
{
|
||||
return;
|
||||
logger->config.level = config.level;
|
||||
fprintf(stderr, "(logger) logger level reload to %s\n", level_str[config.level]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "(logger) logger level reload failed\n");
|
||||
}
|
||||
g_log_context.config.level = config.level;
|
||||
}
|
||||
|
||||
void log_print(enum log_level level, const char *module, const char *fmt, ...)
|
||||
void log_print(struct logger *logger, enum log_level level, const char *module, const char *fmt, ...)
|
||||
{
|
||||
int nwrite;
|
||||
char buf[4096] = {0};
|
||||
@@ -309,20 +321,20 @@ void log_print(enum log_level level, const char *module, const char *fmt, ...)
|
||||
// add end of line
|
||||
p += snprintf(p, end - p, "\n");
|
||||
|
||||
if (g_log_ctx->config.output == LOG_OUTPUT_STDERR || g_log_ctx->config.output == LOG_OUTPUT_BOTH)
|
||||
if (logger->config.output == LOG_OUTPUT_STDERR || logger->config.output == LOG_OUTPUT_BOTH)
|
||||
{
|
||||
fprintf(stderr, "%s", buf);
|
||||
}
|
||||
|
||||
if (g_log_ctx->config.output == LOG_OUTPUT_FILE || g_log_ctx->config.output == LOG_OUTPUT_BOTH)
|
||||
if (logger->config.output == LOG_OUTPUT_FILE || logger->config.output == LOG_OUTPUT_BOTH)
|
||||
{
|
||||
if (g_log_ctx->log_file_reopen_day != local.tm_mday)
|
||||
if (logger->log_file_opened_day != local.tm_mday)
|
||||
{
|
||||
log_reopen();
|
||||
log_file_reopen(logger);
|
||||
}
|
||||
do
|
||||
{
|
||||
nwrite = write(g_log_ctx->log_fd, buf, p - buf);
|
||||
nwrite = write(logger->log_fd, buf, p - buf);
|
||||
} while (nwrite == -1 && errno == EINTR);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user