]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add event_reason_begin/end() API
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 9 Mar 2021 14:45:20 +0000 (16:45 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 29 Sep 2021 10:09:58 +0000 (10:09 +0000)
This can be used to easily add reason_code to all events being emitted
within the begin..end calls. The reasons can also be nested. For example:

reason = event_reason_begin("reason1");
// ...
reason2 = event_reason_begin("reason2");
// ..
event_reason_end(&reason2);
event_reason_end(&reason);

This results in having reason_code=["reason1", "reason2"] for all events
emitted while reason2 exists.

src/lib/lib-event.c
src/lib/lib-event.h

index 809914af4e8b6e59f55132a051f3035b284e0137..587fb2b5e3ee5c5b668311c76e50907ccc6d1306 100644 (file)
@@ -55,6 +55,10 @@ struct event_internal_category {
        int refcount;
 };
 
+struct event_reason {
+       struct event *event;
+};
+
 extern const struct event_passthrough event_passthrough_vfuncs;
 
 static struct event *events = NULL;
@@ -524,6 +528,35 @@ struct event *event_get_global(void)
        return current_global_event;
 }
 
+#undef event_reason_begin
+struct event_reason *
+event_reason_begin(const char *reason_code, const char *source_filename,
+                  unsigned int source_linenum)
+{
+       struct event_reason *reason;
+
+       reason = i_new(struct event_reason, 1);
+       reason->event = event_create(event_get_global(),
+                                    source_filename, source_linenum);
+       event_strlist_append(reason->event, EVENT_REASON_CODE, reason_code);
+       event_push_global(reason->event);
+       return reason;
+}
+
+void event_reason_end(struct event_reason **_reason)
+{
+       struct event_reason *reason = *_reason;
+
+       if (reason == NULL)
+               return;
+       event_pop_global(reason->event);
+       /* This event was created only for global use. It shouldn't be
+          permanently stored anywhere. This assert could help catch bugs. */
+       i_assert(reason->event->refcount == 1);
+       event_unref(&reason->event);
+       i_free(reason);
+}
+
 static struct event *
 event_set_log_prefix(struct event *event, const char *prefix, bool append)
 {
index c7ea4ef13d310340ad461b4d78344184da1d41dd..82483518df6f6e2b9d06bec25d00c031b2d33f13 100644 (file)
@@ -4,6 +4,9 @@
 
 #include <sys/time.h>
 
+/* Field name for the reason_code string list. */
+#define EVENT_REASON_CODE "reason_code"
+
 struct event;
 struct event_log_params;
 
@@ -201,6 +204,16 @@ struct event *event_pop_global(struct event *event);
 /* Returns the current global event. */
 struct event *event_get_global(void);
 
+/* Shortcut to create and push a global event and set its reason_code field. */
+struct event_reason *
+event_reason_begin(const char *reason_code, const char *source_filename,
+                  unsigned int source_linenum);
+#define event_reason_begin(reason_code) \
+       event_reason_begin(reason_code, __FILE__, __LINE__)
+/* Finish the reason event. It pops the global event, which means it must be
+   at the top of the stack. */
+void event_reason_end(struct event_reason **reason);
+
 /* Set the appended log prefix string for this event. All the parent events'
    log prefixes will be concatenated together when logging. The log type
    text (e.g. "Info: ") will be inserted before appended log prefixes (but