]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Rework] Add console and syslog modules
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 10 Feb 2020 17:18:40 +0000 (17:18 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 10 Feb 2020 21:12:13 +0000 (21:12 +0000)
src/libserver/cfg_file.h
src/libutil/CMakeLists.txt
src/libutil/logger.c
src/libutil/logger.h
src/libutil/logger_console.c [new file with mode: 0644]
src/libutil/logger_file.c
src/libutil/logger_private.h
src/libutil/logger_syslog.c [new file with mode: 0644]

index 447ee4ed326b418905c3d314f85d4076a23934eb..cf1532692244e0e069c8d66226cd4079cdbc4937 100644 (file)
@@ -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 {
index 6cd5df8a06f67e39e191cd77414b5c5207362b64..553d96e4771f62f8d23be7352c9387246dee957b 100644 (file)
@@ -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
index 1f586b1112767bb7ba911d5ed5354911e65534d1..f2ab3f611f9cc3924e3e23733f4bac66208270a7 100644 (file)
 #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
index 3cec58249680ecbbd4da163b9eb5497f38445de7..e98905f764984273f07f4573dfc0c929b82f480c 100644 (file)
@@ -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,18 +87,13 @@ 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
  */
 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
  */
@@ -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 (file)
index 0000000..c410bdd
--- /dev/null
@@ -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
index b2e01cf8133d0712a076a6c9392dc961a8b61a05..b4bb6208b6ddcb86b6f92f0f051baaf2fbe2cb48 100644 (file)
@@ -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 *
index 4644e4e86650e5f4862c44655c36b4dc8e5b434b..84ec3b026d3a0628f315e59bdb8bab39db397267 100644 (file)
@@ -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 (file)
index 0000000..15afabd
--- /dev/null
@@ -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;
+}