summaryrefslogtreecommitdiff
path: root/src/basic/log.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-09-21 14:05:35 +0200
committerSven Eden <yamakuzure@gmx.net>2017-09-21 14:05:35 +0200
commit58da9c4933dc569030ba1bc54386cf04838ac0dc (patch)
tree5a4908595622ec30d3387f9da2c59b643459d882 /src/basic/log.c
parentfeab16e5e3c1fa3469405bde91b542e5dcf0aa40 (diff)
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.
Diffstat (limited to 'src/basic/log.c')
-rw-r--r--src/basic/log.c67
1 files changed, 67 insertions, 0 deletions
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;