diff --git a/configure.ac b/configure.ac index 6c7126f56..6f0c0d552 100644 --- a/configure.ac +++ b/configure.ac @@ -131,6 +131,7 @@ CFLAGS="$saved_CFLAGS" AC_SUBST(SYMBOL_VISIBILITY) AC_CHECK_FUNCS(localtime_r) +AC_CHECK_FUNCS(gmtime_r) AC_DEFUN([CHECK_TM_INCLUDES_TM_GMTOFF], [ AC_CACHE_CHECK( diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index b9f65ec7c..33f38d983 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -297,6 +297,11 @@ enum log_filename_pos { LOG_FILENAME_POS_LINE_END, }; +enum log_timezone { + LOG_TIMEZONE_LOCALTIME, + LOG_TIMEZONE_UTC, +}; + /*! Format of the timestamp printed */ enum log_timestamp_format { LOG_TIMESTAMP_NONE, @@ -411,6 +416,8 @@ struct log_target { /* Where on a log line to put the source file info. */ enum log_filename_pos print_filename_pos; + /* Set timezone for timestamps (if at all enabled) */ + enum log_timezone timezone; /* Timestamp format */ enum log_timestamp_format timestamp_format; }; @@ -438,6 +445,7 @@ void log_set_print_extended_timestamp(struct log_target *target, int flag) void log_set_print_timestamp(struct log_target *target, int flag) OSMO_DEPRECATED("Use log_set_print_timestamp2(LOG_TIMESTAMP_CTIME) instead"); void log_set_print_timestamp2(struct log_target *target, enum log_timestamp_format format); +void log_set_timezone(struct log_target *target, enum log_timezone timezone); void log_set_print_tid(struct log_target *target, int); void log_set_print_filename(struct log_target *target, int) OSMO_DEPRECATED("Use log_set_print_filename2() instead"); void log_set_print_filename2(struct log_target *target, enum log_filename_type lft); diff --git a/src/core/libosmocore.map b/src/core/libosmocore.map index 63053fd89..f22c20751 100644 --- a/src/core/libosmocore.map +++ b/src/core/libosmocore.map @@ -91,6 +91,7 @@ log_set_print_level; log_set_print_tid; log_set_print_timestamp; log_set_use_color; +log_set_timezone; log_target_create; log_target_create_file; log_target_create_file_stream; diff --git a/src/core/logging.c b/src/core/logging.c index 827608b5f..873860a3f 100644 --- a/src/core/logging.c +++ b/src/core/logging.c @@ -579,11 +579,20 @@ static const char *const_basename(const char *path) static int get_timestamp(struct timeval *tv, struct tm *tm, const struct log_target *target) { osmo_gettimeofday(tv, NULL); + switch (target->timezone) { + case LOG_TIMEZONE_LOCALTIME: #ifdef HAVE_LOCALTIME_R - return (localtime_r(&tv->tv_sec, tm) != NULL) ? 0 : -1; -#else - return -1; + return (localtime_r(&tv->tv_sec, tm) != NULL) ? 0 : -1; #endif + /* If there is no localtime_r() function, then maybe gmtime_r() is available instead? */ + case LOG_TIMEZONE_UTC: +#ifdef HAVE_GMTIME_R + return (gmtime_r(&tv->tv_sec, tm) != NULL) ? 0 : -1; +#endif + /* If there is no gmtime_r() function, then print no timestamp. */ + default: + return -1; + } } /*! main output formatting function for log lines. @@ -960,6 +969,15 @@ void log_set_print_timestamp(struct log_target *target, int print_timestamp) log_set_print_timestamp2(target, print_timestamp ? LOG_TIMESTAMP_CTIME : LOG_TIMESTAMP_NONE); } +/*! Switch logging timezone between UTC or local time. + * \param[in] target Log target to be affected. + * \param[in] timezone Timezone to set. + */ +void log_set_timezone(struct log_target *target, enum log_timezone timezone) +{ + target->timezone = timezone; +} + /*! Use log_set_print_timestamp2(LOG_TIMESTAMP_DATE_PACKED) instead. * Enable or disable printing of extended timestamps while logging. * \param[in] target Log target to be affected diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index cb4a280dc..5566f05fb 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -190,6 +190,22 @@ DEFUN(logging_use_clr, RET_WITH_UNLOCK(CMD_SUCCESS); } +DEFUN(logging_timezone, + logging_timezone_cmd, + "logging timezone (localtime|utc)", + LOGGING_STR "Configure time zone for log message timestamping\n" + "Log timestamps in the system's local time\n" + "Log timestamps in Coordinated Universal Time (UTC)\n") +{ + struct log_target *tgt; + ACQUIRE_VTY_LOG_TGT_WITH_LOCK(vty, tgt); + if (strcmp(argv[0], "utc") == 0) + log_set_timezone(tgt, LOG_TIMEZONE_UTC); + else + log_set_timezone(tgt, LOG_TIMEZONE_LOCALTIME); + RET_WITH_UNLOCK(CMD_SUCCESS); +} + DEFUN_DEPRECATED(logging_timestamp, logging_timestamp_cmd, "logging timestamp (0|1)", @@ -1099,6 +1115,16 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) vty_out(vty, " logging print timestamp %s%s", log_timestamp_format_name(tgt->timestamp_format), VTY_NEWLINE); + switch (tgt->timezone) { + case LOG_TIMEZONE_UTC: + vty_out(vty, " logging timezone utc%s", VTY_NEWLINE); + break; + default: + case LOG_TIMEZONE_LOCALTIME: + /* write nothing, since LOG_TIMEZONE_LOCALTIME is the default */ + break; + } + if (tgt->print_level) vty_out(vty, " logging print level 1%s", VTY_NEWLINE); vty_out(vty, " logging print file %s%s%s", @@ -1243,6 +1269,7 @@ void logging_vty_add_cmds(void) install_lib_element_ve(&logging_timestamp_cmd); install_lib_element_ve(&logging_prnt_timestamp_cmd); install_lib_element_ve(&logging_prnt_ext_timestamp_cmd); + install_lib_element_ve(&logging_timezone_cmd); install_lib_element_ve(&logging_prnt_tid_cmd); install_lib_element_ve(&logging_prnt_cat_cmd); install_lib_element_ve(&logging_prnt_cat_hex_cmd); @@ -1279,6 +1306,7 @@ void logging_vty_add_cmds(void) install_lib_element(CFG_LOG_NODE, &logging_timestamp_cmd); install_lib_element(CFG_LOG_NODE, &logging_prnt_timestamp_cmd); install_lib_element(CFG_LOG_NODE, &logging_prnt_ext_timestamp_cmd); + install_lib_element(CFG_LOG_NODE, &logging_timezone_cmd); install_lib_element(CFG_LOG_NODE, &logging_prnt_tid_cmd); install_lib_element(CFG_LOG_NODE, &logging_prnt_cat_cmd); install_lib_element(CFG_LOG_NODE, &logging_prnt_cat_hex_cmd); diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index f76861882..ddbfb7b3d 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -47,6 +47,7 @@ logging_vty_test# list logging filter all (0|1) logging color (0|1) logging print timestamp (none|date|date-packed|ctime) + logging timezone (localtime|utc) logging print thread-id (0|1) logging print category (0|1) logging print category-hex (0|1) @@ -65,6 +66,7 @@ logging_vty_test# logging ? filter Filter log messages color Configure color-printing for log messages print Log output settings + timezone Configure time zone for log message timestamping set-log-mask Set the logmask of this logging target level Set the log level for a specified category @@ -72,6 +74,10 @@ logging_vty_test# ### Deprecated command's doc not shown logging_vty_test# logging timestamp ? % There is no matched command. +logging_vty_test# logging timezone ? + localtime Log timestamps in the system's local time + utc Log timestamps in Coordinated Universal Time (UTC) + logging_vty_test# logging level ? ... ! all aa Antropomorphic Armadillos (AA) @@ -155,6 +161,24 @@ logging_vty_test# logging print file basename ? logging_vty_test# configure terminal logging_vty_test(config)# log stderr + +logging_vty_test(config-log)# show running-config +... +log stderr +... !logging timezone +logging_vty_test(config-log)# logging timezone utc +logging_vty_test(config-log)# show running-config +... +log stderr +... !logging timezone + logging timezone utc +... !logging timezone +logging_vty_test(config-log)# logging timezone localtime +logging_vty_test(config-log)# show running-config +... +log stderr +... !logging timezone + logging_vty_test(config-log)# show running-config ... log stderr