]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add log types as event categories
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 16 Apr 2018 10:48:38 +0000 (13:48 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Wed, 25 Apr 2018 08:03:39 +0000 (11:03 +0300)
This allows using debug, info, warning, error, fatal and panic as
categories.

src/lib-master/stats-client.c
src/lib/event-filter.c
src/lib/event-filter.h
src/lib/event-log.c
src/stats/client-writer.c
src/stats/stats-metrics.c
src/stats/stats-metrics.h

index b7d3259bc5050f5fa6bffcab1df196fb72208733..2c007872bb38abdb8919e3e4af5d5e5cf4fb3b75 100644 (file)
@@ -201,7 +201,7 @@ stats_client_send_event(struct stats_client *client, struct event *event,
                        const struct failure_context *ctx)
 {
        if (!client->handshaked ||
-           !event_filter_match(client->filter, event))
+           !event_filter_match(client->filter, event, ctx))
                return;
 
        string_t *str = t_str_new(256);
index 55eb2e2d62900de45e0de3dbac83c6277f737c0f..23d46239f59a156b5471899ca228bf42df7171a7 100644 (file)
@@ -24,6 +24,28 @@ struct event_filter_category {
        struct event_category *category;
 };
 
+enum event_filter_log_type {
+       EVENT_FILTER_LOG_TYPE_DEBUG     = BIT(0),
+       EVENT_FILTER_LOG_TYPE_INFO      = BIT(1),
+       EVENT_FILTER_LOG_TYPE_WARNING   = BIT(2),
+       EVENT_FILTER_LOG_TYPE_ERROR     = BIT(3),
+       EVENT_FILTER_LOG_TYPE_FATAL     = BIT(4),
+       EVENT_FILTER_LOG_TYPE_PANIC     = BIT(5),
+
+       EVENT_FILTER_LOG_TYPE_ALL       = 0xff,
+};
+static const char *event_filter_log_type_names[] = {
+       "debug", "info", "warning", "error", "fatal", "panic",
+};
+static enum event_filter_log_type event_filter_log_types[] = {
+       EVENT_FILTER_LOG_TYPE_DEBUG,
+       EVENT_FILTER_LOG_TYPE_INFO,
+       EVENT_FILTER_LOG_TYPE_WARNING,
+       EVENT_FILTER_LOG_TYPE_ERROR,
+       EVENT_FILTER_LOG_TYPE_FATAL,
+       EVENT_FILTER_LOG_TYPE_PANIC,
+};
+
 struct event_filter_query_internal {
        unsigned int categories_count;
        unsigned int fields_count;
@@ -31,6 +53,7 @@ struct event_filter_query_internal {
        bool has_unregistered_categories;
        struct event_filter_category *categories;
        const struct event_field *fields;
+       enum event_filter_log_type log_type_mask;
 
        const char *name;
        const char *source_filename;
@@ -87,6 +110,21 @@ void event_filter_unref(struct event_filter **_filter)
        pool_unref(&filter->pool);
 }
 
+static bool
+event_filter_category_to_log_type(const char *name,
+                                 enum event_filter_log_type *log_type_r)
+{
+       unsigned int i;
+
+       for (i = 0; i < N_ELEMENTS(event_filter_log_type_names); i++) {
+               if (strcmp(name, event_filter_log_type_names[i]) == 0) {
+                       *log_type_r = 1 << i;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
 static void
 event_filter_add_categories(struct event_filter *filter,
                            struct event_filter_query_internal *int_query,
@@ -94,7 +132,8 @@ event_filter_add_categories(struct event_filter *filter,
 {
        unsigned int categories_count = str_array_length(categories);
        struct event_filter_category *cat;
-       unsigned int i;
+       enum event_filter_log_type log_type;
+       unsigned int i, j;
 
        if (categories_count == 0)
                return;
@@ -102,13 +141,18 @@ event_filter_add_categories(struct event_filter *filter,
        /* copy strings */
        cat = p_new(filter->pool, struct event_filter_category,
                    categories_count);
-       for (i = 0; i < categories_count; i++) {
-               cat[i].name = p_strdup(filter->pool, categories[i]);
-               cat[i].category = event_category_find_registered(categories[i]);
-               if (cat[i].category == NULL)
+       for (i = j = 0; i < categories_count; i++) {
+               if (event_filter_category_to_log_type(categories[i], &log_type)) {
+                       int_query->log_type_mask |= log_type;
+                       continue;
+               }
+               cat[j].name = p_strdup(filter->pool, categories[i]);
+               cat[j].category = event_category_find_registered(categories[i]);
+               if (cat[j].category == NULL)
                        int_query->has_unregistered_categories = TRUE;
+               j++;
        }
-       int_query->categories_count = categories_count;
+       int_query->categories_count = j;
        int_query->categories = cat;
 }
 
@@ -159,6 +203,11 @@ void event_filter_add(struct event_filter *filter,
                event_filter_add_categories(filter, int_query, query->categories);
        if (query->fields != NULL)
                event_filter_add_fields(filter, int_query, query->fields);
+
+       if (int_query->log_type_mask == 0) {
+               /* no explicit log types given. default to all. */
+               int_query->log_type_mask = EVENT_FILTER_LOG_TYPE_ALL;
+       }
 }
 
 void event_filter_merge(struct event_filter *dest,
@@ -175,7 +224,8 @@ void event_filter_merge(struct event_filter *dest,
                query.source_filename = int_query->source_filename;
                query.source_linenum = int_query->source_linenum;
 
-               if (int_query->categories_count > 0) {
+               if (int_query->categories_count > 0 ||
+                   int_query->log_type_mask != EVENT_FILTER_LOG_TYPE_ALL) {
                        ARRAY_TYPE(const_string) categories;
 
                        t_array_init(&categories, int_query->categories_count);
@@ -183,6 +233,12 @@ void event_filter_merge(struct event_filter *dest,
                                array_append(&categories,
                                             &int_query->categories[i].name, 1);
                        }
+                       for (i = 0; i < N_ELEMENTS(event_filter_log_type_names); i++) {
+                               if ((int_query->log_type_mask & (1 << i)) == 0)
+                                       continue;
+                               array_append(&categories,
+                                            &event_filter_log_type_names[i], 1);
+                       }
                        array_append_zero(&categories);
                        query.categories = array_idx(&categories, 0);
                }
@@ -225,6 +281,16 @@ event_filter_export_query(const struct event_filter_query_internal *query,
                str_append_tabescaped(dest, query->categories[i].name);
                str_append_c(dest, '\t');
        }
+       if (query->log_type_mask != EVENT_FILTER_LOG_TYPE_ALL) {
+               for (i = 0; i < N_ELEMENTS(event_filter_log_type_names); i++) {
+                       if ((query->log_type_mask & (1 << i)) == 0)
+                               continue;
+                       str_append_c(dest, EVENT_FILTER_CODE_CATEGORY);
+                       str_append_tabescaped(dest, event_filter_log_type_names[i]);
+                       str_append_c(dest, '\t');
+               }
+       }
+
        for (i = 0; i < query->fields_count; i++) {
                str_append_c(dest, EVENT_FILTER_CODE_FIELD);
                str_append_tabescaped(dest, query->fields[i].key);
@@ -408,8 +474,13 @@ event_filter_query_match_fields(const struct event_filter_query_internal *query,
 static bool
 event_filter_query_match(const struct event_filter_query_internal *query,
                         struct event *event, const char *source_filename,
-                        unsigned int source_linenum)
+                        unsigned int source_linenum,
+                        const struct failure_context *ctx)
 {
+       i_assert(ctx->type < N_ELEMENTS(event_filter_log_types));
+       if ((query->log_type_mask & event_filter_log_types[ctx->type]) == 0)
+               return FALSE;
+
        if (query->name != NULL) {
                if (event->sending_name == NULL ||
                    strcmp(event->sending_name, query->name) != 0)
@@ -440,15 +511,17 @@ event_filter_match_fastpath(struct event_filter *filter, struct event *event)
        return TRUE;
 }
 
-bool event_filter_match(struct event_filter *filter, struct event *event)
+bool event_filter_match(struct event_filter *filter, struct event *event,
+                       const struct failure_context *ctx)
 {
        return event_filter_match_source(filter, event, event->source_filename,
-                                        event->source_linenum);
+                                        event->source_linenum, ctx);
 }
 
 bool event_filter_match_source(struct event_filter *filter, struct event *event,
                               const char *source_filename,
-                              unsigned int source_linenum)
+                              unsigned int source_linenum,
+                              const struct failure_context *ctx)
 {
        const struct event_filter_query_internal *query;
 
@@ -457,7 +530,7 @@ bool event_filter_match_source(struct event_filter *filter, struct event *event,
 
        array_foreach(&filter->queries, query) {
                if (event_filter_query_match(query, event, source_filename,
-                                            source_linenum))
+                                            source_linenum, ctx))
                        return TRUE;
        }
        return FALSE;
@@ -466,17 +539,20 @@ bool event_filter_match_source(struct event_filter *filter, struct event *event,
 struct event_filter_match_iter {
        struct event_filter *filter;
        struct event *event;
+       const struct failure_context *failure_ctx;
        unsigned int idx;
 };
 
 struct event_filter_match_iter *
-event_filter_match_iter_init(struct event_filter *filter, struct event *event)
+event_filter_match_iter_init(struct event_filter *filter, struct event *event,
+                            const struct failure_context *ctx)
 {
        struct event_filter_match_iter *iter;
 
        iter = i_new(struct event_filter_match_iter, 1);
        iter->filter = filter;
        iter->event = event;
+       iter->failure_ctx = ctx;
        if (!event_filter_match_fastpath(filter, event))
                iter->idx = UINT_MAX;
        return iter;
@@ -496,7 +572,8 @@ void *event_filter_match_iter_next(struct event_filter_match_iter *iter)
                if (query->context != NULL &&
                    event_filter_query_match(query, iter->event,
                                             iter->event->source_filename,
-                                            iter->event->source_linenum))
+                                            iter->event->source_linenum,
+                                            iter->failure_ctx))
                        return query->context;
        }
        return NULL;
index 83fa66a7b626d9b9c48112723820264730ec7d18..4191e5a70d5d22eb5cc2a69bb1afcb94e08d1ed6 100644 (file)
@@ -55,16 +55,19 @@ bool event_filter_import_unescaped(struct event_filter *filter,
                                   const char **error_r);
 
 /* Returns TRUE if the event matches the event filter. */
-bool event_filter_match(struct event_filter *filter, struct event *event);
+bool event_filter_match(struct event_filter *filter, struct event *event,
+                       const struct failure_context *ctx);
 /* Same as event_filter_match(), but use the given source filename:linenum
    instead of taking it from the event. */
 bool event_filter_match_source(struct event_filter *filter, struct event *event,
                               const char *source_filename,
-                              unsigned int source_linenum);
+                              unsigned int source_linenum,
+                              const struct failure_context *ctx);
 
 /* Iterate through all queries that match the event. */
 struct event_filter_match_iter *
-event_filter_match_iter_init(struct event_filter *filter, struct event *event);
+event_filter_match_iter_init(struct event_filter *filter, struct event *event,
+                            const struct failure_context *ctx);
 /* Return context for the query that matched, or NULL when there are no more
    matches. */
 void *event_filter_match_iter_next(struct event_filter_match_iter *iter);
index bdd2436bbeea311356673462ddf3f9a4ec971a57..75b75b62554b167e101f78e25fce7e4424bb2a56 100644 (file)
@@ -111,12 +111,16 @@ static bool
 event_want_debug_log(struct event *event, const char *source_filename,
                     unsigned int source_linenum)
 {
+       struct failure_context ctx = { .type = LOG_TYPE_DEBUG };
+
        if (event->forced_debug)
                return TRUE;
 
-       return global_debug_log_filter == NULL ? FALSE :
-               event_filter_match_source(global_debug_log_filter, event,
-                                         source_filename, source_linenum);
+       if (global_debug_log_filter != NULL &&
+           event_filter_match_source(global_debug_log_filter, event,
+                                     source_filename, source_linenum, &ctx))
+               return TRUE;
+       return FALSE;
 }
 
 bool event_want_debug(struct event *event, const char *source_filename,
@@ -129,8 +133,11 @@ bool event_want_debug(struct event *event, const char *source_filename,
 
        /* see if debug send filtering matches */
        if (global_debug_send_filter != NULL) {
+               struct failure_context ctx = { .type = LOG_TYPE_DEBUG };
+
                if (event_filter_match_source(global_debug_send_filter, event,
-                                             source_filename, source_linenum))
+                                             source_filename, source_linenum,
+                                             &ctx))
                        return TRUE;
        }
        return FALSE;
index bde964ba396386d4b9ad6c67b5b0fad6baac949c..e1979225d3a18f62bff755c93dfc9c93819ebfc1 100644 (file)
@@ -116,6 +116,9 @@ writer_client_run_event(struct writer_client *client,
                *error_r = "Invalid log type";
                return FALSE;
        }
+       const struct failure_context ctx = {
+               .type = (enum log_type)log_type
+       };
        args++;
 
        struct event *event = event_create(parent_event);
@@ -123,7 +126,7 @@ writer_client_run_event(struct writer_client *client,
                event_unref(&event);
                return FALSE;
        }
-       stats_metrics_event(client->metrics, event);
+       stats_metrics_event(client->metrics, event, &ctx);
        *event_r = event;
        return TRUE;
 }
index 51804c3ab8c9a5596dfd9b2e42ac8941447e6480..aba60bfaf84151f775b619c1d63b9f9d8dff5dad 100644 (file)
@@ -175,12 +175,13 @@ stats_metric_event(struct metric *metric, struct event *event)
        }
 }
 
-void stats_metrics_event(struct stats_metrics *metrics, struct event *event)
+void stats_metrics_event(struct stats_metrics *metrics, struct event *event,
+                        const struct failure_context *ctx)
 {
        struct event_filter_match_iter *iter;
        struct metric *metric;
 
-       iter = event_filter_match_iter_init(metrics->filter, event);
+       iter = event_filter_match_iter_init(metrics->filter, event, ctx);
        while ((metric = event_filter_match_iter_next(iter)) != NULL)
                stats_metric_event(metric, event);
        event_filter_match_iter_deinit(&iter);
index 2ac23053dc94ebc31acf59a63030a1b1cbac7a5d..b30e1f87d56707f1ce76c10aa2ba9b50527cc02c 100644 (file)
@@ -29,7 +29,8 @@ struct event_filter *
 stats_metrics_get_event_filter(struct stats_metrics *metrics);
 
 /* Update metrics with given event. */
-void stats_metrics_event(struct stats_metrics *metrics, struct event *event);
+void stats_metrics_event(struct stats_metrics *metrics, struct event *event,
+                        const struct failure_context *ctx);
 
 /* Iterate through all the tracked metrics. */
 struct stats_metrics_iter *