From 7973e45d16a81b287f817e740ea3641f617555d7 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Wed, 10 Apr 2024 16:28:49 +0200 Subject: [PATCH] [CORE] logger: add option to disable timestamps Add an option to disable printing the timestamp. This is useful to not have duplicate timestamps, when stderr is piped into a logging system that adds timestamps on its own. For example with systemd's journald: $ journalctl -u open5gs-smfd Apr 10 13:25:18 hostname open5gs-smfd[1582]: 04/10 13:25:18.274: [app] INFO: Configuration: '/etc/open5gs/smf.yaml' (../lib/app/ogs-init.c:130) Configuration change: ``` logger: file: /var/log/open5gs/smf.log logger: file: path: /var/log/open5gs/smf.log ``` Example config, to have no timestamps on stderr: ``` logger: default: timestamp: false file: path: /var/log/open5gs/smf.log timestamp: true ``` --- lib/app/ogs-context.h | 5 ++++ lib/app/ogs-init.c | 59 ++++++++++++++++++++++++++++++++++++++++--- lib/app/ogs-yaml.c | 28 ++++++++++++++++++++ lib/app/ogs-yaml.h | 1 + lib/core/ogs-log.c | 22 ++++++++++++++++ lib/core/ogs-log.h | 7 +++++ 6 files changed, 119 insertions(+), 3 deletions(-) diff --git a/lib/app/ogs-context.h b/lib/app/ogs-context.h index 3e8e11bea..a9e9787c2 100644 --- a/lib/app/ogs-context.h +++ b/lib/app/ogs-context.h @@ -36,10 +36,15 @@ typedef struct ogs_app_context_s { const char *db_uri; + struct { + ogs_log_ts_e timestamp; + } logger_default; + struct { const char *file; const char *level; const char *domain; + ogs_log_ts_e timestamp; } logger; ogs_queue_t *queue; diff --git a/lib/app/ogs-init.c b/lib/app/ogs-init.c index 2c117a4ff..bb4822948 100644 --- a/lib/app/ogs-init.c +++ b/lib/app/ogs-init.c @@ -114,6 +114,9 @@ int ogs_app_initialize( ogs_app()->logger.domain, ogs_app()->logger.level); if (rv != OGS_OK) return rv; + ogs_log_set_timestamp(ogs_app()->logger_default.timestamp, + ogs_app()->logger.timestamp); + /************************************************************************** * Stage 5 : Setup Database Module */ @@ -254,6 +257,57 @@ static int context_validation(void) return OGS_OK; } +static void parse_config_logger_file(ogs_yaml_iter_t *logger_iter, + const char *logger_key) +{ + ogs_yaml_iter_t iter; + + /* Legacy format: + * logger: + * file: /var/log/open5gs/mme.log */ + if (!strcmp(logger_key, "file") && ogs_yaml_iter_has_value(logger_iter)) { + ogs_app()->logger.file = ogs_yaml_iter_value(logger_iter); + + ogs_warn("Please change the configuration file as below."); + ogs_log_print(OGS_LOG_WARN, "\n\n"); + ogs_log_print(OGS_LOG_WARN, "logger:\n"); + ogs_log_print(OGS_LOG_WARN, " file: %s\n", ogs_app()->logger.file); + ogs_log_print(OGS_LOG_WARN, "\n\n"); + ogs_log_print(OGS_LOG_WARN, "logger:\n"); + ogs_log_print(OGS_LOG_WARN, " file:\n"); + ogs_log_print(OGS_LOG_WARN, " path: %s\n", ogs_app()->logger.file); + ogs_log_print(OGS_LOG_WARN, "\n\n\n"); + return; + } + + /* Current format: + * logger: + * default: + * timestamp: false + * file: + * path: /var/log/open5gs/mme.log + * timestamp: true */ + ogs_yaml_iter_recurse(logger_iter, &iter); + while (ogs_yaml_iter_next(&iter)) { + const char *key = ogs_yaml_iter_key(&iter); + ogs_assert(key); + if (!strcmp(key, "timestamp")) { + ogs_log_ts_e ts = ogs_yaml_iter_bool(&iter) + ? OGS_LOG_TS_ENABLED + : OGS_LOG_TS_DISABLED; + if (!strcmp(logger_key, "default")) { + ogs_app()->logger_default.timestamp = ts; + } else if (!strcmp(logger_key, "file")) { + ogs_app()->logger.timestamp = ts; + } + } else if (!strcmp(key, "path")) { + if (!strcmp(logger_key, "file")) { + ogs_app()->logger.file = ogs_yaml_iter_value(&iter); + } + } + } +} + static int parse_config(void) { int rv; @@ -278,9 +332,8 @@ static int parse_config(void) while (ogs_yaml_iter_next(&logger_iter)) { const char *logger_key = ogs_yaml_iter_key(&logger_iter); ogs_assert(logger_key); - if (!strcmp(logger_key, "file")) { - ogs_app()->logger.file = ogs_yaml_iter_value(&logger_iter); - } else if (!strcmp(logger_key, "level")) { + parse_config_logger_file(&logger_iter, logger_key); + if (!strcmp(logger_key, "level")) { ogs_app()->logger.level = ogs_yaml_iter_value(&logger_iter); } else if (!strcmp(logger_key, "domain")) { diff --git a/lib/app/ogs-yaml.c b/lib/app/ogs-yaml.c index 168ec50e8..7853b704e 100644 --- a/lib/app/ogs-yaml.c +++ b/lib/app/ogs-yaml.c @@ -178,6 +178,34 @@ const char *ogs_yaml_iter_value(ogs_yaml_iter_t *iter) return NULL; } +int ogs_yaml_iter_has_value(ogs_yaml_iter_t *iter) +{ + ogs_assert(iter); + ogs_assert(iter->document); + ogs_assert(iter->node); + + if (iter->node->type == YAML_SCALAR_NODE) { + return 1; + } else if (iter->node->type == YAML_MAPPING_NODE) { + yaml_node_t *node = NULL; + + ogs_assert(iter->pair); + node = yaml_document_get_node(iter->document, iter->pair->value); + ogs_assert(node); + return node->type == YAML_SCALAR_NODE; + } else if (iter->node->type == YAML_SEQUENCE_NODE) { + yaml_node_t *node = NULL; + + ogs_assert(iter->item); + node = yaml_document_get_node(iter->document, *iter->item); + ogs_assert(node); + return node->type == YAML_SCALAR_NODE; + } + + ogs_assert_if_reached(); + return 0; +} + int ogs_yaml_iter_bool(ogs_yaml_iter_t *iter) { const char *v = ogs_yaml_iter_value(iter); diff --git a/lib/app/ogs-yaml.h b/lib/app/ogs-yaml.h index 0fbd8646a..ac23bead0 100644 --- a/lib/app/ogs-yaml.h +++ b/lib/app/ogs-yaml.h @@ -59,6 +59,7 @@ void ogs_yaml_iter_recurse(ogs_yaml_iter_t *parent, ogs_yaml_iter_t *iter); int ogs_yaml_iter_type(ogs_yaml_iter_t *iter); const char *ogs_yaml_iter_key(ogs_yaml_iter_t *iter); const char *ogs_yaml_iter_value(ogs_yaml_iter_t *iter); +int ogs_yaml_iter_has_value(ogs_yaml_iter_t *iter); int ogs_yaml_iter_bool(ogs_yaml_iter_t *iter); #ifdef __cplusplus diff --git a/lib/core/ogs-log.c b/lib/core/ogs-log.c index 5baf385fb..ac43d6d7d 100644 --- a/lib/core/ogs-log.c +++ b/lib/core/ogs-log.c @@ -340,6 +340,28 @@ void ogs_log_set_mask_level(const char *_mask, ogs_log_level_e level) } } +void ogs_log_set_timestamp(ogs_log_ts_e ts_default, ogs_log_ts_e ts_file) +{ + ogs_log_t *log; + + if (ts_default == OGS_LOG_TS_UNSET) + ts_default = OGS_LOG_TS_ENABLED; + + if (ts_file == OGS_LOG_TS_UNSET) + ts_file = ts_default; + + ogs_list_for_each(&log_list, log) { + switch (log->type) { + case OGS_LOG_FILE_TYPE: + log->print.timestamp = (ts_file == OGS_LOG_TS_ENABLED); + break; + default: + log->print.timestamp = (ts_default == OGS_LOG_TS_ENABLED); + break; + } + } +} + static ogs_log_level_e ogs_log_level_from_string(const char *string) { ogs_log_level_e level = OGS_ERROR; diff --git a/lib/core/ogs-log.h b/lib/core/ogs-log.h index 24a6b77d1..547f19620 100644 --- a/lib/core/ogs-log.h +++ b/lib/core/ogs-log.h @@ -64,6 +64,12 @@ typedef enum { OGS_LOG_FULL = OGS_LOG_TRACE, } ogs_log_level_e; +typedef enum { + OGS_LOG_TS_UNSET, + OGS_LOG_TS_ENABLED, + OGS_LOG_TS_DISABLED, +} ogs_log_ts_e; + typedef struct ogs_log_s ogs_log_t; typedef struct ogs_log_domain_s ogs_log_domain_t; @@ -90,6 +96,7 @@ void ogs_log_install_domain(int *domain_id, int ogs_log_config_domain(const char *domain, const char *level); void ogs_log_set_mask_level(const char *mask, ogs_log_level_e level); +void ogs_log_set_timestamp(ogs_log_ts_e ts_default, ogs_log_ts_e ts_file); void ogs_log_vprintf(ogs_log_level_e level, int id, ogs_err_t err, const char *file, int line, const char *func,