]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: lib-event - Add support for amending the event log message in a callback.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 30 Jun 2019 09:41:58 +0000 (11:41 +0200)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 9 Jul 2019 19:42:48 +0000 (21:42 +0200)
src/lib/event-log.c
src/lib/lib-event-private.h
src/lib/lib-event.c
src/lib/lib-event.h

index b3f15bd16b9fb06a52d3be4d4a6fc352774ed914..eb672ed1cb27d9ec2b2b7da1eeac93d6bca0bd37 100644 (file)
@@ -95,18 +95,50 @@ void e_log(struct event *event, enum log_type level,
 }
 
 struct event_get_log_message_context {
+       const struct event_log_params *params;
+
        string_t *log_prefix;
+       const char *message;
        bool replace_prefix;
        unsigned int type_pos;
 };
 
-static bool
+static bool ATTR_FORMAT(3, 0)
 event_get_log_message(struct event *event,
-                     struct event_get_log_message_context *glmctx)
+                     struct event_get_log_message_context *glmctx,
+                     const char *fmt, va_list args)
 {
        const char *prefix = event->log_prefix;
        bool ret = FALSE;
 
+       /* Call the message amendment callback for this event if there is one.
+        */
+       if (event->log_message_callback != NULL) {
+               const char *in_message;
+
+               /* construct the log message composed by children and arguments
+                */
+               if (glmctx->message == NULL) {
+                       str_vprintfa(glmctx->log_prefix, fmt, args);
+                       in_message = str_c(glmctx->log_prefix);
+               } else if (str_len(glmctx->log_prefix) == 0) {
+                       in_message = glmctx->message;
+               } else {
+                       str_append(glmctx->log_prefix, glmctx->message);
+                       in_message = str_c(glmctx->log_prefix);
+               }
+
+               /* reformat the log message */
+               glmctx->message = event->log_message_callback(
+                       event->log_message_callback_context,
+                       glmctx->params->log_type, in_message);
+
+               /* continue with a cleared prefix buffer (as prefix is now part
+                  of *message_r). */
+               str_truncate(glmctx->log_prefix, 0);
+               ret = TRUE;
+       }
+
        if (event->log_prefix_callback != NULL) {
                prefix = event->log_prefix_callback(
                        event->log_prefix_callback_context);
@@ -120,10 +152,8 @@ event_get_log_message(struct event *event,
                /* this event replaces all parent log prefixes */
                glmctx->replace_prefix = TRUE;
                glmctx->type_pos = (prefix == NULL ? 0 : strlen(prefix));
-       } else if (event->parent == NULL) {
-               /* append to default log prefix, don't replace it */
-       } else {
-               if (event_get_log_message(event->parent, glmctx))
+       } else if (event->parent != NULL) {
+               if (event_get_log_message(event->parent, glmctx, fmt, args))
                        ret = TRUE;
        }
        return ret;
@@ -208,18 +238,25 @@ event_logv_params(struct event *event, const struct event_log_params *params,
                abort_after_event = TRUE;
 
        i_zero(&glmctx);
+       glmctx.params = params;
        glmctx.log_prefix = t_str_new(64);
-       if (!event_get_log_message(event, &glmctx)) {
+       if (!event_get_log_message(event, &glmctx, fmt, args)) {
                /* keep log prefix as it is */
                event_vsend(event, &ctx, fmt, args);
        } else if (glmctx.replace_prefix) {
                /* event overrides the log prefix (even if it's "") */
                ctx.log_prefix = str_c(glmctx.log_prefix);
                ctx.log_prefix_type_pos = glmctx.type_pos;
-               event_vsend(event, &ctx, fmt, args);
+               if (glmctx.message != NULL)
+                       event_send(event, &ctx, "%s", glmctx.message);
+               else
+                       event_vsend(event, &ctx, fmt, args);
        } else {
                /* append to log prefix, but don't fully replace it */
-               str_vprintfa(glmctx.log_prefix, fmt, args);
+               if (glmctx.message != NULL)
+                       str_append(glmctx.log_prefix, glmctx.message);
+               else
+                       str_vprintfa(glmctx.log_prefix, fmt, args);
                event_send(event, &ctx, "%s", str_c(glmctx.log_prefix));
        }
        if (abort_after_event)
index 7b62e254217d21280a4c95de6519ee6a6c4bff80..7adc1de6f6d0b1430e4de27a0b9f5bfa7928968b 100644 (file)
@@ -14,6 +14,8 @@ struct event {
        char *log_prefix;
        event_log_prefix_callback_t *log_prefix_callback;
        void *log_prefix_callback_context;
+       event_log_message_callback_t *log_message_callback;
+       void *log_message_callback_context;
        enum log_type min_log_level;
        bool log_prefix_from_system_pool:1;
        bool log_prefix_replace:1;
index c88c1f7743b60a26fe396cebac9089b14126a796..7ea2acf79970cf1832a92cf21d38971d8300f7f4 100644 (file)
@@ -485,6 +485,17 @@ event_set_log_prefix_callback(struct event *event,
        return event;
 }
 
+#undef event_set_log_message_callback
+struct event *
+event_set_log_message_callback(struct event *event,
+                              event_log_message_callback_t *callback,
+                              void *context)
+{
+       event->log_message_callback = callback;
+       event->log_message_callback_context = context;
+       return event;
+}
+
 struct event *
 event_set_name(struct event *event, const char *name)
 {
index 690b0fd3a87a7efb2b11550217f1b9fd54659492..a1c6820f0f49415d82910d30fc331eacd243cbef 100644 (file)
@@ -77,7 +77,11 @@ struct event_passthrough {
        struct event *(*event)(void);
 };
 
-typedef const char *event_log_prefix_callback_t(void *context);
+typedef const char *
+event_log_prefix_callback_t(void *context);
+typedef const char *
+event_log_message_callback_t(void *context, enum log_type log_type,
+                            const char *message);
 
 /* Returns TRUE if the event has all the categories that the "other" event has (and maybe more). */
 bool event_has_all_categories(struct event *event, const struct event *other);
@@ -169,7 +173,8 @@ struct event *event_get_global(void);
 struct event *
 event_set_append_log_prefix(struct event *event, const char *prefix);
 /* Replace the full log prefix string for this event. The parent events' log
-   prefixes won't be used.
+   prefixes won't be used. Also, any parent event's message amendment callback
+   is not used.
 
    Clears log_prefix callback.
 */
@@ -185,6 +190,17 @@ struct event *event_set_log_prefix_callback(struct event *event,
        event_set_log_prefix_callback(event, replace, (event_log_prefix_callback_t*)callback, \
                context - CALLBACK_TYPECHECK(callback, const char *(*)(typeof(context))))
 
+/* Sets event message amendment callback */
+struct event *event_set_log_message_callback(struct event *event,
+                                            event_log_message_callback_t *callback,
+                                            void *context);
+#define event_set_log_message_callback(event, callback, context) \
+       event_set_log_message_callback(event, \
+               (event_log_message_callback_t*)callback, \
+               context - CALLBACK_TYPECHECK(callback, \
+                       const char *(*)(typeof(context), enum log_type, \
+                                       const char *)))
+
 /* Set the event's name. The name is specific to a single sending of an event,
    and it'll be automatically cleared once the event is sent. This should
    typically be used only in a parameter to e_debug(), etc. */