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 <jonathan.rajotte-julien@efficios.com>
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
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
}
}
+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,
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.
*/
char uuid_s[UUID_STR_LEN],
clock_uuid_s[UUID_STR_LEN];
int ret = 0;
- char hostname[HOST_NAME_MAX];
assert(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.
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;
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);
*/
uint32_t major;
uint32_t minor;
+
+ /* The id of the parent session */
+ uint64_t tracing_id;
+ uid_t tracing_uid;
};
struct ust_registry_channel {
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,
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;
}
*/
#include <common/time.h>
+#include <common/error.h>
#include <common/macros.h>
#include <stddef.h>
#include <stdint.h>
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)
{
#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.
*
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 */