]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
log: Add LOG_SET_PREFIX() macro
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 27 Mar 2023 14:55:17 +0000 (16:55 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 29 Mar 2023 04:00:33 +0000 (13:00 +0900)
LOG_SET_PREFIX() sets a logging prefix for the current block. The
prefix is prepended to every logging message in the block, followed
by ": ". If a logging prefix is already configured, it is overridden
for the duration of the block, after which it is restored.

A use case for this macro is when we're operating on an image or
directory (using --root or --image). We can use LOG_SET_PREFIX() to
prefix all logging messages with the directory or image that we're
operating on.

src/basic/log.c
src/basic/log.h
src/test/test-log.c

index 7caa587ebf075331e0c2afe772d41835c2732d3b..75f59c43431f78ae530e1ffb30a3a22a80ff6969 100644 (file)
@@ -88,6 +88,8 @@ typedef struct LogContext {
 static thread_local LIST_HEAD(LogContext, _log_context) = NULL;
 static thread_local size_t _log_context_num_fields = 0;
 
+static thread_local const char *log_prefix = NULL;
+
 #if LOG_MESSAGE_VERIFICATION || defined(__COVERITY__)
 bool _log_message_dummy = false; /* Always false */
 #endif
@@ -395,7 +397,7 @@ static int write_to_console(
              header_time[FORMAT_TIMESTAMP_MAX],
              prefix[1 + DECIMAL_STR_MAX(int) + 2],
              tid_string[3 + DECIMAL_STR_MAX(pid_t) + 1];
-        struct iovec iovec[9];
+        struct iovec iovec[11];
         const char *on = NULL, *off = NULL;
         size_t n = 0;
 
@@ -434,6 +436,10 @@ static int write_to_console(
 
         if (on)
                 iovec[n++] = IOVEC_MAKE_STRING(on);
+        if (log_prefix) {
+                iovec[n++] = IOVEC_MAKE_STRING(log_prefix);
+                iovec[n++] = IOVEC_MAKE_STRING(": ");
+        }
         iovec[n++] = IOVEC_MAKE_STRING(buffer);
         if (off)
                 iovec[n++] = IOVEC_MAKE_STRING(off);
@@ -493,6 +499,8 @@ static int write_to_syslog(
                 IOVEC_MAKE_STRING(header_time),
                 IOVEC_MAKE_STRING(program_invocation_short_name),
                 IOVEC_MAKE_STRING(header_pid),
+                IOVEC_MAKE_STRING(strempty(log_prefix)),
+                IOVEC_MAKE_STRING(log_prefix ? ": " : ""),
                 IOVEC_MAKE_STRING(buffer),
         };
         const struct msghdr msghdr = {
@@ -554,6 +562,8 @@ static int write_to_kmsg(
                 IOVEC_MAKE_STRING(header_priority),
                 IOVEC_MAKE_STRING(program_invocation_short_name),
                 IOVEC_MAKE_STRING(header_pid),
+                IOVEC_MAKE_STRING(strempty(log_prefix)),
+                IOVEC_MAKE_STRING(log_prefix ? ": " : ""),
                 IOVEC_MAKE_STRING(buffer),
                 IOVEC_MAKE_STRING("\n"),
         };
@@ -665,13 +675,17 @@ static int write_to_journal(
         if (journal_fd < 0)
                 return 0;
 
-        iovec_len = MIN(4 + _log_context_num_fields * 2, IOVEC_MAX);
+        iovec_len = MIN(6 + _log_context_num_fields * 2, IOVEC_MAX);
         iovec = newa(struct iovec, iovec_len);
 
         log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
 
         iovec[n++] = IOVEC_MAKE_STRING(header);
         iovec[n++] = IOVEC_MAKE_STRING("MESSAGE=");
+        if (log_prefix) {
+                iovec[n++] = IOVEC_MAKE_STRING(log_prefix);
+                iovec[n++] = IOVEC_MAKE_STRING(": ");
+        }
         iovec[n++] = IOVEC_MAKE_STRING(buffer);
         iovec[n++] = IOVEC_MAKE_STRING("\n");
 
@@ -847,16 +861,9 @@ int log_object_internalv(
         /* Make sure that %m maps to the specified error (or "Success"). */
         LOCAL_ERRNO(ERRNO_VALUE(error));
 
-        /* Prepend the object name before the message */
-        if (object) {
-                size_t n;
-
-                n = strlen(object);
-                buffer = newa(char, n + 2 + LINE_MAX);
-                b = stpcpy(stpcpy(buffer, object), ": ");
-        } else
-                b = buffer = newa(char, LINE_MAX);
+        LOG_SET_PREFIX(object);
 
+        b = buffer = newa(char, LINE_MAX);
         (void) vsnprintf(b, LINE_MAX, format, ap);
 
         return log_dispatch_internal(level, error, file, line, func,
@@ -1572,6 +1579,15 @@ void log_setup(void) {
                 log_show_color(true);
 }
 
+const char *_log_set_prefix(const char *prefix, bool force) {
+        const char *old = log_prefix;
+
+        if (prefix || force)
+                log_prefix = prefix;
+
+        return old;
+}
+
 static int saved_log_context_enabled = -1;
 
 bool log_context_enabled(void) {
index 1e22293187ece6e7d97b3623a51379b130ac120d..9008d473909e13f642b8e1275ceba1e7f992a739 100644 (file)
@@ -426,6 +426,16 @@ typedef struct LogRateLimit {
 #define log_ratelimit_error_errno(error, ...)     log_ratelimit_full_errno(LOG_ERR,     error, __VA_ARGS__)
 #define log_ratelimit_emergency_errno(error, ...) log_ratelimit_full_errno(log_emergency_level(), error, __VA_ARGS__)
 
+const char *_log_set_prefix(const char *prefix, bool force);
+static inline const char *_log_unset_prefixp(const char **p) {
+        assert(p);
+        _log_set_prefix(*p, true);
+        return NULL;
+}
+
+#define LOG_SET_PREFIX(prefix) \
+        _cleanup_(_log_unset_prefixp) _unused_ const char *CONCATENATE(_cleanup_log_unset_prefix_, UNIQ) = _log_set_prefix(prefix, false);
+
 /*
  * The log context allows attaching extra metadata to log messages written to the journal via log.h. We keep
  * track of a thread local log context onto which we can push extra metadata fields that should be logged.
index 4fc4bc90874e8c062b1cfc9a3aaaee8f065b857c..e337a3c7df397395f5be9630e463ebeb5405face 100644 (file)
@@ -175,6 +175,32 @@ static void test_log_context(void) {
         assert_se(log_context_num_fields() == 0);
 }
 
+static void test_log_prefix(void) {
+        {
+                LOG_SET_PREFIX("ABC");
+
+                test_log_struct();
+                test_long_lines();
+                test_log_syntax();
+
+                {
+                        LOG_SET_PREFIX("QED");
+
+                        test_log_struct();
+                        test_long_lines();
+                        test_log_syntax();
+                }
+
+                test_log_struct();
+                test_long_lines();
+                test_log_syntax();
+        }
+
+        test_log_struct();
+        test_long_lines();
+        test_log_syntax();
+}
+
 int main(int argc, char* argv[]) {
         test_file();
 
@@ -188,6 +214,7 @@ int main(int argc, char* argv[]) {
                 test_long_lines();
                 test_log_syntax();
                 test_log_context();
+                test_log_prefix();
         }
 
         return 0;