[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:
```
<OLD Format>
logger:
  file: /var/log/open5gs/smf.log

<NEW Format>
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
```
This commit is contained in:
Oliver Smith 2024-04-10 16:28:49 +02:00 committed by Sukchan Lee
parent f960047ccb
commit 7973e45d16
6 changed files with 119 additions and 3 deletions

View File

@ -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;

View File

@ -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<OLD Format>\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<NEW Format>\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")) {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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,