summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-18 17:15:18 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-09-18 17:15:18 +0100
commit07ae99830ac1cdfc7f9a1c16c5dce62eb7d00cbe (patch)
tree33de5bb4ac3d5d16c9a7f1c4651954a19ea86f0d
parent35f8137b1d18ea516968f4f9598763c46b5c2790 (diff)
downloadrspamd-07ae99830ac1cdfc7f9a1c16c5dce62eb7d00cbe.tar.gz
rspamd-07ae99830ac1cdfc7f9a1c16c5dce62eb7d00cbe.zip
Add writing to rrd from the controller.
-rw-r--r--src/controller.c72
-rw-r--r--src/libutil/rrd.c74
-rw-r--r--src/libutil/rrd.h6
3 files changed, 152 insertions, 0 deletions
diff --git a/src/controller.c b/src/controller.c
index 5109fdb8c..b521eaa0e 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -34,6 +34,7 @@
#include "blake2.h"
#include "cryptobox.h"
#include "ottery.h"
+#include "libutil/rrd.h"
/* 60 seconds for worker's IO */
#define DEFAULT_WORKER_IO_TIMEOUT 60000
@@ -102,6 +103,11 @@
#define RSPAMD_PBKDF_ID_V1 1
+const struct timeval rrd_update_time = {
+ .tv_sec = 1,
+ .tv_usec = 0
+};
+
extern struct rspamd_main *rspamd_main;
gpointer init_controller_worker (struct rspamd_config *cfg);
void start_controller_worker (struct rspamd_worker *worker);
@@ -162,6 +168,10 @@ struct rspamd_controller_worker_ctx {
/* Local keypair */
gpointer key;
+
+ struct event *rrd_event;
+ struct rspamd_rrd_file *rrd;
+
};
struct rspamd_controller_session {
@@ -1884,6 +1894,52 @@ rspamd_controller_accept_socket (gint fd, short what, void *arg)
}
static void
+rspamd_controller_rrd_update (gint fd, short what, void *arg)
+{
+ struct rspamd_controller_worker_ctx *ctx = arg;
+ struct rspamd_stat *stat;
+ GArray ar;
+ gdouble points[4];
+ GError *err = NULL;
+ guint i, j;
+ gdouble val;
+
+ g_assert (ctx->rrd != NULL);
+ stat = ctx->srv->stat;
+
+ for (i = METRIC_ACTION_REJECT, j = 0;
+ i <= METRIC_ACTION_NOACTION && j < G_N_ELEMENTS (points);
+ i++) {
+ switch (i) {
+ case METRIC_ACTION_SOFT_REJECT:
+ break;
+ case METRIC_ACTION_REWRITE_SUBJECT:
+ val = stat->actions_stat[i];
+ break;
+ case METRIC_ACTION_ADD_HEADER:
+ val += stat->actions_stat[i];
+ points[j++] = val;
+ break;
+ default:
+ val = stat->actions_stat[i];
+ points[j++] = val;
+ }
+ }
+
+ ar.data = (gchar *)points;
+ ar.len = sizeof (points);
+
+ if (!rspamd_rrd_add_record (ctx->rrd, &ar, rspamd_get_calendar_ticks (),
+ &err)) {
+ msg_err_ctx ("cannot update rrd file: %e", err);
+ g_error_free (err);
+ }
+
+ /* Plan new event */
+ evtimer_add (ctx->rrd_event, &rrd_update_time);
+}
+
+static void
rspamd_controller_load_saved_stats (struct rspamd_controller_worker_ctx *ctx)
{
struct ucl_parser *parser;
@@ -2196,6 +2252,18 @@ start_controller_worker (struct rspamd_worker *worker)
rspamd_controller_load_saved_stats (ctx);
+ /* RRD collector */
+ if (ctx->cfg->rrd_file) {
+ ctx->rrd = rspamd_rrd_file_default (ctx->cfg->rrd_file, NULL);
+
+ if (ctx->rrd) {
+ ctx->rrd_event = g_slice_alloc (sizeof (*ctx->rrd));
+ evtimer_set (ctx->rrd_event, rspamd_controller_rrd_update, ctx);
+ event_base_set (ctx->ev_base, ctx->rrd_event);
+ event_add (ctx->rrd_event, &rrd_update_time);
+ }
+ }
+
rspamd_controller_password_sane (ctx, ctx->password, "normal password");
rspamd_controller_password_sane (ctx, ctx->enable_password, "enable "
"password");
@@ -2299,5 +2367,9 @@ start_controller_worker (struct rspamd_worker *worker)
rspamd_log_close (rspamd_main->logger);
rspamd_controller_store_saved_stats (ctx);
+ if (ctx->rrd) {
+ rspamd_rrd_close (ctx->rrd);
+ }
+
exit (EXIT_SUCCESS);
}
diff --git a/src/libutil/rrd.c b/src/libutil/rrd.c
index 7364a8729..638f44abe 100644
--- a/src/libutil/rrd.c
+++ b/src/libutil/rrd.c
@@ -1208,3 +1208,77 @@ rspamd_rrd_close (struct rspamd_rrd_file * file)
return 0;
}
+
+struct rspamd_rrd_file *
+rspamd_rrd_file_default (const gchar *path,
+ GError **err)
+{
+ struct rspamd_rrd_file *rrd;
+ struct rrd_ds_def ds[4];
+ struct rrd_rra_def rra[4];
+ GArray ar;
+
+ g_assert (path != NULL);
+
+ if (access (path, R_OK) != -1) {
+ /* We can open rrd file */
+ rrd = rspamd_rrd_open (path, err);
+
+ if (rrd == NULL) {
+ return NULL;
+ }
+
+ /* XXX: check rrd file sanity */
+ return rrd;
+ }
+
+ /* Try to create new rrd file */
+
+ rrd = rspamd_rrd_create (path, 4, 4, 1, rspamd_get_calendar_ticks (), err);
+
+ if (rrd == NULL) {
+ return NULL;
+ }
+
+ /* Create DS and RRA */
+ rrd_make_default_ds ("spam", rrd_dst_to_string (RRD_DST_COUNTER), 1, &ds[0]);
+ rrd_make_default_ds ("probable", rrd_dst_to_string (RRD_DST_COUNTER), 1,
+ &ds[1]);
+ rrd_make_default_ds ("greylist", rrd_dst_to_string (RRD_DST_COUNTER), 1,
+ &ds[2]);
+ rrd_make_default_ds ("ham", rrd_dst_to_string (RRD_DST_COUNTER), 1, &ds[3]);
+ ar.data = (gchar *)ds;
+ ar.len = sizeof (ds);
+
+ if (!rspamd_rrd_add_ds (rrd, &ar, err)) {
+ rspamd_rrd_close (rrd);
+ return NULL;
+ }
+
+ /* Once per minute for 1 day */
+ rrd_make_default_rra (rrd_cf_to_string (RRD_CF_AVERAGE),
+ 60, 24 * 60, &rra[0]);
+ /* Once per 5 minutes for 1 week */
+ rrd_make_default_rra (rrd_cf_to_string (RRD_CF_AVERAGE),
+ 5 * 60, 7 * 24 * 60 / 5, &rra[1]);
+ /* Once per hour for 1 month */
+ rrd_make_default_rra (rrd_cf_to_string (RRD_CF_AVERAGE),
+ 60 * 60, 30 * 24 * 60 / 3600, &rra[2]);
+ /* Once per day for 1 year */
+ rrd_make_default_rra (rrd_cf_to_string (RRD_CF_AVERAGE),
+ 60 * 60 * 24, 365 * 24 * 60 / (60 * 60 * 24), &rra[3]);
+ ar.data = (gchar *)rra;
+ ar.len = sizeof (rra);
+
+ if (!rspamd_rrd_add_rra (rrd, &ar, err)) {
+ rspamd_rrd_close (rrd);
+ return NULL;
+ }
+
+ if (!rspamd_rrd_finalize (rrd, err)) {
+ rspamd_rrd_close (rrd);
+ return NULL;
+ }
+
+ return rrd;
+}
diff --git a/src/libutil/rrd.h b/src/libutil/rrd.h
index e6231bab8..189ea479a 100644
--- a/src/libutil/rrd.h
+++ b/src/libutil/rrd.h
@@ -329,4 +329,10 @@ void rrd_make_default_ds (const gchar *name,
const gchar *type,
gulong pdp_step,
struct rrd_ds_def *ds);
+
+/**
+ * Open or create the default rspamd rrd file
+ */
+struct rspamd_rrd_file *rspamd_rrd_file_default (const gchar *path,
+ GError **err);
#endif /* RRD_H_ */