dovecot-2.1: log: Keep track of last 1000 errors/warnings. "dove...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Feb 6 19:30:24 EET 2012
details: http://hg.dovecot.org/dovecot-2.1/rev/66f875b5102b
changeset: 14065:66f875b5102b
user: Timo Sirainen <tss at iki.fi>
date: Mon Feb 06 19:30:12 2012 +0200
description:
log: Keep track of last 1000 errors/warnings. "doveadm log errors" shows them.
diffstat:
src/doveadm/doveadm-log.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
src/log/Makefile.am | 6 +++-
src/log/log-connection.c | 60 ++++++++++++++++++++++++++++++++++++----------
src/log/log-connection.h | 3 +-
src/log/log-settings.c | 19 +++++++++++++-
src/log/main.c | 16 +++++++++++-
6 files changed, 140 insertions(+), 21 deletions(-)
diffs (truncated from 352 to 300 lines):
diff -r 0d224f2c3152 -r 66f875b5102b src/doveadm/doveadm-log.c
--- a/src/doveadm/doveadm-log.c Mon Feb 06 19:28:40 2012 +0200
+++ b/src/doveadm/doveadm-log.c Mon Feb 06 19:30:12 2012 +0200
@@ -2,9 +2,11 @@
#include "lib.h"
#include "ioloop.h"
+#include "istream.h"
#include "hash.h"
#include "str.h"
-#include "istream.h"
+#include "strescape.h"
+#include "time-util.h"
#include "master-service-private.h"
#include "master-service-settings.h"
#include "doveadm.h"
@@ -18,6 +20,8 @@
#define LAST_LOG_TYPE LOG_TYPE_PANIC
#define TEST_LOG_MSG_PREFIX "This is Dovecot's "
+#define LOG_ERRORS_FNAME "log-errors"
+#define LOG_TIMESTAMP_FORMAT "%b %d %H:%M:%S"
static void cmd_log_test(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
{
@@ -274,10 +278,59 @@
}
}
+static void cmd_log_error_write(const char *const *args)
+{
+ /* <type> <timestamp> <prefix> <text> */
+ const char *type_prefix = "?";
+ unsigned int type;
+ time_t t;
+
+ /* find type's prefix */
+ for (type = 0; type < LOG_TYPE_COUNT; type++) {
+ if (strcmp(args[0], failure_log_type_names[type]) == 0) {
+ type_prefix = failure_log_type_prefixes[type];
+ break;
+ }
+ }
+
+ if (str_to_time(args[1], &t) < 0) {
+ i_error("Invalid timestamp: %s", args[1]);
+ t = 0;
+ }
+
+ printf("%s %s%s%s\n", t_strflocaltime(LOG_TIMESTAMP_FORMAT, t),
+ args[2], type_prefix, args[3]);
+}
+
+static void cmd_log_errors(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
+{
+ struct istream *input;
+ const char *path, *line, *const *args;
+ int fd;
+
+ path = t_strconcat(doveadm_settings->base_dir,
+ "/"LOG_ERRORS_FNAME, NULL);
+ fd = net_connect_unix(path);
+ if (fd == -1)
+ i_fatal("net_connect_unix(%s) failed: %m", path);
+ net_set_nonblock(fd, FALSE);
+
+ input = i_stream_create_fd(fd, (size_t)-1, TRUE);
+ while ((line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
+ args = t_strsplit_tabescaped(line);
+ if (str_array_length(args) == 4)
+ cmd_log_error_write(args);
+ else
+ i_error("Invalid input from log: %s", line);
+ } T_END;
+ i_stream_destroy(&input);
+}
+
struct doveadm_cmd doveadm_cmd_log[] = {
{ cmd_log_test, "log test", "" },
{ cmd_log_reopen, "log reopen", "" },
- { cmd_log_find, "log find", "[<dir>]" }
+ { cmd_log_find, "log find", "[<dir>]" },
+ { cmd_log_errors, "log errors", "" }
};
void doveadm_register_log_commands(void)
diff -r 0d224f2c3152 -r 66f875b5102b src/log/Makefile.am
--- a/src/log/Makefile.am Mon Feb 06 19:28:40 2012 +0200
+++ b/src/log/Makefile.am Mon Feb 06 19:30:12 2012 +0200
@@ -11,9 +11,13 @@
log_DEPENDENCIES = $(LIBDOVECOT_DEPS)
log_SOURCES = \
+ doveadm-connection.c \
log-connection.c \
+ log-error-buffer.c \
log-settings.c \
main.c
noinst_HEADERS = \
- log-connection.h
+ doveadm-connection.h \
+ log-connection.h \
+ log-error-buffer.h
diff -r 0d224f2c3152 -r 66f875b5102b src/log/log-connection.c
--- a/src/log/log-connection.c Mon Feb 06 19:28:40 2012 +0200
+++ b/src/log/log-connection.c Mon Feb 06 19:30:12 2012 +0200
@@ -8,6 +8,7 @@
#include "hash.h"
#include "master-interface.h"
#include "master-service.h"
+#include "log-error-buffer.h"
#include "log-connection.h"
#include <stdio.h>
@@ -25,6 +26,7 @@
struct log_connection {
struct log_connection *prev, *next;
+ struct log_error_buffer *errorbuf;
int fd;
int listen_fd;
struct io *io;
@@ -77,8 +79,38 @@
}
static void
+client_log_ctx(struct log_connection *log,
+ const struct failure_context *ctx, time_t log_time,
+ const char *prefix, const char *text)
+{
+ struct log_error err;
+
+ switch (ctx->type) {
+ case LOG_TYPE_DEBUG:
+ case LOG_TYPE_INFO:
+ case LOG_TYPE_COUNT:
+ case LOG_TYPE_OPTION:
+ break;
+ case LOG_TYPE_WARNING:
+ case LOG_TYPE_ERROR:
+ case LOG_TYPE_FATAL:
+ case LOG_TYPE_PANIC:
+ memset(&err, 0, sizeof(err));
+ err.type = ctx->type;
+ err.timestamp = log_time;
+ err.prefix = prefix;
+ err.text = text;
+ log_error_buffer_add(log->errorbuf, &err);
+ break;
+ }
+ i_set_failure_prefix(prefix);
+ i_log_type(ctx, "%s", text);
+ i_set_failure_prefix("log: ");
+}
+
+static void
client_log_fatal(struct log_connection *log, struct log_client *client,
- const char *line, const struct tm *tm)
+ const char *line, time_t log_time, const struct tm *tm)
{
struct failure_context failure_ctx;
const char *prefix = log->default_prefix;
@@ -95,13 +127,12 @@
line, net_ip2addr(&client->ip));
}
}
- i_set_failure_prefix(prefix);
- i_log_type(&failure_ctx, "master: %s", line);
- i_set_failure_prefix("log: ");
+ client_log_ctx(log, &failure_ctx, log_time, prefix,
+ t_strconcat("master: ", line, NULL));
}
static void
-log_parse_master_line(const char *line, const struct tm *tm)
+log_parse_master_line(const char *line, time_t log_time, const struct tm *tm)
{
struct log_connection *const *logs, *log;
struct log_client *client;
@@ -136,19 +167,20 @@
}
log_client_free(log, client, pid);
} else if (strncmp(line, "FATAL ", 6) == 0) {
- client_log_fatal(log, client, line + 6, tm);
+ client_log_fatal(log, client, line + 6, log_time, tm);
} else if (strncmp(line, "DEFAULT-FATAL ", 14) == 0) {
/* If the client has logged a fatal/panic, don't log this
message. */
if (client == NULL || !client->fatal_logged)
- client_log_fatal(log, client, line + 14, tm);
+ client_log_fatal(log, client, line + 14, log_time, tm);
} else {
i_error("Received unknown command from master: %s", line);
}
}
static void
-log_it(struct log_connection *log, const char *line, const struct tm *tm)
+log_it(struct log_connection *log, const char *line,
+ time_t log_time, const struct tm *tm)
{
struct failure_line failure;
struct failure_context failure_ctx;
@@ -157,7 +189,7 @@
if (log->master) {
T_BEGIN {
- log_parse_master_line(line, tm);
+ log_parse_master_line(line, log_time, tm);
} T_END;
return;
}
@@ -185,9 +217,7 @@
prefix = client != NULL && client->prefix != NULL ?
client->prefix : log->default_prefix;
- i_set_failure_prefix(prefix);
- i_log_type(&failure_ctx, "%s", failure.text);
- i_set_failure_prefix("log: ");
+ client_log_ctx(log, &failure_ctx, log_time, prefix, failure.text);
}
static int log_connection_handshake(struct log_connection *log)
@@ -256,7 +286,7 @@
tm = *localtime(&now);
while ((line = i_stream_next_line(log->input)) != NULL)
- log_it(log, line, &tm);
+ log_it(log, line, now, &tm);
}
if (log->input->eof)
@@ -269,11 +299,13 @@
}
}
-struct log_connection *log_connection_create(int fd, int listen_fd)
+struct log_connection *
+log_connection_create(struct log_error_buffer *errorbuf, int fd, int listen_fd)
{
struct log_connection *log;
log = i_new(struct log_connection, 1);
+ log->errorbuf = errorbuf;
log->fd = fd;
log->listen_fd = listen_fd;
log->io = io_add(fd, IO_READ, log_connection_input, log);
diff -r 0d224f2c3152 -r 66f875b5102b src/log/log-connection.h
--- a/src/log/log-connection.h Mon Feb 06 19:28:40 2012 +0200
+++ b/src/log/log-connection.h Mon Feb 06 19:30:12 2012 +0200
@@ -1,7 +1,8 @@
#ifndef LOG_CONNECTION_H
#define LOG_CONNECTION_H
-struct log_connection *log_connection_create(int fd, int listen_fd);
+struct log_connection *
+log_connection_create(struct log_error_buffer *errorbuf, int fd, int listen_fd);
void log_connection_destroy(struct log_connection *log);
void log_connections_init(void);
diff -r 0d224f2c3152 -r 66f875b5102b src/log/log-settings.c
--- a/src/log/log-settings.c Mon Feb 06 19:28:40 2012 +0200
+++ b/src/log/log-settings.c Mon Feb 06 19:30:12 2012 +0200
@@ -1,11 +1,25 @@
/* Copyright (c) 2009-2011 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "buffer.h"
#include "settings-parser.h"
#include "service-settings.h"
#include <stddef.h>
+/* <settings checks> */
+static struct file_listener_settings log_unix_listeners_array[] = {
+ { "log-errors", 0600, "", "" }
+};
+static struct file_listener_settings *log_unix_listeners[] = {
+ &log_unix_listeners_array[0]
+};
+static buffer_t log_unix_listeners_buf = {
+ log_unix_listeners,
+ sizeof(log_unix_listeners), { 0, }
+};
+/* </settings checks> */
+
struct service_settings log_service_settings = {
.name = "log",
.protocol = "",
@@ -23,10 +37,11 @@
.process_limit = 1,
.client_limit = 0,
.service_count = 0,
- .idle_kill = 0,
+ .idle_kill = -1U,
.vsz_limit = (uoff_t)-1,
- .unix_listeners = ARRAY_INIT,
+ .unix_listeners = { { &log_unix_listeners_buf,
More information about the dovecot-cvs
mailing list