aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2024-02-10 21:59:06 +0600
committerGitHub <noreply@github.com>2024-02-10 21:59:06 +0600
commitced57f74834e021342210db9015f7a29da88dd87 (patch)
tree99c32db138e2e6a88ba480b744cd87de78e497e4
parentfcc81b8d4006057f962937831e7ed021919bdde3 (diff)
parentcb6478111db97d78e2a9a9b58e9fa490a11435b3 (diff)
downloadrspamd-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.c155
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;
}