Core: add RFC 5424 syslog message format.

When the "rfc=rfc5424" syslog parameter is used, format syslog
messages according to RFC 5424 instead of RFC 3164.

The RFC 5424 HEADER contains VERSION (always "1"), an ISO 8601
TIMESTAMP with millisecond precision and UTC offset (e.g.
"2003-10-11T22:14:15.003+05:30"), HOSTNAME, APP-NAME, PROCID
(nginx process PID), and nil values for MSGID and STRUCTURED-DATA.

Add cached_syslog_rfc5424_time to ngx_times.c populated alongside
the existing cached_syslog_time in both ngx_time_update() and
ngx_time_sigsafe_update().  The signal-safe path has no millisecond
counter available and emits ".000" for the sub-second field.

Expand NGX_SYSLOG_MAX_STR to accommodate the larger RFC 5424 header.
This commit is contained in:
Vadim Zhestikov 2026-03-25 10:25:43 -07:00
parent b3819741a3
commit 13cc07acb8
3 changed files with 56 additions and 6 deletions

View file

@ -10,9 +10,11 @@
#define NGX_SYSLOG_MAX_STR \
NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1 \
NGX_MAX_ERROR_STR + sizeof("<255>1 ") - 1 \
+ sizeof("1970-09-28T12:00:00.000+06:00") - 1 + 1 /* space */ \
+ (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */ \
+ 32 /* tag */ + 2 /* colon, space */
+ 48 /* APP-NAME/TAG */ + 1 /* space */ \
+ NGX_INT64_LEN /* PROCID */ + sizeof(" - - ") - 1
static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
@ -40,6 +42,8 @@ static ngx_event_t ngx_syslog_dummy_event;
char *
ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
{
u_char ch;
ngx_uint_t j;
ngx_pool_cleanup_t *cln;
peer->facility = NGX_CONF_UNSET_UINT;
@ -50,8 +54,6 @@ ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
}
if (peer->tag.data != NULL) {
ngx_uint_t j;
u_char ch;
if (peer->rfc5424) {
@ -304,6 +306,27 @@ ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
pri = peer->facility * 8 + peer->severity;
if (peer->rfc5424) {
/*
* RFC 5424 HEADER: VERSION SP TIMESTAMP SP HOSTNAME SP
* APP-NAME SP PROCID SP MSGID SP STRUCTURED-DATA SP
*
* PROCID is set to the nginx process PID. MSGID and
* STRUCTURED-DATA are set to the nil value "-".
*/
if (peer->nohostname) {
return ngx_sprintf(buf, "<%ui>1 %V - %V %P - - ",
pri, &ngx_cached_syslog_rfc5424_time,
&peer->tag, ngx_pid);
}
return ngx_sprintf(buf, "<%ui>1 %V %V %V %P - - ",
pri, &ngx_cached_syslog_rfc5424_time,
peer->hostname, &peer->tag, ngx_pid);
}
if (peer->nohostname) {
return ngx_sprintf(buf, "<%ui>%V %V: ", pri, &ngx_cached_syslog_time,
&peer->tag);

View file

@ -33,6 +33,7 @@ volatile ngx_str_t ngx_cached_http_time;
volatile ngx_str_t ngx_cached_http_log_time;
volatile ngx_str_t ngx_cached_http_log_iso8601;
volatile ngx_str_t ngx_cached_syslog_time;
volatile ngx_str_t ngx_cached_syslog_rfc5424_time;
#if !(NGX_WIN32)
@ -56,6 +57,8 @@ static u_char cached_http_log_iso8601[NGX_TIME_SLOTS]
[sizeof("1970-09-28T12:00:00+06:00")];
static u_char cached_syslog_time[NGX_TIME_SLOTS]
[sizeof("Sep 28 12:00:00")];
static u_char cached_syslog_rfc5424_time[NGX_TIME_SLOTS]
[sizeof("1970-09-28T12:00:00.000+06:00")];
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
@ -70,6 +73,8 @@ ngx_time_init(void)
ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1;
ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1;
ngx_cached_syslog_time.len = sizeof("Sep 28 12:00:00") - 1;
ngx_cached_syslog_rfc5424_time.len =
sizeof("1970-09-28T12:00:00.000+06:00") - 1;
ngx_cached_time = &cached_time[0];
@ -80,7 +85,7 @@ ngx_time_init(void)
void
ngx_time_update(void)
{
u_char *p0, *p1, *p2, *p3, *p4;
u_char *p0, *p1, *p2, *p3, *p4, *p5;
ngx_tm_t tm, gmt;
time_t sec;
ngx_uint_t msec;
@ -179,6 +184,15 @@ ngx_time_update(void)
months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday,
tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
p5 = &cached_syslog_rfc5424_time[slot][0];
(void) ngx_sprintf(p5, "%4d-%02d-%02dT%02d:%02d:%02d.%03ui%c%02i:%02i",
tm.ngx_tm_year, tm.ngx_tm_mon,
tm.ngx_tm_mday, tm.ngx_tm_hour,
tm.ngx_tm_min, tm.ngx_tm_sec, msec,
tp->gmtoff < 0 ? '-' : '+',
ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));
ngx_memory_barrier();
ngx_cached_time = tp;
@ -187,6 +201,7 @@ ngx_time_update(void)
ngx_cached_http_log_time.data = p2;
ngx_cached_http_log_iso8601.data = p3;
ngx_cached_syslog_time.data = p4;
ngx_cached_syslog_rfc5424_time.data = p5;
ngx_unlock(&ngx_time_lock);
}
@ -214,7 +229,7 @@ ngx_monotonic_time(time_t sec, ngx_uint_t msec)
void
ngx_time_sigsafe_update(void)
{
u_char *p, *p2;
u_char *p, *p2, *p3;
ngx_tm_t tm;
time_t sec;
ngx_time_t *tp;
@ -260,10 +275,21 @@ ngx_time_sigsafe_update(void)
months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday,
tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
p3 = &cached_syslog_rfc5424_time[slot][0];
(void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d.000%c%02i:%02i",
tm.ngx_tm_year, tm.ngx_tm_mon,
tm.ngx_tm_mday, tm.ngx_tm_hour,
tm.ngx_tm_min, tm.ngx_tm_sec,
cached_gmtoff < 0 ? '-' : '+',
ngx_abs(cached_gmtoff / 60),
ngx_abs(cached_gmtoff % 60));
ngx_memory_barrier();
ngx_cached_err_log_time.data = p;
ngx_cached_syslog_time.data = p2;
ngx_cached_syslog_rfc5424_time.data = p3;
ngx_unlock(&ngx_time_lock);
}

View file

@ -41,6 +41,7 @@ extern volatile ngx_str_t ngx_cached_http_time;
extern volatile ngx_str_t ngx_cached_http_log_time;
extern volatile ngx_str_t ngx_cached_http_log_iso8601;
extern volatile ngx_str_t ngx_cached_syslog_time;
extern volatile ngx_str_t ngx_cached_syslog_rfc5424_time;
/*
* milliseconds elapsed since some unspecified point in the past