From b59249576fb9d87008dd016cc5cfa3e06e69585e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 16 Sep 2023 17:01:08 +0100 Subject: [PATCH] [Minor] Refactor logging function to join console and file --- src/libserver/logger/logger.c | 200 +++++++++++++++++++++++++- src/libserver/logger/logger_console.c | 135 ++--------------- src/libserver/logger/logger_file.c | 120 ++-------------- src/libserver/logger/logger_private.h | 28 +++- 4 files changed, 243 insertions(+), 240 deletions(-) diff --git a/src/libserver/logger/logger.c b/src/libserver/logger/logger.c index b62048c86..9b9d302f2 100644 --- a/src/libserver/logger/logger.c +++ b/src/libserver/logger/logger.c @@ -1,11 +1,11 @@ -/*- - * Copyright 2016 Vsevolod Stakhov +/* + * Copyright 2023 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, @@ -27,6 +27,8 @@ static rspamd_logger_t *default_logger = NULL; static rspamd_logger_t *emergency_logger = NULL; static struct rspamd_log_modules *log_modules = NULL; +static const gchar lf_chr = '\n'; + guint rspamd_task_log_id = (guint) -1; RSPAMD_CONSTRUCTOR(rspamd_task_log_init) { @@ -1003,4 +1005,196 @@ rspamd_get_log_severity_string(gint level_flags) bitnum = ffs(level_flags) - 1; #endif return level_strs[bitnum]; +} + +static inline void +log_time(gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf, + size_t len) +{ + time_t sec = (time_t) now; + gsize r; + struct tm tms; + + rspamd_localtime(sec, &tms); + r = strftime(timebuf, len, "%F %H:%M:%S", &tms); + + if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) { + gchar usec_buf[16]; + + rspamd_snprintf(usec_buf, sizeof(usec_buf), "%.5f", + now - (gdouble) sec); + rspamd_snprintf(timebuf + r, len - r, + "%s", usec_buf + 1); + } +} + +gsize rspamd_log_fill_iov(struct iovec *iov, + double ts, + const gchar *module, + const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *logger) +{ + bool log_color = (logger->flags & RSPAMD_LOG_FLAG_COLOR); + bool log_severity = (logger->flags & RSPAMD_LOG_FLAG_SEVERITY); + bool log_rspamadm = (logger->flags & RSPAMD_LOG_FLAG_RSPAMADM); + bool log_systemd = (logger->flags & RSPAMD_LOG_FLAG_SYSTEMD); + + gint r; + + if (iov == NULL) { + if (log_rspamadm) { + if (logger->log_level == G_LOG_LEVEL_DEBUG) { + return 4; + } + else { + return 3; /* No time component */ + } + } + else if (log_systemd) { + return 3; + } + else { + if (log_color) { + return 5; + } + else { + return 4; + } + } + } + else { + static gchar timebuf[64], modulebuf[64]; + static gchar tmpbuf[256]; + + if (!log_systemd) { + log_time(ts, logger, timebuf, sizeof(timebuf)); + } + + if (!log_rspamadm) { + if (!log_systemd) { + if (log_color) { + if (level_flags & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE)) { + /* White */ + r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;37m"); + } + else if (level_flags & G_LOG_LEVEL_WARNING) { + /* Magenta */ + r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;32m"); + } + else if (level_flags & G_LOG_LEVEL_CRITICAL) { + /* Red */ + r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[1;31m"); + } + else { + r = 0; + } + } + else { + r = 0; + } + + if (log_severity) { + r += rspamd_snprintf(tmpbuf + r, + sizeof(tmpbuf) - r, + "%s [%s] #%P(%s) ", + timebuf, + rspamd_get_log_severity_string(level_flags), + logger->pid, + logger->process_type); + } + else { + r += rspamd_snprintf(tmpbuf + r, + sizeof(tmpbuf) - r, + "%s #%P(%s) ", + timebuf, + logger->pid, + logger->process_type); + } + } + else { + r = 0; + r += rspamd_snprintf(tmpbuf + r, + sizeof(tmpbuf) - r, + "(%s) ", + logger->process_type); + } + + int mremain, mr; + char *m; + + modulebuf[0] = '\0'; + mremain = sizeof(modulebuf); + m = modulebuf; + + if (id != NULL) { + guint slen = strlen(id); + slen = MIN(RSPAMD_LOG_ID_LEN, slen); + mr = rspamd_snprintf(m, mremain, "<%*.s>; ", slen, + id); + m += mr; + mremain -= mr; + } + if (module != NULL) { + mr = rspamd_snprintf(m, mremain, "%s; ", module); + m += mr; + mremain -= mr; + } + if (function != NULL) { + mr = rspamd_snprintf(m, mremain, "%s: ", function); + m += mr; + mremain -= mr; + } + else { + mr = rspamd_snprintf(m, mremain, ": "); + m += mr; + mremain -= mr; + } + + /* Ensure that we have a space at the end */ + if (m > modulebuf && *(m - 1) != ' ') { + *(m - 1) = ' '; + } + + /* Construct IOV for log line */ + iov[0].iov_base = tmpbuf; + iov[0].iov_len = r; + iov[1].iov_base = modulebuf; + iov[1].iov_len = m - modulebuf; + iov[2].iov_base = (void *) message; + iov[2].iov_len = mlen; + iov[3].iov_base = (void *) &lf_chr; + iov[3].iov_len = 1; + + if (log_color) { + iov[4].iov_base = "\033[0m"; + iov[4].iov_len = sizeof("\033[0m") - 1; + + return 5; + } + + return 4; + } + else { + /* Rspamadm case */ + int niov = 0; + + if (logger->log_level == G_LOG_LEVEL_DEBUG) { + iov[niov].iov_base = (void *) timebuf; + iov[niov++].iov_len = strlen(timebuf); + iov[niov].iov_base = (void *) " "; + iov[niov++].iov_len = 1; + } + + iov[niov].iov_base = (void *) message; + iov[niov++].iov_len = mlen; + iov[niov].iov_base = (void *) &lf_chr; + iov[niov++].iov_len = 1; + + return niov; + } + } } \ No newline at end of file diff --git a/src/libserver/logger/logger_console.c b/src/libserver/logger/logger_console.c index b5250f657..691566ab9 100644 --- a/src/libserver/logger/logger_console.c +++ b/src/libserver/logger/logger_console.c @@ -1,11 +1,11 @@ -/*- - * Copyright 2020 Vsevolod Stakhov +/* + * Copyright 2023 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, @@ -153,13 +153,8 @@ bool rspamd_log_console_log(const gchar *module, const gchar *id, gpointer arg) { struct rspamd_console_logger_priv *priv = (struct rspamd_console_logger_priv *) arg; - static gchar timebuf[64], modulebuf[64]; - gchar tmpbuf[256]; - gchar *m; - struct iovec iov[6]; - gulong r = 0, mr = 0; - size_t mremain; - gint fd, niov = 0; + gint fd, r; + double now; if (level_flags & G_LOG_LEVEL_CRITICAL) { fd = priv->crit_fd; @@ -184,119 +179,13 @@ bool rspamd_log_console_log(const gchar *module, const gchar *id, rspamd_file_lock(fd, FALSE); #endif - if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) { - log_time(rspamd_get_calendar_ticks(), - rspamd_log, timebuf, sizeof(timebuf)); - } - - if (priv->log_color) { - if (level_flags & (G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE)) { - /* White */ - r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;37m"); - } - else if (level_flags & G_LOG_LEVEL_WARNING) { - /* Magenta */ - r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[0;32m"); - } - else if (level_flags & G_LOG_LEVEL_CRITICAL) { - /* Red */ - r = rspamd_snprintf(tmpbuf, sizeof(tmpbuf), "\033[1;31m"); - } - } - else { - r = 0; - } - - if (priv->log_rspamadm) { - if (rspamd_log->log_level == G_LOG_LEVEL_DEBUG) { - log_time(rspamd_get_calendar_ticks(), - rspamd_log, timebuf, sizeof(timebuf)); - iov[niov].iov_base = (void *) timebuf; - iov[niov++].iov_len = strlen(timebuf); - iov[niov].iov_base = (void *) " "; - iov[niov++].iov_len = 1; - } - - iov[niov].iov_base = (void *) message; - iov[niov++].iov_len = mlen; - iov[niov].iov_base = (void *) &lf_chr; - iov[niov++].iov_len = 1; - } - else { - if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) { - if (priv->log_severity) { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "%s [%s] #%P(%s) ", - timebuf, - rspamd_get_log_severity_string(level_flags), - rspamd_log->pid, - rspamd_log->process_type); - } - else { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "%s #%P(%s) ", - timebuf, - rspamd_log->pid, - rspamd_log->process_type); - } - } - else { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "#%P(%s) ", - rspamd_log->pid, - rspamd_log->process_type); - } - - modulebuf[0] = '\0'; - mremain = sizeof(modulebuf); - m = modulebuf; - - if (id != NULL) { - guint slen = strlen(id); - slen = MIN(RSPAMD_LOG_ID_LEN, slen); - mr = rspamd_snprintf(m, mremain, "<%*.s>; ", slen, - id); - m += mr; - mremain -= mr; - } - if (module != NULL) { - mr = rspamd_snprintf(m, mremain, "%s; ", module); - m += mr; - mremain -= mr; - } - if (function != NULL) { - mr = rspamd_snprintf(m, mremain, "%s: ", function); - m += mr; - mremain -= mr; - } - else { - mr = rspamd_snprintf(m, mremain, ": "); - m += mr; - mremain -= mr; - } - - /* Ensure that we have a space at the end */ - if (m > modulebuf && *(m - 1) != ' ') { - *(m - 1) = ' '; - } - - iov[niov].iov_base = tmpbuf; - iov[niov++].iov_len = r; - iov[niov].iov_base = modulebuf; - iov[niov++].iov_len = m - modulebuf; - iov[niov].iov_base = (void *) message; - iov[niov++].iov_len = mlen; - iov[niov].iov_base = (void *) &lf_chr; - iov[niov++].iov_len = 1; - } - - if (priv->log_color) { - iov[niov].iov_base = "\033[0m"; - iov[niov++].iov_len = sizeof("\033[0m") - 1; - } + now = rspamd_get_calendar_ticks(); + gsize niov = rspamd_log_fill_iov(NULL, now, module, id, + function, level_flags, message, + mlen, rspamd_log); + struct iovec *iov = g_alloca(sizeof(struct iovec) * niov); + rspamd_log_fill_iov(iov, now, module, id, function, level_flags, message, + mlen, rspamd_log); again: r = writev(fd, iov, niov); diff --git a/src/libserver/logger/logger_file.c b/src/libserver/logger/logger_file.c index 91ae1956c..490cf0b65 100644 --- a/src/libserver/logger/logger_file.c +++ b/src/libserver/logger/logger_file.c @@ -1,11 +1,11 @@ -/*- - * Copyright 2020 Vsevolod Stakhov +/* + * Copyright 2023 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, @@ -24,8 +24,6 @@ #define FILE_LOG_QUARK g_quark_from_static_string("file_logger") -static const gchar lf_chr = '\n'; - struct rspamd_file_logger_priv { gint fd; struct { @@ -57,28 +55,6 @@ rspamd_log_calculate_cksum(const gchar *message, size_t mlen) return rspamd_cryptobox_fast_hash(message, mlen, rspamd_hash_seed()); } -static inline void -log_time(gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf, - size_t len) -{ - time_t sec = (time_t) now; - gsize r; - struct tm tms; - - rspamd_localtime(sec, &tms); - r = strftime(timebuf, len, "%F %H:%M:%S", &tms); - - if (rspamd_log->flags & RSPAMD_LOG_FLAG_USEC) { - gchar usec_buf[16]; - - rspamd_snprintf(usec_buf, sizeof(usec_buf), "%.5f", - now - (gdouble) sec); - rspamd_snprintf(timebuf + r, len - r, - "%s", usec_buf + 1); - } -} - - /* * Write a line to log file (unbuffered) */ @@ -399,15 +375,8 @@ bool rspamd_log_file_log(const gchar *module, const gchar *id, gpointer arg) { struct rspamd_file_logger_priv *priv = (struct rspamd_file_logger_priv *) arg; - static gchar timebuf[64], modulebuf[64]; - gchar tmpbuf[256]; - gchar *m; gdouble now; - struct iovec iov[6]; - gulong r = 0, mr = 0; guint64 cksum; - size_t mremain; - const gchar *cptype = NULL; gboolean got_time = FALSE; @@ -496,84 +465,13 @@ bool rspamd_log_file_log(const gchar *module, const gchar *id, now = rspamd_get_calendar_ticks(); } - /* Format time */ - if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) { - log_time(now, rspamd_log, timebuf, sizeof(timebuf)); - } - - cptype = rspamd_log->process_type; - r = 0; - - if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) { - if (priv->log_severity) { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "%s [%s] #%P(%s) ", - timebuf, - rspamd_get_log_severity_string(level_flags), - rspamd_log->pid, - cptype); - } - else { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "%s #%P(%s) ", - timebuf, - rspamd_log->pid, - cptype); - } - } - else { - r += rspamd_snprintf(tmpbuf + r, - sizeof(tmpbuf) - r, - "(%s) ", - cptype); - } - - modulebuf[0] = '\0'; - mremain = sizeof(modulebuf); - m = modulebuf; - - if (id != NULL) { - guint slen = strlen(id); - slen = MIN(RSPAMD_LOG_ID_LEN, slen); - mr = rspamd_snprintf(m, mremain, "<%*.s>; ", slen, - id); - m += mr; - mremain -= mr; - } - if (module != NULL) { - mr = rspamd_snprintf(m, mremain, "%s; ", module); - m += mr; - mremain -= mr; - } - if (function != NULL) { - mr = rspamd_snprintf(m, mremain, "%s: ", function); - m += mr; - mremain -= mr; - } - else { - mr = rspamd_snprintf(m, mremain, ": "); - m += mr; - mremain -= mr; - } - - /* Ensure that we have a space at the end */ - if (m > modulebuf && *(m - 1) != ' ') { - *(m - 1) = ' '; - } + gsize niov = rspamd_log_fill_iov(NULL, now, module, id, function, level_flags, message, + mlen, rspamd_log); + struct iovec *iov = g_alloca(sizeof(struct iovec) * niov); + rspamd_log_fill_iov(iov, now, module, id, function, level_flags, message, + mlen, rspamd_log); - /* Construct IOV for log line */ - iov[0].iov_base = tmpbuf; - iov[0].iov_len = r; - iov[1].iov_base = modulebuf; - iov[1].iov_len = m - modulebuf; - iov[2].iov_base = (void *) message; - iov[2].iov_len = mlen; - iov[3].iov_base = (void *) &lf_chr; - iov[3].iov_len = 1; - - return file_log_helper(rspamd_log, priv, iov, 4, level_flags); + return file_log_helper(rspamd_log, priv, iov, niov, level_flags); } void * diff --git a/src/libserver/logger/logger_private.h b/src/libserver/logger/logger_private.h index a5ce1cdc3..138f8df91 100644 --- a/src/libserver/logger/logger_private.h +++ b/src/libserver/logger/logger_private.h @@ -1,11 +1,11 @@ -/*- - * Copyright 2020 Vsevolod Stakhov +/* + * Copyright 2023 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, @@ -102,6 +102,28 @@ bool rspamd_log_file_log(const gchar *module, const gchar *id, gpointer arg); bool rspamd_log_file_on_fork(rspamd_logger_t *logger, struct rspamd_config *cfg, gpointer arg, GError **err); + +/** + * Fills IOV of logger (usable for file/console logging) + * Warning: this function is NOT reentrant, do not call it twice from a single moment of execution + * @param iov if NULL just returns the number of elements required in IOV array + * @param module + * @param id + * @param function + * @param level_flags + * @param message + * @param mlen + * @param rspamd_log + * @return number of iov elements being filled + */ +gsize rspamd_log_fill_iov(struct iovec *iov, + double ts, + const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log); /** * Escape log line by replacing unprintable characters to hex escapes like \xNN * @param src -- 2.39.5