@@ -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 { |
@@ -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 |
@@ -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 |
@@ -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, |
@@ -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; | |||
} |
@@ -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 * |
@@ -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 |
@@ -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; | |||
} |