From: Lennart Poettering Date: Thu, 21 Sep 2017 12:05:35 +0000 (+0200) Subject: core: whenever a unit terminates, log its consumed resources to the journal X-Git-Tag: v235.1~91 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=58da9c4933dc569030ba1bc54386cf04838ac0dc;p=elogind.git core: whenever a unit terminates, log its consumed resources to the journal This adds a new recognizable log message for each unit invocation that contains structured information about consumed resources of the unit as a whole after it terminated. This is particular useful for apps that want to figure out what the resource consumption of a unit given a specific invocation ID was. The log message is only generated for units that have at least one XyzAccounting= property turned on, and currently only covers IP traffic and CPU time metrics. --- diff --git a/src/basic/log.c b/src/basic/log.c index 13fedd847..c02a73a94 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -993,6 +993,73 @@ int log_struct_internal( return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8); } +int log_struct_iovec_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const struct iovec input_iovec[], + size_t n_input_iovec) { + + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + PROTECT_ERRNO; + size_t i; + char *m; + + if (error < 0) + error = -error; + + if (_likely_(LOG_PRI(level) > log_max_level[realm])) + return -error; + + if (log_target == LOG_TARGET_NULL) + return -error; + + if ((level & LOG_FACMASK) == 0) + level = log_facility | LOG_PRI(level); + + if (IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_JOURNAL) && + journal_fd >= 0) { + + struct iovec iovec[1 + n_input_iovec*2]; + char header[LINE_MAX]; + struct msghdr mh = { + .msg_iov = iovec, + .msg_iovlen = 1 + n_input_iovec*2, + }; + + log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); + iovec[0] = IOVEC_MAKE_STRING(header); + + for (i = 0; i < n_input_iovec; i++) { + iovec[1+i*2] = input_iovec[i]; + iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n"); + } + + if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0) + return -errno; + } + + for (i = 0; i < n_input_iovec; i++) { + if (input_iovec[i].iov_len < strlen("MESSAGE=")) + continue; + + if (memcmp(input_iovec[i].iov_base, "MESSAGE=", strlen("MESSAGE=")) == 0) + break; + } + + if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */ + return -error; + + m = strndupa(input_iovec[i].iov_base + strlen("MESSAGE="), + input_iovec[i].iov_len - strlen("MESSAGE=")); + + return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m); +} + int log_set_target_from_string(const char *e) { LogTarget t; diff --git a/src/basic/log.h b/src/basic/log.h index d3d6e6e73..38b71a593 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -188,6 +188,15 @@ int log_format_iovec( const char *format, va_list ap) _printf_(6, 0); +int log_struct_iovec_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const struct iovec input_iovec[], + size_t n_input_iovec); + /* This modifies the buffer passed! */ int log_dump_internal( int level, @@ -276,6 +285,11 @@ void log_assert_failed_return_realm( error, __FILE__, __LINE__, __func__, __VA_ARGS__) #define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__) +#define log_struct_iovec_errno(level, error, iovec, n_iovec) \ + log_struct_iovec_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ + error, __FILE__, __LINE__, __func__, iovec, n_iovec) +#define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec) + /* This modifies the buffer passed! */ #define log_dump(level, buffer) \ log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \