diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2024-02-10 21:59:06 +0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-10 21:59:06 +0600 |
commit | ced57f74834e021342210db9015f7a29da88dd87 (patch) | |
tree | 99c32db138e2e6a88ba480b744cd87de78e497e4 | |
parent | fcc81b8d4006057f962937831e7ed021919bdde3 (diff) | |
parent | cb6478111db97d78e2a9a9b58e9fa490a11435b3 (diff) | |
download | rspamd-ced57f74834e021342210db9015f7a29da88dd87.tar.gz rspamd-ced57f74834e021342210db9015f7a29da88dd87.zip |
Merge pull request #4813 from rspamd/vstakhov-json-syslog
[Feature] Support JSON logging when in syslog mode
-rw-r--r-- | src/libserver/logger/logger_syslog.c | 155 |
1 files changed, 146 insertions, 9 deletions
diff --git a/src/libserver/logger/logger_syslog.c b/src/libserver/logger/logger_syslog.c index 3c4f7f7fd..faade1d01 100644 --- a/src/libserver/logger/logger_syslog.c +++ b/src/libserver/logger/logger_syslog.c @@ -1,11 +1,11 @@ -/*- - * Copyright 2020 Vsevolod Stakhov +/* + * Copyright 2024 Vsevolod Stakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -43,7 +43,7 @@ rspamd_log_syslog_init(rspamd_logger_t *logger, struct rspamd_config *cfg, priv = g_malloc0(sizeof(*priv)); priv->log_facility = cfg->log_facility; - openlog("rspamd", LOG_NDELAY | LOG_PID, priv->log_facility); + openlog("rspamd", LOG_CONS | LOG_NDELAY | LOG_PID, priv->log_facility); return priv; } @@ -88,11 +88,148 @@ bool rspamd_log_syslog_log(const gchar *module, const gchar *id, } } - syslog(syslog_level, "<%.*s>; %s; %s: %.*s", - RSPAMD_LOG_ID_LEN, id != NULL ? id : "", - module != NULL ? module : "", - function != NULL ? function : "", - (gint) mlen, message); + bool log_json = (rspamd_log->flags & RSPAMD_LOG_FLAG_JSON); + + /* Ensure safety as %.*s is used */ + char idbuf[RSPAMD_LOG_ID_LEN + 1]; + + if (id != NULL) { + rspamd_strlcpy(idbuf, id, RSPAMD_LOG_ID_LEN + 1); + } + else { + idbuf[0] = '\0'; + } + + if (log_json) { + long now = rspamd_get_calendar_ticks(); + if (rspamd_memcspn(message, "\"\\\r\n\b\t\v", mlen) == mlen) { + /* Fast path */ + syslog(syslog_level, "{\"ts\": %ld, " + "\"pid\": %d, " + "\"severity\": \"%s\", " + "\"worker_type\": \"%s\", " + "\"id\": \"%s\", " + "\"module\": \"%s\", " + "\"function\": \"%s\", " + "\"message\": \"%.*s\"}", + now, + (int) rspamd_log->pid, + rspamd_get_log_severity_string(level_flags), + rspamd_log->process_type, + idbuf, + module != NULL ? module : "", + function != NULL ? function : "", + (gint) mlen, message); + } + else { + /* Escaped version */ + /* We need to do JSON escaping of the quotes */ + const char *p, *end = message + mlen; + long escaped_len; + + for (p = message, escaped_len = 0; p < end; p++, escaped_len++) { + switch (*p) { + case '\v': + case '\0': + escaped_len += 5; + break; + case '\\': + case '"': + case '\n': + case '\r': + case '\b': + case '\t': + escaped_len++; + break; + default: + break; + } + } + + + char *dst = g_malloc(escaped_len + 1); + char *d; + + for (p = message, d = dst; p < end; p++, d++) { + switch (*p) { + case '\n': + *d++ = '\\'; + *d = 'n'; + break; + case '\r': + *d++ = '\\'; + *d = 'r'; + break; + case '\b': + *d++ = '\\'; + *d = 'b'; + break; + case '\t': + *d++ = '\\'; + *d = 't'; + break; + case '\f': + *d++ = '\\'; + *d = 'f'; + break; + case '\0': + *d++ = '\\'; + *d++ = 'u'; + *d++ = '0'; + *d++ = '0'; + *d++ = '0'; + *d = '0'; + break; + case '\v': + *d++ = '\\'; + *d++ = 'u'; + *d++ = '0'; + *d++ = '0'; + *d++ = '0'; + *d = 'B'; + break; + case '\\': + *d++ = '\\'; + *d = '\\'; + break; + case '"': + *d++ = '\\'; + *d = '"'; + break; + default: + *d = *p; + break; + } + } + + *d = '\0'; + + syslog(syslog_level, "{\"ts\": %ld, " + "\"pid\": %d, " + "\"severity\": \"%s\", " + "\"worker_type\": \"%s\", " + "\"id\": \"%s\", " + "\"module\": \"%s\", " + "\"function\": \"%s\", " + "\"message\": \"%s\"}", + now, + (int) rspamd_log->pid, + rspamd_get_log_severity_string(level_flags), + rspamd_log->process_type, + idbuf, + module != NULL ? module : "", + function != NULL ? function : "", + dst); + g_free(dst); + } + } + else { + syslog(syslog_level, "<%s>; %s; %s: %.*s", + idbuf, + module != NULL ? module : "", + function != NULL ? function : "", + (gint) mlen, message); + } return true; } |