diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-02-10 17:18:40 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2020-02-10 21:12:13 +0000 |
commit | 4de514b49c2891c4e628c3aae4428641f8785cb3 (patch) | |
tree | 7ac7650bb833b9565000ca0c319933395af2b6f3 /src | |
parent | adef14349a2c7c2b762ac2bbae6f52e93e4aa628 (diff) | |
download | rspamd-4de514b49c2891c4e628c3aae4428641f8785cb3.tar.gz rspamd-4de514b49c2891c4e628c3aae4428641f8785cb3.zip |
[Rework] Add console and syslog modules
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/cfg_file.h | 1 | ||||
-rw-r--r-- | src/libutil/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/libutil/logger.c | 39 | ||||
-rw-r--r-- | src/libutil/logger.h | 31 | ||||
-rw-r--r-- | src/libutil/logger_console.c | 290 | ||||
-rw-r--r-- | src/libutil/logger_file.c | 83 | ||||
-rw-r--r-- | src/libutil/logger_private.h | 52 | ||||
-rw-r--r-- | src/libutil/logger_syslog.c | 142 |
8 files changed, 538 insertions, 102 deletions
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h index 447ee4ed3..cf1532692 100644 --- a/src/libserver/cfg_file.h +++ b/src/libserver/cfg_file.h @@ -76,7 +76,6 @@ enum rspamd_log_cfg_flags { RSPAMD_LOG_FLAG_USEC = (1 << 3), RSPAMD_LOG_FLAG_RSPAMADM = (1 << 4), RSPAMD_LOG_FLAG_ENFORCED = (1 << 5), - RSPAMD_LOG_FLAG_TTY = (1 << 6), }; struct rspamd_worker_log_pipe { diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt index 6cd5df8a0..553d96e47 100644 --- a/src/libutil/CMakeLists.txt +++ b/src/libutil/CMakeLists.txt @@ -12,6 +12,8 @@ SET(LIBRSPAMDUTILSRC ${CMAKE_CURRENT_SOURCE_DIR}/http_context.c ${CMAKE_CURRENT_SOURCE_DIR}/logger.c ${CMAKE_CURRENT_SOURCE_DIR}/logger_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/logger_syslog.c + ${CMAKE_CURRENT_SOURCE_DIR}/logger_console.c ${CMAKE_CURRENT_SOURCE_DIR}/map.c ${CMAKE_CURRENT_SOURCE_DIR}/map_helpers.c ${CMAKE_CURRENT_SOURCE_DIR}/mem_pool.c diff --git a/src/libutil/logger.c b/src/libutil/logger.c index 1f586b111..f2ab3f611 100644 --- a/src/libutil/logger.c +++ b/src/libutil/logger.c @@ -22,10 +22,6 @@ #include "unix-std.h" #include "logger_private.h" -#ifdef HAVE_SYSLOG_H -#include <syslog.h> -#endif - static rspamd_logger_t *default_logger = NULL; static struct rspamd_log_modules *log_modules = NULL; @@ -278,7 +274,6 @@ rspamd_set_logger (struct rspamd_config *cfg, } logger->log_type = cfg->log_type; - logger->log_facility = cfg->log_facility; if (!(logger->flags & RSPAMD_LOG_FLAG_ENFORCED)) { logger->log_level = cfg->log_level; @@ -346,39 +341,7 @@ void rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *rspamd_log) { rspamd_log->pid = getpid (); - rspamd_log->process_type = ptype; - - /* We also need to clear all messages pending */ - if (rspamd_log->repeats > 0) { - rspamd_log->repeats = 0; - if (rspamd_log->saved_message) { - g_free (rspamd_log->saved_message); - g_free (rspamd_log->saved_function); - g_free (rspamd_log->saved_module); - g_free (rspamd_log->saved_id); - rspamd_log->saved_message = NULL; - rspamd_log->saved_function = NULL; - rspamd_log->saved_module = NULL; - rspamd_log->saved_id = NULL; - } - } -} - -/** - * Flush logging buffer - */ -void -rspamd_log_flush (rspamd_logger_t *rspamd_log) -{ - if (rspamd_log->is_buffered && - (rspamd_log->type == RSPAMD_LOG_CONSOLE || - rspamd_log->type == RSPAMD_LOG_FILE)) { - direct_write_log_line (rspamd_log, - rspamd_log->io_buf.buf, - rspamd_log->io_buf.used, - FALSE, rspamd_log->log_level); - rspamd_log->io_buf.used = 0; - } + rspamd_log->process_type = g_quark_to_string (ptype); } static inline gboolean diff --git a/src/libutil/logger.h b/src/libutil/logger.h index 3cec58249..e98905f76 100644 --- a/src/libutil/logger.h +++ b/src/libutil/logger.h @@ -22,7 +22,7 @@ enum rspamd_log_flags { }; typedef struct rspamd_logger_s rspamd_logger_t; -typedef void (*rspamd_log_func_t) (const gchar *module, const gchar *id, +typedef bool (*rspamd_log_func_t) (const gchar *module, const gchar *id, const gchar *function, gint level_flags, const gchar *message, @@ -62,22 +62,22 @@ void rspamd_set_logger (struct rspamd_config *cfg, /** * Open log file or initialize other structures */ -gint rspamd_log_open (rspamd_logger_t *logger); +bool rspamd_log_open (rspamd_logger_t *logger); /** * Close log file or destroy other structures */ -void rspamd_log_close (rspamd_logger_t *logger, gboolean termination); +bool rspamd_log_close (rspamd_logger_t *logger, gboolean termination); /** * Close and open log again */ -gint rspamd_log_reopen (rspamd_logger_t *logger); +bool rspamd_log_reopen (rspamd_logger_t *logger); /** * Open log file or initialize other structures for privileged processes */ -gint rspamd_log_open_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); +bool rspamd_log_open_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); /** * Close log file or destroy other structures for privileged processes @@ -87,7 +87,7 @@ void rspamd_log_close_priv (rspamd_logger_t *logger, gboolean termination, uid_t /** * Close and open log again for privileged processes */ -gint rspamd_log_reopen_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); +bool rspamd_log_reopen_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); /** * Set log pid @@ -95,11 +95,6 @@ gint rspamd_log_reopen_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); void rspamd_log_update_pid (GQuark ptype, rspamd_logger_t *logger); /** - * Flush log buffer for some types of logging - */ -void rspamd_log_flush (rspamd_logger_t *logger); - -/** * Log function that is compatible for glib messages */ void rspamd_glib_log_function (const gchar *log_domain, @@ -113,12 +108,12 @@ void rspamd_glib_printerr_function (const gchar *message); /** * Function with variable number of arguments support */ -void rspamd_common_log_function (rspamd_logger_t *logger, +bool rspamd_common_log_function (rspamd_logger_t *logger, gint level_flags, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, ...); -void rspamd_common_logv (rspamd_logger_t *logger, gint level_flags, +bool rspamd_common_logv (rspamd_logger_t *logger, gint level_flags, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, va_list args); @@ -149,16 +144,16 @@ void rspamd_logger_configure_modules (GHashTable *mods_enabled); /** * Conditional debug function */ -void rspamd_conditional_debug (rspamd_logger_t *logger, +bool rspamd_conditional_debug (rspamd_logger_t *logger, rspamd_inet_addr_t *addr, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, ...); -void rspamd_conditional_debug_fast (rspamd_logger_t *logger, +bool rspamd_conditional_debug_fast (rspamd_logger_t *logger, rspamd_inet_addr_t *addr, guint mod_id, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, ...); -void rspamd_conditional_debug_fast_num_id (rspamd_logger_t *logger, +bool rspamd_conditional_debug_fast_num_id (rspamd_logger_t *logger, rspamd_inet_addr_t *addr, guint mod_id, const gchar *module, guint64 id, @@ -167,7 +162,7 @@ void rspamd_conditional_debug_fast_num_id (rspamd_logger_t *logger, /** * Function with variable number of arguments support that uses static default logger */ -void rspamd_default_log_function (gint level_flags, +bool rspamd_default_log_function (gint level_flags, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, @@ -180,7 +175,7 @@ void rspamd_default_log_function (gint level_flags, * @param fmt * @param args */ -void rspamd_default_logv (gint level_flags, +bool rspamd_default_logv (gint level_flags, const gchar *module, const gchar *id, const gchar *function, const gchar *fmt, diff --git a/src/libutil/logger_console.c b/src/libutil/logger_console.c new file mode 100644 index 000000000..c410bdd79 --- /dev/null +++ b/src/libutil/logger_console.c @@ -0,0 +1,290 @@ +/*- + * Copyright 2020 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" +#include "logger.h" +#include "libserver/cfg_file.h" +#include "libcryptobox/cryptobox.h" +#include "unix-std.h" + +#include "logger_private.h" + +#define CONSOLE_LOG_QUARK g_quark_from_static_string ("console_logger") + +static const gchar lf_chr = '\n'; +struct rspamd_console_logger_priv { + gint fd; + gint crit_fd; + gboolean log_color; + gboolean log_rspamadm; + gboolean log_tty; +}; + +/* Copy & paste :( */ +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); + } +} + +void * +rspamd_log_console_init (rspamd_logger_t *logger, struct rspamd_config *cfg, + uid_t uid, gid_t gid, GError **err) +{ + struct rspamd_console_logger_priv *priv; + + priv = g_malloc0 (sizeof (*priv)); + priv->log_color = (logger->flags & RSPAMD_LOG_FLAG_COLOR); + priv->log_rspamadm (logger->flags & RSPAMD_LOG_FLAG_RSPAMADM); + + if (priv->log_rspamadm) { + priv->fd = dup (STDOUT_FILENO); + priv->crit_fd = dup (STDERR_FILENO); + } + else { + priv->fd = dup (STDERR_FILENO); + priv->crit_fd = priv->fd; + } + + if (priv->fd == -1) { + g_set_error (err, CONSOLE_LOG_QUARK, errno, + "open_log: cannot dup console fd: %s, %s\n", + strerror (errno)); + rspamd_log_console_dtor (priv); + + return NULL; + } + + if (isatty (priv->fd)) { + priv->log_tty = true; + } + + return priv; +} + +void * +rspamd_log_console_reload (rspamd_logger_t *logger, struct rspamd_config *cfg, + gpointer arg, uid_t uid, gid_t gid, GError **err) +{ + struct rspamd_console_logger_priv *npriv; + + npriv = rspamd_log_console_init (logger, cfg, uid, gid, err); + + if (npriv) { + /* Close old */ + rspamd_log_console_dtor (logger, arg); + } + + return npriv; +} + +void +rspamd_log_console_dtor (rspamd_logger_t *logger, gpointer arg) +{ + struct rspamd_console_logger_priv *priv = (struct rspamd_console_logger_priv *)arg; + + if (priv->fd != -1) { + if (priv->fd != priv->crit_fd) { + /* Two different FD case */ + if (close (priv->crit_fd) == -1) { + rspamd_fprintf (stderr, "cannot close log crit_fd %d: %s\n", + priv->crit_fd, strerror (errno)); + } + } + + if (close (priv->fd) == -1) { + rspamd_fprintf (stderr, "cannot close log fd %d: %s\n", + priv->fd, strerror (errno)); + } + + /* Avoid the next if to be executed as crit_fd is equal to fd */ + priv->crit_fd = -1; + } + + if (priv->crit_fd != -1) { + if (close (priv->crit_fd) == -1) { + rspamd_fprintf (stderr, "cannot close log crit_fd %d: %s\n", + priv->crit_fd, strerror (errno)); + } + } + + g_free (priv); +} + +bool +rspamd_log_console_log (const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log, + 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; + + if (level_flags & G_LOG_LEVEL_CRITICAL) { + fd = priv->crit_fd; + } + else { + fd = priv->fd; + } + +#ifndef DISABLE_PTHREAD_MUTEX + if (rspamd_log->mtx) { + rspamd_mempool_lock_mutex (rspamd_log->mtx); + } + else { + rspamd_file_lock (fd, FALSE); + } +#else + rspamd_file_lock (fd, FALSE); +#endif + + 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 { + r += rspamd_snprintf (tmpbuf + r, + sizeof (tmpbuf) - r, + "%s #%P(%s) ", + timebuf, + rspamd_log->pid, + rspamd_log->process_type); + + modulebuf[0] = '\0'; + mremain = sizeof (modulebuf); + m = modulebuf; + + if (id != NULL) { + guint slen = strlen (id); + slen = MIN (LOG_ID, 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; + } + + 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; + } + +again: + r = writev (fd, iov, niov); + + if (r == -1) { + if (errno == EAGAIN || errno == EINTR) { + goto again; + } + + if (rspamd_log->mtx) { + rspamd_mempool_unlock_mutex (rspamd_log->mtx); + } + else { + rspamd_file_unlock (fd, FALSE); + } + + return false; + } + + if (rspamd_log->mtx) { + rspamd_mempool_unlock_mutex (rspamd_log->mtx); + } + else { + rspamd_file_unlock (fd, FALSE); + } + + return true; +}
\ No newline at end of file diff --git a/src/libutil/logger_file.c b/src/libutil/logger_file.c index b2e01cf81..b4bb6208b 100644 --- a/src/libutil/logger_file.c +++ b/src/libutil/logger_file.c @@ -45,7 +45,6 @@ struct rspamd_file_logger_priv { gchar *saved_module; gchar *saved_id; guint saved_loglevel; - guint64 log_cnt[4]; }; /** @@ -82,7 +81,7 @@ log_time (gdouble now, rspamd_logger_t *rspamd_log, gchar *timebuf, /* * Write a line to log file (unbuffered) */ -static void +static bool direct_write_log_line (rspamd_logger_t *rspamd_log, struct rspamd_file_logger_priv *priv, void *data, @@ -114,7 +113,7 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, tlen = count; } - if (tlen > PIPE_BUF || rspamd_log->flags & RSPAMD_LOG_FLAG_TTY) { + if (tlen > PIPE_BUF) { locked = TRUE; #ifndef DISABLE_PTHREAD_MUTEX @@ -155,14 +154,9 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, /* We cannot write message to file, so we need to detect error and make decision */ if (errno == EINTR) { /* Try again */ - direct_write_log_line (rspamd_log, priv, data, count, is_iov, level_flags); - return; + return direct_write_log_line (rspamd_log, priv, data, count, is_iov, level_flags); } - r = rspamd_snprintf (errmsg, - sizeof (errmsg), - "direct_write_log_line: cannot write log line: %s", - strerror (errno)); if (errno == EFAULT || errno == EINVAL || errno == EFBIG || errno == ENOSPC) { /* Rare case */ @@ -173,10 +167,14 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, /* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */ rspamd_log->enabled = FALSE; } + + return false; } else if (priv->throttling) { priv->throttling = FALSE; } + + return true; } /** @@ -198,10 +196,24 @@ fill_buffer (rspamd_logger_t *rspamd_log, } +static void +rspamd_log_flush (rspamd_logger_t *rspamd_log, struct rspamd_file_logger_priv *priv) +{ + if (priv->is_buffered) { + direct_write_log_line (rspamd_log, + priv, + priv->io_buf.buf, + priv->io_buf.used, + FALSE, + rspamd_log->log_level); + priv->io_buf.used = 0; + } +} + /* * Write message to buffer or to file (using direct_write_log_line function) */ -static void +static bool file_log_helper (rspamd_logger_t *rspamd_log, struct rspamd_file_logger_priv *priv, const struct iovec *iov, @@ -213,7 +225,7 @@ file_log_helper (rspamd_logger_t *rspamd_log, if (!priv->is_buffered) { /* Write string directly */ - direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt, + return direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt, TRUE, level_flags); } else { @@ -224,13 +236,13 @@ file_log_helper (rspamd_logger_t *rspamd_log, /* Fill buffer */ if (priv->io_buf.size < len) { /* Buffer is too small to hold this string, so write it directly */ - rspamd_log_flush (rspamd_log); - direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt, + rspamd_log_flush (rspamd_log, priv); + return direct_write_log_line (rspamd_log, priv, (void *) iov, iovcnt, TRUE, level_flags); } else if (priv->io_buf.used + len >= priv->io_buf.size) { /* Buffer is full, try to write it directly */ - rspamd_log_flush (rspamd_log); + rspamd_log_flush (rspamd_log, priv); fill_buffer (rspamd_log, priv, iov, iovcnt); } else { @@ -238,6 +250,8 @@ file_log_helper (rspamd_logger_t *rspamd_log, fill_buffer (rspamd_log, priv, iov, iovcnt); } } + + return true; } static void @@ -283,6 +297,7 @@ rspamd_log_reset_repeated (rspamd_logger_t *rspamd_log, r, rspamd_log, priv); + rspamd_log_flush (rspamd_log, priv); } } } @@ -365,6 +380,7 @@ rspamd_log_file_dtor (rspamd_logger_t *logger, gpointer arg) struct rspamd_file_logger_priv *priv = (struct rspamd_file_logger_priv *)arg; rspamd_log_reset_repeated (logger, priv); + rspamd_log_flush (logger, priv); if (priv->fd != -1) { if (close (priv->fd) == -1) { @@ -377,7 +393,7 @@ rspamd_log_file_dtor (rspamd_logger_t *logger, gpointer arg) g_free (priv); } -void +bool rspamd_log_file_log (const gchar *module, const gchar *id, const gchar *function, gint level_flags, @@ -400,19 +416,20 @@ rspamd_log_file_log (const gchar *module, const gchar *id, if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) { - return; + return false; } /* Check throttling due to write errors */ if (!(level_flags & RSPAMD_LOG_FORCED) && priv->throttling) { now = rspamd_get_calendar_ticks (); + if (priv->throttling_time != now) { priv->throttling_time = now; got_time = TRUE; } else { /* Do not try to write to file too often while throttling */ - return; + return false; } } @@ -442,12 +459,12 @@ rspamd_log_file_log (const gchar *module, const gchar *id, priv->saved_loglevel = level_flags; } - return; + return true; } else if (priv->repeats > REPEATS_MAX) { rspamd_log_reset_repeated (rspamd_log, priv); - rspamd_log_file_log (module, id, + bool ret = rspamd_log_file_log (module, id, function, level_flags, message, @@ -458,7 +475,7 @@ rspamd_log_file_log (const gchar *module, const gchar *id, /* Probably we have more repeats in future */ priv->repeats = REPEATS_MIN + 1; - return; + return ret; } } else { @@ -467,14 +484,13 @@ rspamd_log_file_log (const gchar *module, const gchar *id, if (priv->repeats > REPEATS_MIN) { rspamd_log_reset_repeated (rspamd_log, priv); - rspamd_log_file_log (module, id, + return rspamd_log_file_log (module, id, function, level_flags, message, mlen, rspamd_log, arg); - return; } else { priv->repeats = 0; @@ -489,25 +505,8 @@ rspamd_log_file_log (const gchar *module, const gchar *id, log_time (now, rspamd_log, timebuf, sizeof (timebuf)); } - cptype = g_quark_to_string (rspamd_log->process_type); - - if (rspamd_log->flags & RSPAMD_LOG_FLAG_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; - } + cptype = rspamd_log->process_type; + r = 0; if (!(rspamd_log->flags & RSPAMD_LOG_FLAG_SYSTEMD)) { r += rspamd_snprintf (tmpbuf + r, @@ -562,7 +561,7 @@ rspamd_log_file_log (const gchar *module, const gchar *id, iov[3].iov_base = (void *) &lf_chr; iov[3].iov_len = 1; - file_log_helper (rspamd_log, priv, iov, 4, level_flags); + return file_log_helper (rspamd_log, priv, iov, 4, level_flags); } void * diff --git a/src/libutil/logger_private.h b/src/libutil/logger_private.h index 4644e4e86..84ec3b026 100644 --- a/src/libutil/logger_private.h +++ b/src/libutil/logger_private.h @@ -60,7 +60,6 @@ struct rspamd_logger_error_log { */ struct rspamd_logger_s { struct rspamd_logger_funcs ops; - gint log_facility; gint log_level; struct rspamd_logger_error_log *errlog; @@ -74,9 +73,10 @@ struct rspamd_logger_s { gboolean opened; pid_t pid; - GQuark process_type; + const gchar *process_type; struct rspamd_radix_map_helper *debug_ip; rspamd_mempool_mutex_t *mtx; + guint64 log_cnt[4]; }; /* @@ -91,7 +91,7 @@ void * rspamd_log_file_init (rspamd_logger_t *logger, struct rspamd_config *cfg, void * rspamd_log_file_reload (rspamd_logger_t *logger, struct rspamd_config *cfg, gpointer arg, uid_t uid, gid_t gid, GError **err); void rspamd_log_file_dtor (rspamd_logger_t *logger, gpointer arg); -void rspamd_log_file_log (const gchar *module, const gchar *id, +bool rspamd_log_file_log (const gchar *module, const gchar *id, const gchar *function, gint level_flags, const gchar *message, @@ -106,4 +106,50 @@ const static struct rspamd_logger_funcs file_log_funcs = { .log = rspamd_log_file_log, }; +/* + * Syslog logging + */ +void * rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg, + uid_t uid, gid_t gid, GError **err); +void * rspamd_log_syslog_reload (rspamd_logger_t *logger, struct rspamd_config *cfg, + gpointer arg, uid_t uid, gid_t gid, GError **err); +void rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg); +bool rspamd_log_syslog_log (const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log, + gpointer arg); + +const static struct rspamd_logger_funcs syslog_log_funcs = { + .init = rspamd_log_syslog_init, + .dtor = rspamd_log_syslog_dtor, + .reload = rspamd_log_syslog_reload, + .log = rspamd_log_syslog_log, +}; + +/* + * Console logging + */ +void * rspamd_log_console_init (rspamd_logger_t *logger, struct rspamd_config *cfg, + uid_t uid, gid_t gid, GError **err); +void * rspamd_log_console_reload (rspamd_logger_t *logger, struct rspamd_config *cfg, + gpointer arg, uid_t uid, gid_t gid, GError **err); +void rspamd_log_console_dtor (rspamd_logger_t *logger, gpointer arg); +bool rspamd_log_console_log (const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log, + gpointer arg); + +const static struct rspamd_logger_funcs console_log_funcs = { + .init = rspamd_log_console_init, + .dtor = rspamd_log_console_dtor, + .reload = rspamd_log_console_reload, + .log = rspamd_log_console_log, +}; + #endif diff --git a/src/libutil/logger_syslog.c b/src/libutil/logger_syslog.c new file mode 100644 index 000000000..15afabdb9 --- /dev/null +++ b/src/libutil/logger_syslog.c @@ -0,0 +1,142 @@ +/*- + * Copyright 2020 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" +#include "logger.h" +#include "libserver/cfg_file.h" +#include "logger_private.h" + +#define SYSLOG_LOG_QUARK g_quark_from_static_string ("syslog_logger") + +struct rspamd_syslog_logger_priv { + gint log_facility; +}; + +#ifdef HAVE_SYSLOG_H +#include <syslog.h> + +void * +rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg, + uid_t uid, gid_t gid, GError **err) +{ + struct rspamd_syslog_logger_priv *priv; + + priv = g_malloc0 (sizeof (*priv)); + + priv->log_facility = cfg->log_facility; + openlog ("rspamd", LOG_NDELAY | LOG_PID, priv->log_facility); + + return priv; +} + +void +rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg) +{ + struct rspamd_syslog_logger_priv *priv = (struct rspamd_syslog_logger_priv *)arg; + + closelog (); + g_free (priv); +} +bool +rspamd_log_syslog_log (const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log, + gpointer arg) +{ + static const struct { + GLogLevelFlags glib_level; + gint syslog_level; + } levels_match[] = { + {G_LOG_LEVEL_DEBUG, LOG_DEBUG}, + {G_LOG_LEVEL_INFO, LOG_INFO}, + {G_LOG_LEVEL_WARNING, LOG_WARNING}, + {G_LOG_LEVEL_CRITICAL, LOG_ERR} + }; + unsigned i; + gint syslog_level; + + if (!(level_flags & RSPAMD_LOG_FORCED) && !rspamd_log->enabled) { + return false; + } + + /* Detect level */ + syslog_level = LOG_DEBUG; + + for (i = 0; i < G_N_ELEMENTS (levels_match); i ++) { + if (level_flags & levels_match[i].glib_level) { + syslog_level = levels_match[i].syslog_level; + break; + } + } + + syslog (syslog_level, "<%.*s>; %s; %s: %*.s", + LOG_ID, id != NULL ? id : "", + module != NULL ? module : "", + function != NULL ? function : "", + (gint)mlen, message); + + return true; +} + +#else + +void * +rspamd_log_syslog_init (rspamd_logger_t *logger, struct rspamd_config *cfg, + uid_t uid, gid_t gid, GError **err) +{ + g_set_error (err, SYSLOG_LOG_QUARK, EINVAL, "syslog support is not compiled in"); + + return NULL; +} + +bool +rspamd_log_syslog_log (const gchar *module, const gchar *id, + const gchar *function, + gint level_flags, + const gchar *message, + gsize mlen, + rspamd_logger_t *rspamd_log, + gpointer arg) +{ + return false; +} + +void +rspamd_log_syslog_dtor (rspamd_logger_t *logger, gpointer arg) +{ + /* Left blank intentionally */ +} + +#endif + +void * +rspamd_log_syslog_reload (rspamd_logger_t *logger, struct rspamd_config *cfg, + gpointer arg, uid_t uid, gid_t gid, GError **err) +{ + struct rspamd_syslog_logger_priv *npriv; + + npriv = rspamd_log_syslog_init (logger, cfg, uid, gid, err); + + if (npriv) { + /* Close old */ + rspamd_log_syslog_dtor (logger, arg); + } + + return npriv; +} |