app/trace: print arguments from chained entries
The trace app has been extended to parse chained entries when printing arguments that exceed the size of a single trace entry. Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: Ib9705fd08da998bea39f14eaa83305a8e9d0d5a8 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8406 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
6cc3169677
commit
2731216dca
@ -34,6 +34,7 @@
|
|||||||
#include "spdk/stdinc.h"
|
#include "spdk/stdinc.h"
|
||||||
#include "spdk/env.h"
|
#include "spdk/env.h"
|
||||||
#include "spdk/json.h"
|
#include "spdk/json.h"
|
||||||
|
#include "spdk/likely.h"
|
||||||
#include "spdk/string.h"
|
#include "spdk/string.h"
|
||||||
#include "spdk/util.h"
|
#include "spdk/util.h"
|
||||||
|
|
||||||
@ -104,6 +105,25 @@ struct object_stats {
|
|||||||
object_stats() : start(), index(), size(), tpoint_id(), counter(0) {}
|
object_stats() : start(), index(), size(), tpoint_id(), counter(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct argument_context {
|
||||||
|
struct spdk_trace_entry *entry;
|
||||||
|
struct spdk_trace_entry_buffer *buffer;
|
||||||
|
uint16_t lcore;
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
argument_context(struct spdk_trace_entry *entry,
|
||||||
|
uint16_t lcore) : entry(entry), lcore(lcore)
|
||||||
|
{
|
||||||
|
buffer = (struct spdk_trace_entry_buffer *)entry;
|
||||||
|
|
||||||
|
/* The first argument resides within the spdk_trace_entry structure, so the initial
|
||||||
|
* offset needs to be adjusted to the start of the spdk_trace_entry.args array
|
||||||
|
*/
|
||||||
|
offset = offsetof(struct spdk_trace_entry, args) -
|
||||||
|
offsetof(struct spdk_trace_entry_buffer, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct object_stats g_stats[SPDK_TRACE_MAX_OBJECT];
|
struct object_stats g_stats[SPDK_TRACE_MAX_OBJECT];
|
||||||
|
|
||||||
static char *g_exe_name;
|
static char *g_exe_name;
|
||||||
@ -171,39 +191,102 @@ print_float(const char *arg_string, float arg)
|
|||||||
printf("%-7s%-16.3f ", format_argname(arg_string), arg);
|
printf("%-7s%-16.3f ", format_argname(arg_string), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static struct spdk_trace_entry_buffer *
|
||||||
print_arg(uint8_t arg_type, const char *arg_string, const void *arg)
|
get_next_buffer(struct spdk_trace_entry_buffer *buf, uint16_t lcore)
|
||||||
{
|
{
|
||||||
uint64_t value;
|
struct spdk_trace_history *history;
|
||||||
|
|
||||||
switch (arg_type) {
|
history = spdk_get_per_lcore_history(g_histories, lcore);
|
||||||
|
|
||||||
|
if (spdk_unlikely((void *)buf == &history->entries[history->num_entries - 1])) {
|
||||||
|
return (struct spdk_trace_entry_buffer *)&history->entries[0];
|
||||||
|
} else {
|
||||||
|
return buf + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
build_arg(struct argument_context *argctx, const struct spdk_trace_argument *arg,
|
||||||
|
void *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
struct spdk_trace_entry *entry = argctx->entry;
|
||||||
|
struct spdk_trace_entry_buffer *buffer = argctx->buffer;
|
||||||
|
size_t curlen, argoff;
|
||||||
|
|
||||||
|
argoff = 0;
|
||||||
|
while (argoff < arg->size) {
|
||||||
|
if (argctx->offset == sizeof(buffer->data)) {
|
||||||
|
buffer = get_next_buffer(buffer, argctx->lcore);
|
||||||
|
if (spdk_unlikely(buffer->tpoint_id != SPDK_TRACE_MAX_TPOINT_ID ||
|
||||||
|
buffer->tsc != entry->tsc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
argctx->offset = 0;
|
||||||
|
argctx->buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
curlen = spdk_min(sizeof(buffer->data) - argctx->offset, arg->size - argoff);
|
||||||
|
if (argoff < bufsize) {
|
||||||
|
memcpy((uint8_t *)buf + argoff, &buffer->data[argctx->offset],
|
||||||
|
spdk_min(curlen, bufsize - argoff));
|
||||||
|
}
|
||||||
|
|
||||||
|
argctx->offset += curlen;
|
||||||
|
argoff += curlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_arg(struct argument_context *argctx, const struct spdk_trace_argument *arg)
|
||||||
|
{
|
||||||
|
uint64_t value = 0;
|
||||||
|
char strbuf[256];
|
||||||
|
|
||||||
|
switch (arg->type) {
|
||||||
case SPDK_TRACE_ARG_TYPE_PTR:
|
case SPDK_TRACE_ARG_TYPE_PTR:
|
||||||
memcpy(&value, arg, sizeof(value));
|
if (build_arg(argctx, arg, &value, sizeof(value))) {
|
||||||
print_ptr(arg_string, value);
|
print_ptr(arg->name, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPDK_TRACE_ARG_TYPE_INT:
|
case SPDK_TRACE_ARG_TYPE_INT:
|
||||||
memcpy(&value, arg, sizeof(value));
|
if (build_arg(argctx, arg, &value, sizeof(value))) {
|
||||||
print_uint64(arg_string, value);
|
print_uint64(arg->name, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPDK_TRACE_ARG_TYPE_STR:
|
case SPDK_TRACE_ARG_TYPE_STR:
|
||||||
print_string(arg_string, (const char *)arg);
|
assert((size_t)arg->size <= sizeof(strbuf));
|
||||||
|
if (build_arg(argctx, arg, strbuf, sizeof(strbuf))) {
|
||||||
|
print_string(arg->name, strbuf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_arg_json(uint8_t arg_type, const void *arg)
|
print_arg_json(struct argument_context *argctx, const struct spdk_trace_argument *arg)
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value = 0;
|
||||||
|
char strbuf[256];
|
||||||
|
|
||||||
switch (arg_type) {
|
switch (arg->type) {
|
||||||
case SPDK_TRACE_ARG_TYPE_PTR:
|
case SPDK_TRACE_ARG_TYPE_PTR:
|
||||||
case SPDK_TRACE_ARG_TYPE_INT:
|
case SPDK_TRACE_ARG_TYPE_INT:
|
||||||
memcpy(&value, arg, sizeof(value));
|
if (build_arg(argctx, arg, &value, sizeof(value))) {
|
||||||
spdk_json_write_uint64(g_json, value);
|
spdk_json_write_uint64(g_json, value);
|
||||||
|
} else {
|
||||||
|
spdk_json_write_null(g_json);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SPDK_TRACE_ARG_TYPE_STR:
|
case SPDK_TRACE_ARG_TYPE_STR:
|
||||||
spdk_json_write_string(g_json, (const char *)arg);
|
assert((size_t)arg->size <= sizeof(strbuf));
|
||||||
|
if (build_arg(argctx, arg, strbuf, sizeof(strbuf))) {
|
||||||
|
spdk_json_write_string(g_json, strbuf);
|
||||||
|
} else {
|
||||||
|
spdk_json_write_null(g_json);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +298,7 @@ print_event(struct spdk_trace_entry *e, uint64_t tsc_rate,
|
|||||||
struct spdk_trace_tpoint *d;
|
struct spdk_trace_tpoint *d;
|
||||||
struct object_stats *stats;
|
struct object_stats *stats;
|
||||||
float us;
|
float us;
|
||||||
size_t i, offset;
|
size_t i;
|
||||||
|
|
||||||
d = &g_histories->flags.tpoint[e->tpoint_id];
|
d = &g_histories->flags.tpoint[e->tpoint_id];
|
||||||
stats = &g_stats[d->object_type];
|
stats = &g_stats[d->object_type];
|
||||||
@ -246,13 +329,12 @@ print_event(struct spdk_trace_entry *e, uint64_t tsc_rate,
|
|||||||
printf("id: N/A");
|
printf("id: N/A");
|
||||||
}
|
}
|
||||||
} else if (e->object_id != 0) {
|
} else if (e->object_id != 0) {
|
||||||
print_arg(SPDK_TRACE_ARG_TYPE_PTR, "object", &e->object_id);
|
print_ptr("object", e->object_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, offset = 0; i < d->num_args; ++i) {
|
struct argument_context argctx(e, lcore);
|
||||||
assert(offset < sizeof(e->args));
|
for (i = 0; i < d->num_args; ++i) {
|
||||||
print_arg(d->args[i].type, d->args[i].name, &e->args[offset]);
|
print_arg(&argctx, &d->args[i]);
|
||||||
offset += d->args[i].size;
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@ -263,7 +345,7 @@ print_event_json(struct spdk_trace_entry *e, uint64_t tsc_rate,
|
|||||||
{
|
{
|
||||||
struct spdk_trace_tpoint *d;
|
struct spdk_trace_tpoint *d;
|
||||||
struct object_stats *stats;
|
struct object_stats *stats;
|
||||||
size_t i, offset;
|
size_t i;
|
||||||
|
|
||||||
d = &g_histories->flags.tpoint[e->tpoint_id];
|
d = &g_histories->flags.tpoint[e->tpoint_id];
|
||||||
stats = &g_stats[d->object_type];
|
stats = &g_stats[d->object_type];
|
||||||
@ -303,11 +385,11 @@ print_event_json(struct spdk_trace_entry *e, uint64_t tsc_rate,
|
|||||||
spdk_json_write_object_end(g_json);
|
spdk_json_write_object_end(g_json);
|
||||||
}
|
}
|
||||||
if (d->num_args > 0) {
|
if (d->num_args > 0) {
|
||||||
|
struct argument_context argctx(e, lcore);
|
||||||
|
|
||||||
spdk_json_write_named_array_begin(g_json, "args");
|
spdk_json_write_named_array_begin(g_json, "args");
|
||||||
for (i = 0, offset = 0; i < d->num_args; ++i) {
|
for (i = 0; i < d->num_args; ++i) {
|
||||||
assert(offset < sizeof(e->args));
|
print_arg_json(&argctx, &d->args[i]);
|
||||||
print_arg_json(d->args[i].type, &e->args[offset]);
|
|
||||||
offset += d->args[i].size;
|
|
||||||
}
|
}
|
||||||
spdk_json_write_array_end(g_json);
|
spdk_json_write_array_end(g_json);
|
||||||
}
|
}
|
||||||
@ -382,7 +464,9 @@ populate_events(struct spdk_trace_history *history, int num_entries)
|
|||||||
|
|
||||||
i = first;
|
i = first;
|
||||||
while (1) {
|
while (1) {
|
||||||
g_entry_map[entry_key(lcore, e[i].tsc)] = &e[i];
|
if (e[i].tpoint_id != SPDK_TRACE_MAX_TPOINT_ID) {
|
||||||
|
g_entry_map[entry_key(lcore, e[i].tsc)] = &e[i];
|
||||||
|
}
|
||||||
if (i == last) {
|
if (i == last) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user