This adds a configurable option 'FEATURE_SYSLOGD_ISO8601FMT' enabling a command line option ('-I', with semantics similar to 'date') that directs syslogd to log timestamps in ISO 8601 format.
Precision in seconds (the default), milliseconds, and microseconds are supported. Without the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ss±hhmm (seconds) YYYY-MM-DDThh:mm:ss.sss±hhmm (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuu±hhmm (microseconds) with the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option, outputs are of the form: YYYY-MM-DDThh:mm:ssZ (seconds) YYYY-MM-DDThh:mm:ss.sssZ (milliseconds) YYYY-MM-DDThh:mm:ss.uuuuuuZ (microseconds) Signed-off-by: Grant Erickson <gerick...@nuovations.com> --- sysklogd/syslogd.c | 157 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 39 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 287b70e45d19..f05fac6d8a92 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -44,6 +44,15 @@ //config: syslogd to log timestamps in Coordinated Universal Time //config: (UTC) rather than in local time. //config: +//config:config FEATURE_SYSLOGD_ISO8601FMT +//config: bool "Log timestamps in ISO 8601 format" +//config: default n +//config: depends on SYSLOGD +//config: help +//config: This enables a command line option ('-I') that directs +//config: syslogd to log timestamps in ISO 8601 format with second, +//config: millisecond, or microsecond resolution. +//config: //config:config FEATURE_REMOTE_LOG //config: bool "Remote Log support" //config: default y @@ -159,6 +168,10 @@ //usage: IF_FEATURE_SYSLOGD_UTC( //usage: "\n -u Log timestamps in Coordinated Universal Time (UTC)" //usage: ) +//usage: IF_FEATURE_SYSLOGD_ISO8601FMT( +//usage: "\n -I[SPEC] Log timestamps in ISO 8601 format" +//usage: "\n SPEC=seconds (default), ms, or us" +//usage: ) //usage: "\n -t Strip client-generated timestamps" //usage: IF_FEATURE_SYSLOGD_DUP( //usage: "\n -D Drop duplicates" @@ -272,6 +285,9 @@ IF_FEATURE_SYSLOGD_CFG( \ IF_FEATURE_KMSG_SYSLOG( \ int kmsgfd; \ int primask; \ +) \ +IF_FEATURE_SYSLOGD_ISO8601FMT( \ + int iso8601fmt; \ ) struct init_globals { @@ -298,7 +314,7 @@ struct globals { /* ...then sprintf into printbuf, adding timestamp (15 or 19 chars), * host (64), fac.prio (20) to the message */ /* (growth by: 15 + 64 + 20 + delims = ~110) */ - char printbuf[MAX_READ*2 + 128]; + char printbuf[MAX_READ*2 + 144]; }; static const struct init_globals init_data = { @@ -337,15 +353,16 @@ enum { OPTBIT_loglevel, // -l OPTBIT_small, // -S OPTBIT_timestamp, // -t - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize ,) // -s - IF_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt ,) // -b - IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R - IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L - IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C - IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D - IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f - IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K - IF_FEATURE_SYSLOGD_UTC( OPTBIT_utc ,) // -u + IF_FEATURE_ROTATE_LOGFILE( OPTBIT_filesize ,) // -s + IF_FEATURE_ROTATE_LOGFILE( OPTBIT_rotatecnt ,) // -b + IF_FEATURE_REMOTE_LOG( OPTBIT_remotelog ,) // -R + IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L + IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C + IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D + IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f + IF_FEATURE_KMSG_SYSLOG( OPTBIT_kmsg ,) // -K + IF_FEATURE_SYSLOGD_UTC( OPTBIT_utc ,) // -u + IF_FEATURE_SYSLOGD_ISO8601FMT(OPTBIT_iso8601fmt ,) // -I OPT_mark = 1 << OPTBIT_mark , OPT_nofork = 1 << OPTBIT_nofork , @@ -353,38 +370,41 @@ enum { OPT_loglevel = 1 << OPTBIT_loglevel, OPT_small = 1 << OPTBIT_small , OPT_timestamp = 1 << OPTBIT_timestamp, - OPT_filesize = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize )) + 0, - OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt )) + 0, - OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, - OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, - OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, - OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, - OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, - OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, - OPT_utc = IF_FEATURE_SYSLOGD_UTC( (1 << OPTBIT_utc )) + 0, + OPT_filesize = IF_FEATURE_ROTATE_LOGFILE( (1 << OPTBIT_filesize )) + 0, + OPT_rotatecnt = IF_FEATURE_ROTATE_LOGFILE( (1 << OPTBIT_rotatecnt )) + 0, + OPT_remotelog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_remotelog )) + 0, + OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, + OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, + OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, + OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, + OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, + OPT_utc = IF_FEATURE_SYSLOGD_UTC( (1 << OPTBIT_utc )) + 0, + OPT_iso8601fmt = IF_FEATURE_SYSLOGD_ISO8601FMT((1 << OPTBIT_iso8601fmt )) + 0, }; #define OPTION_STR "m:nO:l:St" \ - IF_FEATURE_ROTATE_LOGFILE("s:" ) \ - IF_FEATURE_ROTATE_LOGFILE("b:" ) \ - IF_FEATURE_REMOTE_LOG( "R:*") \ - IF_FEATURE_REMOTE_LOG( "L" ) \ - IF_FEATURE_IPC_SYSLOG( "C::") \ - IF_FEATURE_SYSLOGD_DUP( "D" ) \ - IF_FEATURE_SYSLOGD_CFG( "f:" ) \ - IF_FEATURE_KMSG_SYSLOG( "K" ) \ - IF_FEATURE_SYSLOGD_UTC( "u" ) + IF_FEATURE_ROTATE_LOGFILE( "s:" ) \ + IF_FEATURE_ROTATE_LOGFILE( "b:" ) \ + IF_FEATURE_REMOTE_LOG( "R:*") \ + IF_FEATURE_REMOTE_LOG( "L" ) \ + IF_FEATURE_IPC_SYSLOG( "C::") \ + IF_FEATURE_SYSLOGD_DUP( "D" ) \ + IF_FEATURE_SYSLOGD_CFG( "f:" ) \ + IF_FEATURE_KMSG_SYSLOG( "K" ) \ + IF_FEATURE_SYSLOGD_UTC( "u" ) \ + IF_FEATURE_SYSLOGD_ISO8601FMT("I::") #define OPTION_DECL *opt_m, *opt_l \ - IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ - IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ - IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \ - IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL) + IF_FEATURE_ROTATE_LOGFILE( ,*opt_s) \ + IF_FEATURE_ROTATE_LOGFILE( ,*opt_b) \ + IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \ + IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL) \ + IF_FEATURE_SYSLOGD_ISO8601FMT(,*opt_I = NULL) #define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \ - IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \ - IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \ - IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ - IF_FEATURE_IPC_SYSLOG( ,&opt_C) \ - IF_FEATURE_SYSLOGD_CFG( ,&opt_f) - + IF_FEATURE_ROTATE_LOGFILE( ,&opt_s) \ + IF_FEATURE_ROTATE_LOGFILE( ,&opt_b) \ + IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ + IF_FEATURE_IPC_SYSLOG( ,&opt_C) \ + IF_FEATURE_SYSLOGD_CFG( ,&opt_f) \ + IF_FEATURE_SYSLOGD_ISO8601FMT(,&opt_I) #if ENABLE_FEATURE_SYSLOGD_CFG static const CODE* find_by_name(char *name, const CODE* c_set) @@ -873,6 +893,21 @@ static struct tm * generate_time(struct timeval *tvp, struct tm *tmp) return tm; } +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT +static void append_zone_string(char *timestamp, size_t max, const struct tm *tmp) +{ + if (timestamp && tmp) { +#if ENABLE_FEATURE_SYSLOGD_UTC + if (option_mask32 & OPT_utc) + snprintf(timestamp, max, "%c", 'Z'); + else + strftime(timestamp, max, "%z", tmp); +#else + strftime(timestamp, max, "%z", tmp); +#endif + } +} +#endif /* len parameter is used only for "is there a timestamp?" check. * NB: some callers cheat and supply len==0 when they know @@ -887,11 +922,15 @@ static void timestamp_and_log(int pri, char *msg, int len) msg[15] == ' '); const char *format="%h %e %T"; char *timestamp = NULL; - char timestampbuf[20]; + char timestampbuf[32]; /* MMM DD hh:mm:ss default */ /* 0123456789012345 - 16 */ /* MMM DD hh:mm:ss.mmm ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS */ /* 01234567890123456789 - 20 */ + /* YYYY-MM-DDThh:mm:ss.uuuuuuZ OPT_utc & OPT_iso8601fmt */ + /* 0123456789012345678901234567 - 28 */ + /* YYYY-MM-DDThh:mm:ss.uuuuuu+hhmm OPT_iso8601fmt */ + /* 01234567890123456789012345678901 - 32 */ struct timeval tvnow; #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC struct tm parsed; @@ -941,6 +980,33 @@ static void timestamp_and_log(int pri, char *msg, int len) tmp = generate_time(&tvnow, &tmnow); } +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT + if (tmp && !timestamp && G.iso8601fmt >= 0) { + format = "%FT%T"; + /* -I[SPEC]: 0:seconds 1:ms 2:us */ + n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); + + if (G.iso8601fmt == 1 || G.iso8601fmt == 2) { + const char *iso8601fracfmt; + unsigned long divisor; + + if (G.iso8601fmt == 1) { + iso8601fracfmt = ".%03lu"; + divisor = 1000u; + } else { + iso8601fracfmt = ".%06lu"; + divisor = 1u; + } + + n += snprintf(timestampbuf + n, sizeof(timestampbuf) - n, iso8601fracfmt, tvnow.tv_usec / divisor); + } + + append_zone_string(timestampbuf + n, sizeof(timestampbuf) - n, tmp); + + timestamp = timestampbuf; + } +#endif /* ENABLE_FEATURE_SYSLOGD_ISO8601FMT */ + #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS if (tmp && !timestamp) { n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp); @@ -1138,6 +1204,19 @@ static int NOINLINE syslogd_init(char **argv) #if ENABLE_FEATURE_IPC_SYSLOG if (opt_C) // -Cn G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; +#endif +#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT + G.iso8601fmt = -1; + if (opts & OPT_iso8601fmt) { + G.iso8601fmt = 0; /* default is seconds */ + if (opt_I) { + static const char iso8601fmts[] ALIGN1 = + "seconds\0""ms\0""us\0"; + G.iso8601fmt = index_in_substrings(iso8601fmts, opt_I); + if (G.iso8601fmt < 0) + bb_show_usage(); + } + } #endif /* If they have not specified remote logging, then log locally */ if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R -- 2.45.0 _______________________________________________ busybox mailing list busybox@busybox.net https://lists.busybox.net/mailman/listinfo/busybox