From 883354532cb6f050baf86511fa59baf908391714 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 21 Mar 2023 14:06:21 +0100 Subject: [PATCH 1/3] log: Avoid pushing the same fields more than once on the log context Let's try to optimize against pushing the same fields multiple times onto the log context. To achieve this we make the log context reference counted and return an existing context object if it's using the same fields. A consequence of this is that we have to make sure attaching/detaching is coupled to the lifetime of the context object, so we make the attach and detach functions private for now. If we need independent attach/detach in the future, we can make that work with some extra complexity but since we don't need it yet, let's not support it for now. --- src/basic/log.c | 28 +++++++++++++++++++---- src/basic/log.h | 22 ++++++++---------- src/libsystemd/sd-bus/sd-bus.c | 2 +- src/libsystemd/sd-device/device-monitor.c | 2 +- src/test/test-log.c | 18 ++++++++------- 5 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index 8b973f9e0a9..c713b9ac88d 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -73,6 +73,7 @@ static bool prohibit_ipc = false; static char *log_abort_msg = NULL; typedef struct LogContext { + unsigned n_ref; /* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory * referenced by this is freed or not */ char **fields; @@ -1562,7 +1563,7 @@ bool log_context_enabled(void) { return saved_log_context_enabled; } -LogContext* log_context_attach(LogContext *c) { +static LogContext* log_context_attach(LogContext *c) { assert(c); _log_context_num_fields += strv_length(c->fields); @@ -1571,7 +1572,7 @@ LogContext* log_context_attach(LogContext *c) { return LIST_PREPEND(ll, _log_context, c); } -LogContext* log_context_detach(LogContext *c) { +static LogContext* log_context_detach(LogContext *c) { if (!c) return NULL; @@ -1584,11 +1585,21 @@ LogContext* log_context_detach(LogContext *c) { } LogContext* log_context_new(char **fields, bool owned) { + if (!fields) + return NULL; + + LIST_FOREACH(ll, i, _log_context) + if (i->fields == fields) { + assert(!owned); + return log_context_ref(i); + } + LogContext *c = new(LogContext, 1); if (!c) return NULL; *c = (LogContext) { + .n_ref = 1, .fields = fields, .owned = owned, }; @@ -1598,13 +1609,20 @@ LogContext* log_context_new(char **fields, bool owned) { LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned) { if (!input_iovec || n_input_iovec == 0) - return NULL; /* Nothing to do */ + return NULL; + + LIST_FOREACH(ll, i, _log_context) + if (i->input_iovec == input_iovec && i->n_input_iovec == n_input_iovec) { + assert(!owned); + return log_context_ref(i); + } LogContext *c = new(LogContext, 1); if (!c) return NULL; *c = (LogContext) { + .n_ref = 1, .input_iovec = input_iovec, .n_input_iovec = n_input_iovec, .owned = owned, @@ -1613,7 +1631,7 @@ LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bo return log_context_attach(c); } -LogContext* log_context_free(LogContext *c) { +static LogContext* log_context_free(LogContext *c) { if (!c) return NULL; @@ -1627,6 +1645,8 @@ LogContext* log_context_free(LogContext *c) { return mfree(c); } +DEFINE_TRIVIAL_REF_UNREF_FUNC(LogContext, log_context, log_context_free); + LogContext* log_context_new_consume(char **fields) { LogContext *c = log_context_new(fields, /*owned=*/ true); if (!c) diff --git a/src/basic/log.h b/src/basic/log.h index c4ac73e27bc..f17a97ee370 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -457,25 +457,23 @@ typedef struct LogContext LogContext; bool log_context_enabled(void); -LogContext* log_context_attach(LogContext *c); -LogContext* log_context_detach(LogContext *c); - LogContext* log_context_new(char **fields, bool owned); LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned); -LogContext* log_context_free(LogContext *c); /* Same as log_context_new(), but frees the given fields strv/iovec on failure. */ LogContext* log_context_new_consume(char **fields); LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec); +LogContext *log_context_ref(LogContext *c); +LogContext *log_context_unref(LogContext *c); + +DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_unref); + /* Returns the number of attached log context objects. */ size_t log_context_num_contexts(void); /* Returns the number of fields in all attached log contexts. */ size_t log_context_num_fields(void); -DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_detach); -DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_free); - #define LOG_CONTEXT_PUSH(...) \ LOG_CONTEXT_PUSH_STRV(STRV_MAKE(__VA_ARGS__)) @@ -483,13 +481,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_free); LOG_CONTEXT_PUSH(snprintf_ok((char[LINE_MAX]) {}, LINE_MAX, __VA_ARGS__)) #define _LOG_CONTEXT_PUSH_STRV(strv, c) \ - _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_new(strv, /*owned=*/ false); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new(strv, /*owned=*/ false); #define LOG_CONTEXT_PUSH_STRV(strv) \ _LOG_CONTEXT_PUSH_STRV(strv, UNIQ_T(c, UNIQ)) #define _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, c) \ - _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ false); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ false); #define LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec) \ _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) @@ -503,19 +501,19 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(LogContext*, log_context_free); _unused_ _cleanup_strv_free_ strv = strv_new(s); \ if (!strv) \ free(s); \ - _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_new_consume(TAKE_PTR(strv)) + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consume(TAKE_PTR(strv)) #define LOG_CONTEXT_CONSUME_STR(s) \ _LOG_CONTEXT_CONSUME_STR(s, UNIQ_T(c, UNIQ), UNIQ_T(sv, UNIQ)) #define _LOG_CONTEXT_CONSUME_STRV(strv, c) \ - _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_new_consume(strv); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consume(strv); #define LOG_CONTEXT_CONSUME_STRV(strv) \ _LOG_CONTEXT_CONSUME_STRV(strv, UNIQ_T(c, UNIQ)) #define _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, c) \ - _unused_ _cleanup_(log_context_freep) LogContext *c = log_context_new_consumev(input_iovec, n_input_iovec); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consumev(input_iovec, n_input_iovec); #define LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec) \ _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index e3f71ca302c..4387db3841b 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2940,7 +2940,7 @@ static int process_fd_check(sd_bus *bus, sd_bus_message *m) { } static int process_message(sd_bus *bus, sd_bus_message *m) { - _unused_ _cleanup_(log_context_freep) LogContext *c = NULL; + _unused_ _cleanup_(log_context_unrefp) LogContext *c = NULL; int r; assert(bus); diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index 0d2eea5f591..1d8b7550b66 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -242,7 +242,7 @@ _public_ int sd_device_monitor_stop(sd_device_monitor *m) { static int device_monitor_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; - _unused_ _cleanup_(log_context_freep) LogContext *c = NULL; + _unused_ _cleanup_(log_context_unrefp) LogContext *c = NULL; sd_device_monitor *m = ASSERT_PTR(userdata); if (device_monitor_receive_device(m, &device) <= 0) diff --git a/src/test/test-log.c b/src/test/test-log.c index 68b5cb5092c..cfbd45c2e34 100644 --- a/src/test/test-log.c +++ b/src/test/test-log.c @@ -80,9 +80,10 @@ static void test_log_context(void) { LOG_CONTEXT_PUSH_STRV(strv); LOG_CONTEXT_PUSH_STRV(strv); - /* Test that the log context was set up correctly. */ - assert_se(log_context_num_contexts() == 4); - assert_se(log_context_num_fields() == 6); + /* Test that the log context was set up correctly. The strv we pushed twice should only + * result in one log context which is reused. */ + assert_se(log_context_num_contexts() == 3); + assert_se(log_context_num_fields() == 4); /* Test that everything still works with modifications to the log context. */ test_log_struct(); @@ -94,8 +95,8 @@ static void test_log_context(void) { LOG_CONTEXT_PUSH_STRV(strv); /* Check that our nested fields got added correctly. */ - assert_se(log_context_num_contexts() == 6); - assert_se(log_context_num_fields() == 9); + assert_se(log_context_num_contexts() == 4); + assert_se(log_context_num_fields() == 5); /* Test that everything still works in a nested block. */ test_log_struct(); @@ -104,15 +105,15 @@ static void test_log_context(void) { } /* Check that only the fields from the nested block got removed. */ - assert_se(log_context_num_contexts() == 4); - assert_se(log_context_num_fields() == 6); + assert_se(log_context_num_contexts() == 3); + assert_se(log_context_num_fields() == 4); } assert_se(log_context_num_contexts() == 0); assert_se(log_context_num_fields() == 0); { - _cleanup_(log_context_freep) LogContext *ctx = NULL; + _cleanup_(log_context_unrefp) LogContext *ctx = NULL; char **strv = STRV_MAKE("SIXTH=ijn", "SEVENTH=PRP"); assert_se(ctx = log_context_new(strv, /*owned=*/ false)); @@ -146,6 +147,7 @@ static void test_log_context(void) { assert_se(iovw); assert_se(iovw_consume(iovw, strdup("MNO=pqr"), STRLEN("MNO=pqr") + 1) == 0); + LOG_CONTEXT_PUSH_IOV(iov, ELEMENTSOF(iov)); LOG_CONTEXT_PUSH_IOV(iov, ELEMENTSOF(iov)); LOG_CONTEXT_CONSUME_IOV(iovw->iovec, iovw->count); LOG_CONTEXT_PUSH("STU=vwx"); From 81b3565efdb08df93596cc7a79ece57b528a69f3 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 21 Mar 2023 14:51:56 +0100 Subject: [PATCH 2/3] log: Add key/value support to the log context Now that we have reference counting, it's useful to be able to push single key values onto the log context separately, so that we don't have to allocate new storage to join the separate string together into a single field which means we won't be able to reuse a context containing the same field. --- src/basic/log.c | 53 +++++++++++++++++++---- src/basic/log.h | 25 +++++++---- src/libsystemd/sd-bus/sd-bus.c | 2 +- src/libsystemd/sd-device/device-monitor.c | 2 +- src/test/test-log.c | 13 +++++- 5 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index c713b9ac88d..6b847c37757 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -42,7 +42,7 @@ #include "utf8.h" #define SNDBUF_SIZE (8*1024*1024) -#define IOVEC_MAX 128U +#define IOVEC_MAX 256U static log_syntax_callback_t log_syntax_callback = NULL; static void *log_syntax_callback_userdata = NULL; @@ -79,6 +79,8 @@ typedef struct LogContext { char **fields; struct iovec *input_iovec; size_t n_input_iovec; + char *key; + char *value; bool owned; LIST_FIELDS(struct LogContext, ll); } LogContext; @@ -632,6 +634,15 @@ static void log_do_context(struct iovec *iovec, size_t iovec_len, size_t *n) { iovec[(*n)++] = c->input_iovec[i]; iovec[(*n)++] = IOVEC_MAKE_STRING("\n"); } + + if (c->key && c->value) { + if (*n + 3 >= iovec_len) + return; + + iovec[(*n)++] = IOVEC_MAKE_STRING(c->key); + iovec[(*n)++] = IOVEC_MAKE_STRING(c->value); + iovec[(*n)++] = IOVEC_MAKE_STRING("\n"); + } } } @@ -1568,6 +1579,7 @@ static LogContext* log_context_attach(LogContext *c) { _log_context_num_fields += strv_length(c->fields); _log_context_num_fields += c->n_input_iovec; + _log_context_num_fields += !!c->key; return LIST_PREPEND(ll, _log_context, c); } @@ -1576,15 +1588,38 @@ static LogContext* log_context_detach(LogContext *c) { if (!c) return NULL; - assert(_log_context_num_fields >= strv_length(c->fields) + c->n_input_iovec); + assert(_log_context_num_fields >= strv_length(c->fields) + c->n_input_iovec +!!c->key); _log_context_num_fields -= strv_length(c->fields); _log_context_num_fields -= c->n_input_iovec; + _log_context_num_fields -= !!c->key; LIST_REMOVE(ll, _log_context, c); return NULL; } -LogContext* log_context_new(char **fields, bool owned) { +LogContext* log_context_new(const char *key, const char *value) { + assert(key); + assert(endswith(key, "=")); + assert(value); + + LIST_FOREACH(ll, i, _log_context) + if (i->key == key && i->value == value) + return log_context_ref(i); + + LogContext *c = new(LogContext, 1); + if (!c) + return NULL; + + *c = (LogContext) { + .n_ref = 1, + .key = (char *) key, + .value = (char *) value, + }; + + return log_context_attach(c); +} + +LogContext* log_context_new_strv(char **fields, bool owned) { if (!fields) return NULL; @@ -1607,7 +1642,7 @@ LogContext* log_context_new(char **fields, bool owned) { return log_context_attach(c); } -LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned) { +LogContext* log_context_new_iov(struct iovec *input_iovec, size_t n_input_iovec, bool owned) { if (!input_iovec || n_input_iovec == 0) return NULL; @@ -1640,6 +1675,8 @@ static LogContext* log_context_free(LogContext *c) { if (c->owned) { strv_free(c->fields); iovec_array_free(c->input_iovec, c->n_input_iovec); + free(c->key); + free(c->value); } return mfree(c); @@ -1647,16 +1684,16 @@ static LogContext* log_context_free(LogContext *c) { DEFINE_TRIVIAL_REF_UNREF_FUNC(LogContext, log_context, log_context_free); -LogContext* log_context_new_consume(char **fields) { - LogContext *c = log_context_new(fields, /*owned=*/ true); +LogContext* log_context_new_strv_consume(char **fields) { + LogContext *c = log_context_new_strv(fields, /*owned=*/ true); if (!c) strv_free(fields); return c; } -LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec) { - LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ true); +LogContext* log_context_new_iov_consume(struct iovec *input_iovec, size_t n_input_iovec) { + LogContext *c = log_context_new_iov(input_iovec, n_input_iovec, /*owned=*/ true); if (!c) iovec_array_free(input_iovec, n_input_iovec); diff --git a/src/basic/log.h b/src/basic/log.h index f17a97ee370..28af01f68b8 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -457,12 +457,13 @@ typedef struct LogContext LogContext; bool log_context_enabled(void); -LogContext* log_context_new(char **fields, bool owned); -LogContext* log_context_newv(struct iovec *input_iovec, size_t n_input_iovec, bool owned); +LogContext* log_context_new(const char *key, const char *value); +LogContext* log_context_new_strv(char **fields, bool owned); +LogContext* log_context_new_iov(struct iovec *input_iovec, size_t n_input_iovec, bool owned); /* Same as log_context_new(), but frees the given fields strv/iovec on failure. */ -LogContext* log_context_new_consume(char **fields); -LogContext* log_context_new_consumev(struct iovec *input_iovec, size_t n_input_iovec); +LogContext* log_context_new_strv_consume(char **fields); +LogContext* log_context_new_iov_consume(struct iovec *input_iovec, size_t n_input_iovec); LogContext *log_context_ref(LogContext *c); LogContext *log_context_unref(LogContext *c); @@ -480,14 +481,20 @@ size_t log_context_num_fields(void); #define LOG_CONTEXT_PUSHF(...) \ LOG_CONTEXT_PUSH(snprintf_ok((char[LINE_MAX]) {}, LINE_MAX, __VA_ARGS__)) +#define _LOG_CONTEXT_PUSH_KEY_VALUE(key, value, c) \ + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new(key, value); + +#define LOG_CONTEXT_PUSH_KEY_VALUE(key, value) \ + _LOG_CONTEXT_PUSH_KEY_VALUE(key, value, UNIQ_T(c, UNIQ)) + #define _LOG_CONTEXT_PUSH_STRV(strv, c) \ - _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new(strv, /*owned=*/ false); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv(strv, /*owned=*/ false); #define LOG_CONTEXT_PUSH_STRV(strv) \ _LOG_CONTEXT_PUSH_STRV(strv, UNIQ_T(c, UNIQ)) #define _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, c) \ - _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_newv(input_iovec, n_input_iovec, /*owned=*/ false); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_iov(input_iovec, n_input_iovec, /*owned=*/ false); #define LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec) \ _LOG_CONTEXT_PUSH_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) @@ -501,19 +508,19 @@ size_t log_context_num_fields(void); _unused_ _cleanup_strv_free_ strv = strv_new(s); \ if (!strv) \ free(s); \ - _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consume(TAKE_PTR(strv)) + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv_consume(TAKE_PTR(strv)) #define LOG_CONTEXT_CONSUME_STR(s) \ _LOG_CONTEXT_CONSUME_STR(s, UNIQ_T(c, UNIQ), UNIQ_T(sv, UNIQ)) #define _LOG_CONTEXT_CONSUME_STRV(strv, c) \ - _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consume(strv); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_strv_consume(strv); #define LOG_CONTEXT_CONSUME_STRV(strv) \ _LOG_CONTEXT_CONSUME_STRV(strv, UNIQ_T(c, UNIQ)) #define _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, c) \ - _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_consumev(input_iovec, n_input_iovec); + _unused_ _cleanup_(log_context_unrefp) LogContext *c = log_context_new_iov_consume(input_iovec, n_input_iovec); #define LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec) \ _LOG_CONTEXT_CONSUME_IOV(input_iovec, n_input_iovec, UNIQ_T(c, UNIQ)) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 4387db3841b..6ee8bb7a7ff 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2950,7 +2950,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { bus->iteration_counter++; if (log_context_enabled()) - c = log_context_new_consume(bus_message_make_log_fields(m)); + c = log_context_new_strv_consume(bus_message_make_log_fields(m)); log_debug_bus_message(m); diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index 1d8b7550b66..af093385da8 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -249,7 +249,7 @@ static int device_monitor_event_handler(sd_event_source *s, int fd, uint32_t rev return 0; if (log_context_enabled()) - c = log_context_new_consume(device_make_log_fields(device)); + c = log_context_new_strv_consume(device_make_log_fields(device)); if (m->callback) return m->callback(m, device, m->userdata); diff --git a/src/test/test-log.c b/src/test/test-log.c index cfbd45c2e34..4fc4bc90874 100644 --- a/src/test/test-log.c +++ b/src/test/test-log.c @@ -116,7 +116,7 @@ static void test_log_context(void) { _cleanup_(log_context_unrefp) LogContext *ctx = NULL; char **strv = STRV_MAKE("SIXTH=ijn", "SEVENTH=PRP"); - assert_se(ctx = log_context_new(strv, /*owned=*/ false)); + assert_se(ctx = log_context_new_strv(strv, /*owned=*/ false)); assert_se(log_context_num_contexts() == 1); assert_se(log_context_num_fields() == 2); @@ -160,6 +160,17 @@ static void test_log_context(void) { test_log_syntax(); } + { + LOG_CONTEXT_PUSH_KEY_VALUE("ABC=", "QED"); + LOG_CONTEXT_PUSH_KEY_VALUE("ABC=", "QED"); + assert_se(log_context_num_contexts() == 1); + assert_se(log_context_num_fields() == 1); + + test_log_struct(); + test_long_lines(); + test_log_syntax(); + } + assert_se(log_context_num_contexts() == 0); assert_se(log_context_num_fields() == 0); } From 4b2af439eb3f56ae309f26e7ce08a8eb573ca417 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 21 Mar 2023 14:57:29 +0100 Subject: [PATCH 3/3] unit: Add LOG_CONTEXT_PUSH_UNIT() A helper macro to push all unit related fields onto the log context. We also modify exec_spawn() to use it. --- src/core/execute.c | 2 ++ src/core/unit.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index 093d1ad5b47..b448ad175e6 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -5474,6 +5474,8 @@ int exec_spawn(Unit *unit, assert(params); assert(params->fds || (params->n_socket_fds + params->n_storage_fds <= 0)); + LOG_CONTEXT_PUSH_UNIT(unit); + if (context->std_input == EXEC_INPUT_SOCKET || context->std_output == EXEC_OUTPUT_SOCKET || context->std_error == EXEC_OUTPUT_SOCKET) { diff --git a/src/core/unit.h b/src/core/unit.h index d5a6d595e29..8f53773a119 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -1208,3 +1208,13 @@ typedef struct UnitForEachDependencyData { /* Note: this matches deps that have *any* of the atoms specified in match_atom set */ #define UNIT_FOREACH_DEPENDENCY(other, u, match_atom) \ _UNIT_FOREACH_DEPENDENCY(other, u, match_atom, UNIQ_T(data, UNIQ)) + +#define _LOG_CONTEXT_PUSH_UNIT(unit, u, c) \ + const Unit *u = (unit); \ + const ExecContext *c = unit_get_exec_context(u); \ + LOG_CONTEXT_PUSH_KEY_VALUE(u->manager->unit_log_field, u->id); \ + LOG_CONTEXT_PUSH_KEY_VALUE(u->manager->invocation_log_field, u->invocation_id_string); \ + LOG_CONTEXT_PUSH_IOV(c ? c->log_extra_fields : NULL, c ? c->n_log_extra_fields : 0) + +#define LOG_CONTEXT_PUSH_UNIT(unit) \ + _LOG_CONTEXT_PUSH_UNIT(unit, UNIQ_T(u, UNIQ), UNIQ_T(c, UNIQ))