From a113ee0dd7fdba285a379289d47351f6e39c51db Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Fri, 19 Apr 2019 12:45:44 -0400 Subject: [PATCH] Metadata: add env fields to ease life of viewer MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add the following field in the env section of the metadata: - trace_name The session name without datetime information. Hence when the session is an auto-generated one, only print LTTNG_DEFAULT_NAME. - trace_creation_time: The time at which the session was created. We use session->creation time for it. - tracer_buffering_scheme The buffering scheme used. The value can be uid or pid. - tracer_buffering_id The key used by the buffering scheme (uid/pid). - isa_length The length of the ISA used. (e.g 32 or 64) Addend these fields ensure that the trace itself carry information that is normally carried via folder hierarchy. e.g test-20190417-174951/ <- trace_name └── ust <- domain └── uid <- tracer_buffering_scheme └── 1000 <- tracer_buffering_id └── 64-bit <- isa_length ├── channel0_0 ├── channel0_1 ├── channel0_2 ├── channel0_3 ├── index │ ├── channel0_0.idx │ ├── channel0_1.idx │ ├── channel0_2.idx │ └── channel0_3.idx └── metadata Per-pid buffering is quite similar. Signed-off-by: Jonathan Rajotte --- src/bin/lttng-sessiond/ust-app.c | 5 +- src/bin/lttng-sessiond/ust-metadata.c | 122 +++++++++++++++++++++++--- src/bin/lttng-sessiond/ust-registry.c | 7 +- src/bin/lttng-sessiond/ust-registry.h | 18 +++- src/common/time.c | 32 +++++++ src/common/time.h | 9 ++ 6 files changed, 178 insertions(+), 15 deletions(-) diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 4bee50496..faa51c759 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -1993,7 +1993,7 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, app->byte_order, app->version.major, app->version.minor, reg_pid->root_shm_path, reg_pid->shm_path, - ua_sess->euid, ua_sess->egid); + ua_sess->euid, ua_sess->egid, ua_sess->tracing_id, app->uid); if (ret < 0) { /* * reg_pid->registry->reg.ust is NULL upon error, so we need to @@ -2060,7 +2060,8 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, app->uint64_t_alignment, app->long_alignment, app->byte_order, app->version.major, app->version.minor, reg_uid->root_shm_path, - reg_uid->shm_path, usess->uid, usess->gid); + reg_uid->shm_path, usess->uid, usess->gid, + ua_sess->tracing_id, app->uid); if (ret < 0) { /* * reg_uid->registry->reg.ust is NULL upon error, so we need to diff --git a/src/bin/lttng-sessiond/ust-metadata.c b/src/bin/lttng-sessiond/ust-metadata.c index a657f7c5d..f05c14c32 100644 --- a/src/bin/lttng-sessiond/ust-metadata.c +++ b/src/bin/lttng-sessiond/ust-metadata.c @@ -217,6 +217,41 @@ void sanitize_ctf_identifier(char *out, const char *in) } } +static +int print_escaped_ctf_string(struct ust_registry_session *session, const char *string) +{ + int ret; + size_t i; + char cur; + + i = 0; + cur = string[i]; + while (cur != '\0') { + switch (cur) { + case '\n': + ret = lttng_metadata_printf(session, "%s", "\\n"); + break; + case '\\': + case '"': + ret = lttng_metadata_printf(session, "%c", '\\'); + if (ret) + goto error; + /* We still print the current char */ + /* Fallthrough */ + default: + ret = lttng_metadata_printf(session, "%c", cur); + break; + } + + if (ret) + goto error; + + cur = string[++i]; + } +error: + return ret; +} + /* Called with session registry mutex held. */ static int ust_metadata_enum_statedump(struct ust_registry_session *session, @@ -869,6 +904,71 @@ int64_t measure_clock_offset(void) return offset_best_sample.offset; } +static +int print_metadata_session_information(struct ust_registry_session *registry) +{ + int ret; + struct ltt_session *session = NULL; + char creation_time[ISO8601_LEN]; + + rcu_read_lock(); + session = session_find_by_id(registry->tracing_id); + if (!session) { + ret = -1; + goto error; + } + + + /* Print the trace name */ + ret = lttng_metadata_printf(registry, " trace_name = \""); + if (ret) { + goto error; + } + + /* + * This is necessary since the creation time is present in the session + * name when it is generated. + */ + if (session->has_auto_generated_name) { + ret = print_escaped_ctf_string(registry, DEFAULT_SESSION_NAME); + } else { + ret = print_escaped_ctf_string(registry, session->name); + } + if (ret) { + goto error; + } + + ret = lttng_metadata_printf(registry, "\";\n"); + if (ret) { + goto error; + } + + /* Prepare creation time */ + ret = time_t_to_ISO8601(creation_time, sizeof(creation_time), + session->creation_time); + + if (ret) { + goto error; + } + + /* Output the reste of the information */ + ret = lttng_metadata_printf(registry, + " trace_creation_time = \"%s\";\n" + " hostname = \"%s\";\n", + creation_time, + session->hostname); + if (ret) { + goto error; + } + +error: + if (session) { + session_put(session); + } + rcu_read_unlock(); + return ret; +} + /* * Should be called with session registry mutex held. */ @@ -880,7 +980,6 @@ int ust_metadata_session_statedump(struct ust_registry_session *session, char uuid_s[UUID_STR_LEN], clock_uuid_s[UUID_STR_LEN]; int ret = 0; - char hostname[HOST_NAME_MAX]; assert(session); @@ -930,25 +1029,28 @@ int ust_metadata_session_statedump(struct ust_registry_session *session, if (ret) goto end; - /* ignore error, just use empty string if error. */ - hostname[0] = '\0'; - ret = gethostname(hostname, sizeof(hostname)); - if (ret && errno == ENAMETOOLONG) - hostname[HOST_NAME_MAX - 1] = '\0'; ret = lttng_metadata_printf(session, "env {\n" - " hostname = \"%s\";\n" " domain = \"ust\";\n" " tracer_name = \"lttng-ust\";\n" " tracer_major = %u;\n" - " tracer_minor = %u;\n", - hostname, + " tracer_minor = %u;\n" + " tracer_buffering_scheme = \"%s\";\n" + " tracer_buffering_id = %u;\n" + " isa_length = %u;\n", major, - minor + minor, + app ? "pid" : "uid", + app ? (int) app->uid : (int) session->tracing_uid, + session->bits_per_long ); if (ret) goto end; + ret = print_metadata_session_information(session); + if (ret) + goto end; + /* * If per-application registry, we can output extra information * about the application. diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index a8db79ea6..c495d86b7 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -880,7 +880,9 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, const char *root_shm_path, const char *shm_path, uid_t euid, - gid_t egid) + gid_t egid, + uint64_t tracing_id, + uid_t tracing_uid) { int ret; struct ust_registry_session *session; @@ -962,6 +964,9 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, goto error; } + session->tracing_id = tracing_id; + session->tracing_uid = tracing_uid; + pthread_mutex_lock(&session->lock); ret = ust_metadata_session_statedump(session, app, major, minor); pthread_mutex_unlock(&session->lock); diff --git a/src/bin/lttng-sessiond/ust-registry.h b/src/bin/lttng-sessiond/ust-registry.h index 2940ab7ac..2fc2dff87 100644 --- a/src/bin/lttng-sessiond/ust-registry.h +++ b/src/bin/lttng-sessiond/ust-registry.h @@ -131,6 +131,10 @@ struct ust_registry_session { */ uint32_t major; uint32_t minor; + + /* The id of the parent session */ + uint64_t tracing_id; + uid_t tracing_uid; }; struct ust_registry_channel { @@ -291,7 +295,9 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, const char *root_shm_path, const char *shm_path, uid_t euid, - gid_t egid); + gid_t egid, + uint64_t tracing_id, + uid_t tracing_uid); void ust_registry_session_destroy(struct ust_registry_session *session); int ust_registry_create_event(struct ust_registry_session *session, @@ -351,7 +357,15 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, uint32_t uint32_t_alignment, uint32_t uint64_t_alignment, uint32_t long_alignment, - int byte_order) + int byte_order, + uint32_t major, + uint32_t minor, + const char *root_shm_path, + const char *shm_path, + uid_t euid, + gid_t egid, + uint64_t tracing_id, + uid_t tracing_uid); { return 0; } diff --git a/src/common/time.c b/src/common/time.c index a01c16df5..387db3e32 100644 --- a/src/common/time.c +++ b/src/common/time.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -68,6 +69,37 @@ struct timespec timespec_abs_diff(struct timespec t1, struct timespec t2) return res; } +LTTNG_HIDDEN +int time_t_to_ISO8601(char *dest, size_t dest_size, time_t time) +{ + int ret; + struct tm tm, *timeinfo; + + if (dest_size < ISO8601_LEN) { + ERR("Failed to format time to ISO8601 destination too small"); + ret = -1; + goto end; + } + + timeinfo = localtime_r(&time, &tm); + if (!timeinfo) { + PERROR("localtime"); + ret = -1; + goto end; + } + + ret = strftime(dest, dest_size, ISO8601_FORMAT, timeinfo); + if (ret == 0) { + ERR("Failed to format time to ISO8601"); + ret = -1; + goto end; + } + + ret = 0; +end: + return ret; +} + static void __attribute__((constructor)) init_locale_utf8_support(void) { diff --git a/src/common/time.h b/src/common/time.h index 24513d30b..7e760599f 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -46,6 +46,9 @@ bool locale_supports_utf8(void); #define MIN_UNIT "m" #define HR_UNIT "h" +#define ISO8601_FORMAT "%Y%m%dT%H%M%S%z" +#define ISO8601_LEN 21 + /* * timespec_to_ms: Convert timespec to milliseconds. * @@ -61,4 +64,10 @@ int timespec_to_ms(struct timespec ts, unsigned long *ms); LTTNG_HIDDEN struct timespec timespec_abs_diff(struct timespec ts_a, struct timespec ts_b); +/* + * Format time_t to ISO8601 compatible format. + */ +LTTNG_HIDDEN +int time_t_to_ISO8601(char *s, size_t s_size, time_t time); + #endif /* LTTNG_TIME_H */ -- 2.34.1