Small refactoring of emitter
- Make API more clear for using as standalone json emitter - Support cases that weren't possible before, e.g. - emitting primitive values in an array - emitting nested arrays
This commit is contained in:
parent
41b7372ead
commit
eb261e53a6
@ -60,17 +60,6 @@ struct emitter_row_s {
|
||||
ql_head(emitter_col_t) cols;
|
||||
};
|
||||
|
||||
static inline void
|
||||
emitter_row_init(emitter_row_t *row) {
|
||||
ql_new(&row->cols);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_col_init(emitter_col_t *col, emitter_row_t *row) {
|
||||
ql_elm_new(col, link);
|
||||
ql_tail_insert(&row->cols, col, link);
|
||||
}
|
||||
|
||||
typedef struct emitter_s emitter_t;
|
||||
struct emitter_s {
|
||||
emitter_output_t output;
|
||||
@ -80,18 +69,10 @@ struct emitter_s {
|
||||
int nesting_depth;
|
||||
/* True if we've already emitted a value at the given depth. */
|
||||
bool item_at_depth;
|
||||
/* True if we emitted a key and will emit corresponding value next. */
|
||||
bool emitted_key;
|
||||
};
|
||||
|
||||
static inline void
|
||||
emitter_init(emitter_t *emitter, emitter_output_t emitter_output,
|
||||
void (*write_cb)(void *, const char *), void *cbopaque) {
|
||||
emitter->output = emitter_output;
|
||||
emitter->write_cb = write_cb;
|
||||
emitter->cbopaque = cbopaque;
|
||||
emitter->item_at_depth = false;
|
||||
emitter->nesting_depth = 0;
|
||||
}
|
||||
|
||||
/* Internal convenience function. Write to the emitter the given string. */
|
||||
JEMALLOC_FORMAT_PRINTF(2, 3)
|
||||
static inline void
|
||||
@ -103,18 +84,6 @@ emitter_printf(emitter_t *emitter, const char *format, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Write to the emitter the given string, but only in table mode. */
|
||||
JEMALLOC_FORMAT_PRINTF(2, 3)
|
||||
static inline void
|
||||
emitter_table_printf(emitter_t *emitter, const char *format, ...) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_gen_fmt(char *out_fmt, size_t out_size, const char *fmt_specifier,
|
||||
emitter_justify_t justify, int width) {
|
||||
@ -235,47 +204,143 @@ emitter_indent(emitter_t *emitter) {
|
||||
|
||||
static inline void
|
||||
emitter_json_key_prefix(emitter_t *emitter) {
|
||||
if (emitter->emitted_key) {
|
||||
emitter->emitted_key = false;
|
||||
return;
|
||||
}
|
||||
emitter_printf(emitter, "%s\n", emitter->item_at_depth ? "," : "");
|
||||
emitter_indent(emitter);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_begin(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth == 0);
|
||||
emitter_printf(emitter, "{");
|
||||
emitter_nest_inc(emitter);
|
||||
} else {
|
||||
// tabular init
|
||||
emitter_printf(emitter, "%s", "");
|
||||
}
|
||||
}
|
||||
/******************************************************************************/
|
||||
/* Public functions for emitter_t. */
|
||||
|
||||
static inline void
|
||||
emitter_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth == 1);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n}\n");
|
||||
}
|
||||
emitter_init(emitter_t *emitter, emitter_output_t emitter_output,
|
||||
void (*write_cb)(void *, const char *), void *cbopaque) {
|
||||
emitter->output = emitter_output;
|
||||
emitter->write_cb = write_cb;
|
||||
emitter->cbopaque = cbopaque;
|
||||
emitter->item_at_depth = false;
|
||||
emitter->emitted_key = false;
|
||||
emitter->nesting_depth = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* JSON public API. */
|
||||
|
||||
/*
|
||||
* Note emits a different kv pair as well, but only in table mode. Omits the
|
||||
* note if table_note_key is NULL.
|
||||
* Emits a key (e.g. as appears in an object). The next json entity emitted will
|
||||
* be the corresponding value.
|
||||
*/
|
||||
static inline void
|
||||
emitter_kv_note(emitter_t *emitter, const char *json_key, const char *table_key,
|
||||
emitter_json_key(emitter_t *emitter, const char *json_key) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "\"%s\": ", json_key);
|
||||
emitter->emitted_key = true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_value(emitter_t *emitter, emitter_type_t value_type,
|
||||
const void *value) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_print_value(emitter, emitter_justify_none, -1,
|
||||
value_type, value);
|
||||
emitter->item_at_depth = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shorthand for calling emitter_json_key and then emitter_json_value. */
|
||||
static inline void
|
||||
emitter_json_kv(emitter_t *emitter, const char *json_key,
|
||||
emitter_type_t value_type, const void *value) {
|
||||
emitter_json_key(emitter, json_key);
|
||||
emitter_json_value(emitter, value_type, value);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_array_begin(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "[");
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
/* Shorthand for calling emitter_json_key and then emitter_json_array_begin. */
|
||||
static inline void
|
||||
emitter_json_array_kv_begin(emitter_t *emitter, const char *json_key) {
|
||||
emitter_json_key(emitter, json_key);
|
||||
emitter_json_array_begin(emitter);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_array_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n");
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "]");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_object_begin(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "{");
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
/* Shorthand for calling emitter_json_key and then emitter_json_object_begin. */
|
||||
static inline void
|
||||
emitter_json_object_kv_begin(emitter_t *emitter, const char *json_key) {
|
||||
emitter_json_key(emitter, json_key);
|
||||
emitter_json_object_begin(emitter);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_object_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n");
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Table public API. */
|
||||
|
||||
static inline void
|
||||
emitter_table_dict_begin(emitter_t *emitter, const char *table_key) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "%s\n", table_key);
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_table_dict_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_nest_dec(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_table_kv_note(emitter_t *emitter, const char *table_key,
|
||||
emitter_type_t value_type, const void *value,
|
||||
const char *table_note_key, emitter_type_t table_note_value_type,
|
||||
const void *table_note_value) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "\"%s\": ", json_key);
|
||||
emitter_print_value(emitter, emitter_justify_none, -1,
|
||||
value_type, value);
|
||||
} else {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "%s: ", table_key);
|
||||
emitter_print_value(emitter, emitter_justify_none, -1,
|
||||
@ -292,130 +357,22 @@ emitter_kv_note(emitter_t *emitter, const char *json_key, const char *table_key,
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_kv(emitter_t *emitter, const char *json_key, const char *table_key,
|
||||
emitter_table_kv(emitter_t *emitter, const char *table_key,
|
||||
emitter_type_t value_type, const void *value) {
|
||||
emitter_kv_note(emitter, json_key, table_key, value_type, value, NULL,
|
||||
emitter_table_kv_note(emitter, table_key, value_type, value, NULL,
|
||||
emitter_type_bool, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_kv(emitter_t *emitter, const char *json_key,
|
||||
emitter_type_t value_type, const void *value) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_kv(emitter, json_key, NULL, value_type, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write to the emitter the given string, but only in table mode. */
|
||||
JEMALLOC_FORMAT_PRINTF(2, 3)
|
||||
static inline void
|
||||
emitter_table_kv(emitter_t *emitter, const char *table_key,
|
||||
emitter_type_t value_type, const void *value) {
|
||||
emitter_table_printf(emitter_t *emitter, const char *format, ...) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_kv(emitter, NULL, table_key, value_type, value);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_dict_begin(emitter_t *emitter, const char *json_key,
|
||||
const char *table_header) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "\"%s\": {", json_key);
|
||||
emitter_nest_inc(emitter);
|
||||
} else {
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "%s\n", table_header);
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_dict_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n");
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "}");
|
||||
} else {
|
||||
emitter_nest_dec(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_dict_begin(emitter_t *emitter, const char *json_key) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_dict_begin(emitter, json_key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_dict_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_dict_end(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_table_dict_begin(emitter_t *emitter, const char *table_key) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_dict_begin(emitter, NULL, table_key);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_table_dict_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_table) {
|
||||
emitter_dict_end(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_arr_begin(emitter_t *emitter, const char *json_key) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "\"%s\": [", json_key);
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_arr_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n");
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "]");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_arr_obj_begin(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_printf(emitter, "{");
|
||||
emitter_nest_inc(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_arr_obj_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth > 0);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n");
|
||||
emitter_indent(emitter);
|
||||
emitter_printf(emitter, "}");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_json_arr_value(emitter_t *emitter, emitter_type_t value_type,
|
||||
const void *value) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key_prefix(emitter);
|
||||
emitter_print_value(emitter, emitter_justify_none, -1,
|
||||
value_type, value);
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,4 +389,93 @@ emitter_table_row(emitter_t *emitter, emitter_row_t *row) {
|
||||
emitter_table_printf(emitter, "\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_row_init(emitter_row_t *row) {
|
||||
ql_new(&row->cols);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_col_init(emitter_col_t *col, emitter_row_t *row) {
|
||||
ql_elm_new(col, link);
|
||||
ql_tail_insert(&row->cols, col, link);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Generalized public API. Emits using either JSON or table, according to
|
||||
* settings in the emitter_t. */
|
||||
|
||||
/*
|
||||
* Note emits a different kv pair as well, but only in table mode. Omits the
|
||||
* note if table_note_key is NULL.
|
||||
*/
|
||||
static inline void
|
||||
emitter_kv_note(emitter_t *emitter, const char *json_key, const char *table_key,
|
||||
emitter_type_t value_type, const void *value,
|
||||
const char *table_note_key, emitter_type_t table_note_value_type,
|
||||
const void *table_note_value) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key(emitter, json_key);
|
||||
emitter_json_value(emitter, value_type, value);
|
||||
} else {
|
||||
emitter_table_kv_note(emitter, table_key, value_type, value,
|
||||
table_note_key, table_note_value_type, table_note_value);
|
||||
}
|
||||
emitter->item_at_depth = true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_kv(emitter_t *emitter, const char *json_key, const char *table_key,
|
||||
emitter_type_t value_type, const void *value) {
|
||||
emitter_kv_note(emitter, json_key, table_key, value_type, value, NULL,
|
||||
emitter_type_bool, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_dict_begin(emitter_t *emitter, const char *json_key,
|
||||
const char *table_header) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_key(emitter, json_key);
|
||||
emitter_json_object_begin(emitter);
|
||||
} else {
|
||||
emitter_table_dict_begin(emitter, table_header);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_dict_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_object_end(emitter);
|
||||
} else {
|
||||
emitter_table_dict_end(emitter);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_begin(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth == 0);
|
||||
emitter_printf(emitter, "{");
|
||||
emitter_nest_inc(emitter);
|
||||
} else {
|
||||
/*
|
||||
* This guarantees that we always call write_cb at least once.
|
||||
* This is useful if some invariant is established by each call
|
||||
* to write_cb, but doesn't hold initially: e.g., some buffer
|
||||
* holds a null-terminated string.
|
||||
*/
|
||||
emitter_printf(emitter, "%s", "");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_end(emitter_t *emitter) {
|
||||
if (emitter->output == emitter_output_json) {
|
||||
assert(emitter->nesting_depth == 1);
|
||||
emitter_nest_dec(emitter);
|
||||
emitter_printf(emitter, "\n}\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_EMITTER_H */
|
||||
|
92
src/stats.c
92
src/stats.c
@ -287,7 +287,7 @@ stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i) {
|
||||
header_col_size.width -=5;
|
||||
emitter_table_printf(emitter, "bins:");
|
||||
emitter_table_row(emitter, &header_row);
|
||||
emitter_json_arr_begin(emitter, "bins");
|
||||
emitter_json_array_kv_begin(emitter, "bins");
|
||||
|
||||
for (j = 0, in_gap = false; j < nbins; j++) {
|
||||
uint64_t nslabs;
|
||||
@ -333,7 +333,7 @@ stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i) {
|
||||
col_mutex32);
|
||||
}
|
||||
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_json_kv(emitter, "nmalloc", emitter_type_uint64,
|
||||
&nmalloc);
|
||||
emitter_json_kv(emitter, "ndalloc", emitter_type_uint64,
|
||||
@ -351,12 +351,12 @@ stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i) {
|
||||
emitter_json_kv(emitter, "curslabs", emitter_type_size,
|
||||
&curslabs);
|
||||
if (mutex) {
|
||||
emitter_json_dict_begin(emitter, "mutex");
|
||||
emitter_json_object_kv_begin(emitter, "mutex");
|
||||
mutex_stats_emit(emitter, NULL, col_mutex64,
|
||||
col_mutex32);
|
||||
emitter_json_dict_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
emitter_json_arr_obj_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
|
||||
size_t availregs = nregs * curslabs;
|
||||
char util[6];
|
||||
@ -400,7 +400,7 @@ stats_arena_bins_print(emitter_t *emitter, bool mutex, unsigned i) {
|
||||
|
||||
emitter_table_row(emitter, &row);
|
||||
}
|
||||
emitter_json_arr_end(emitter); /* Close "bins". */
|
||||
emitter_json_array_end(emitter); /* Close "bins". */
|
||||
|
||||
if (in_gap) {
|
||||
emitter_table_printf(emitter, " ---\n");
|
||||
@ -447,7 +447,7 @@ stats_arena_lextents_print(emitter_t *emitter, unsigned i) {
|
||||
header_size.width -= 6;
|
||||
emitter_table_printf(emitter, "large:");
|
||||
emitter_table_row(emitter, &header_row);
|
||||
emitter_json_arr_begin(emitter, "lextents");
|
||||
emitter_json_array_kv_begin(emitter, "lextents");
|
||||
|
||||
for (j = 0, in_gap = false; j < nlextents; j++) {
|
||||
uint64_t nmalloc, ndalloc, nrequests;
|
||||
@ -471,10 +471,10 @@ stats_arena_lextents_print(emitter_t *emitter, unsigned i) {
|
||||
CTL_M2_M4_GET("stats.arenas.0.lextents.0.curlextents", i, j,
|
||||
&curlextents, size_t);
|
||||
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_json_kv(emitter, "curlextents", emitter_type_size,
|
||||
&curlextents);
|
||||
emitter_json_arr_obj_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
|
||||
col_size.size_val = lextent_size;
|
||||
col_ind.unsigned_val = nbins + j;
|
||||
@ -488,7 +488,7 @@ stats_arena_lextents_print(emitter_t *emitter, unsigned i) {
|
||||
emitter_table_row(emitter, &row);
|
||||
}
|
||||
}
|
||||
emitter_json_arr_end(emitter); /* Close "lextents". */
|
||||
emitter_json_array_end(emitter); /* Close "lextents". */
|
||||
if (in_gap) {
|
||||
emitter_table_printf(emitter, " ---\n");
|
||||
}
|
||||
@ -504,19 +504,19 @@ stats_arena_mutexes_print(emitter_t *emitter, unsigned arena_ind) {
|
||||
emitter_row_init(&row);
|
||||
mutex_stats_init_cols(&row, "", &col_name, col64, col32);
|
||||
|
||||
emitter_json_dict_begin(emitter, "mutexes");
|
||||
emitter_json_object_kv_begin(emitter, "mutexes");
|
||||
emitter_table_row(emitter, &row);
|
||||
|
||||
for (mutex_prof_arena_ind_t i = 0; i < mutex_prof_num_arena_mutexes;
|
||||
i++) {
|
||||
const char *name = arena_mutex_names[i];
|
||||
emitter_json_dict_begin(emitter, name);
|
||||
emitter_json_object_kv_begin(emitter, name);
|
||||
mutex_stats_read_arena(arena_ind, i, name, &col_name, col64,
|
||||
col32);
|
||||
mutex_stats_emit(emitter, &row, col64, col32);
|
||||
emitter_json_dict_end(emitter); /* Close the mutex dict. */
|
||||
emitter_json_object_end(emitter); /* Close the mutex dict. */
|
||||
}
|
||||
emitter_json_dict_end(emitter); /* End "mutexes". */
|
||||
emitter_json_object_end(emitter); /* End "mutexes". */
|
||||
}
|
||||
|
||||
static void
|
||||
@ -738,7 +738,7 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||
alloc_count_##name.type = emitter_type_##valtype; \
|
||||
alloc_count_##name.valtype##_val = small_or_large##_##name;
|
||||
|
||||
emitter_json_dict_begin(emitter, "small");
|
||||
emitter_json_object_kv_begin(emitter, "small");
|
||||
alloc_count_title.str_val = "small:";
|
||||
|
||||
GET_AND_EMIT_ALLOC_STAT(small, allocated, size)
|
||||
@ -747,9 +747,9 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||
GET_AND_EMIT_ALLOC_STAT(small, nrequests, uint64)
|
||||
|
||||
emitter_table_row(emitter, &alloc_count_row);
|
||||
emitter_json_dict_end(emitter); /* Close "small". */
|
||||
emitter_json_object_end(emitter); /* Close "small". */
|
||||
|
||||
emitter_json_dict_begin(emitter, "large");
|
||||
emitter_json_object_kv_begin(emitter, "large");
|
||||
alloc_count_title.str_val = "large:";
|
||||
|
||||
GET_AND_EMIT_ALLOC_STAT(large, allocated, size)
|
||||
@ -758,7 +758,7 @@ stats_arena_print(emitter_t *emitter, unsigned i, bool bins, bool large,
|
||||
GET_AND_EMIT_ALLOC_STAT(large, nrequests, uint64)
|
||||
|
||||
emitter_table_row(emitter, &alloc_count_row);
|
||||
emitter_json_dict_end(emitter); /* Close "large". */
|
||||
emitter_json_object_end(emitter); /* Close "large". */
|
||||
|
||||
#undef GET_AND_EMIT_ALLOC_STAT
|
||||
|
||||
@ -980,7 +980,7 @@ stats_general_print(emitter_t *emitter) {
|
||||
* The json output sticks arena info into an "arenas" dict; the table
|
||||
* output puts them at the top-level.
|
||||
*/
|
||||
emitter_json_dict_begin(emitter, "arenas");
|
||||
emitter_json_object_kv_begin(emitter, "arenas");
|
||||
|
||||
CTL_GET("arenas.narenas", &uv, unsigned);
|
||||
emitter_kv(emitter, "narenas", "Arenas", emitter_type_unsigned, &uv);
|
||||
@ -1021,9 +1021,9 @@ stats_general_print(emitter_t *emitter) {
|
||||
* (not just omit the printing).
|
||||
*/
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_arr_begin(emitter, "bin");
|
||||
emitter_json_array_kv_begin(emitter, "bin");
|
||||
for (unsigned i = 0; i < nbins; i++) {
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_object_begin(emitter);
|
||||
|
||||
CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t);
|
||||
emitter_json_kv(emitter, "size", emitter_type_size,
|
||||
@ -1037,9 +1037,9 @@ stats_general_print(emitter_t *emitter) {
|
||||
emitter_json_kv(emitter, "slab_size", emitter_type_size,
|
||||
&sv);
|
||||
|
||||
emitter_json_arr_obj_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
emitter_json_arr_end(emitter); /* Close "bin". */
|
||||
emitter_json_array_end(emitter); /* Close "bin". */
|
||||
}
|
||||
|
||||
unsigned nlextents;
|
||||
@ -1048,20 +1048,20 @@ stats_general_print(emitter_t *emitter) {
|
||||
emitter_type_unsigned, &nlextents);
|
||||
|
||||
if (emitter->output == emitter_output_json) {
|
||||
emitter_json_arr_begin(emitter, "lextent");
|
||||
emitter_json_array_kv_begin(emitter, "lextent");
|
||||
for (unsigned i = 0; i < nlextents; i++) {
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_object_begin(emitter);
|
||||
|
||||
CTL_M2_GET("arenas.lextent.0.size", i, &sv, size_t);
|
||||
emitter_json_kv(emitter, "size", emitter_type_size,
|
||||
&sv);
|
||||
|
||||
emitter_json_arr_obj_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
emitter_json_arr_end(emitter); /* Close "lextent". */
|
||||
emitter_json_array_end(emitter); /* Close "lextent". */
|
||||
}
|
||||
|
||||
emitter_json_dict_end(emitter); /* Close "arenas" */
|
||||
emitter_json_object_end(emitter); /* Close "arenas" */
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1098,7 +1098,7 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
}
|
||||
|
||||
/* Generic global stats. */
|
||||
emitter_json_dict_begin(emitter, "stats");
|
||||
emitter_json_object_kv_begin(emitter, "stats");
|
||||
emitter_json_kv(emitter, "allocated", emitter_type_size, &allocated);
|
||||
emitter_json_kv(emitter, "active", emitter_type_size, &active);
|
||||
emitter_json_kv(emitter, "metadata", emitter_type_size, &metadata);
|
||||
@ -1114,14 +1114,14 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
resident, mapped, retained);
|
||||
|
||||
/* Background thread stats. */
|
||||
emitter_json_dict_begin(emitter, "background_thread");
|
||||
emitter_json_object_kv_begin(emitter, "background_thread");
|
||||
emitter_json_kv(emitter, "num_threads", emitter_type_size,
|
||||
&num_background_threads);
|
||||
emitter_json_kv(emitter, "num_runs", emitter_type_uint64,
|
||||
&background_thread_num_runs);
|
||||
emitter_json_kv(emitter, "run_interval", emitter_type_uint64,
|
||||
&background_thread_run_interval);
|
||||
emitter_json_dict_end(emitter); /* Close "background_thread". */
|
||||
emitter_json_object_end(emitter); /* Close "background_thread". */
|
||||
|
||||
emitter_table_printf(emitter, "Background threads: %zu, "
|
||||
"num_runs: %"FMTu64", run_interval: %"FMTu64" ns\n",
|
||||
@ -1138,25 +1138,25 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
mutex_stats_init_cols(&row, "", &name, col64, col32);
|
||||
|
||||
emitter_table_row(emitter, &row);
|
||||
emitter_json_dict_begin(emitter, "mutexes");
|
||||
emitter_json_object_kv_begin(emitter, "mutexes");
|
||||
|
||||
for (int i = 0; i < mutex_prof_num_global_mutexes; i++) {
|
||||
mutex_stats_read_global(global_mutex_names[i], &name,
|
||||
col64, col32);
|
||||
emitter_json_dict_begin(emitter, global_mutex_names[i]);
|
||||
emitter_json_object_kv_begin(emitter, global_mutex_names[i]);
|
||||
mutex_stats_emit(emitter, &row, col64, col32);
|
||||
emitter_json_dict_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
|
||||
emitter_json_dict_end(emitter); /* Close "mutexes". */
|
||||
emitter_json_object_end(emitter); /* Close "mutexes". */
|
||||
}
|
||||
|
||||
emitter_json_dict_end(emitter); /* Close "stats". */
|
||||
emitter_json_object_end(emitter); /* Close "stats". */
|
||||
|
||||
if (merged || destroyed || unmerged) {
|
||||
unsigned narenas;
|
||||
|
||||
emitter_json_dict_begin(emitter, "stats.arenas");
|
||||
emitter_json_object_kv_begin(emitter, "stats.arenas");
|
||||
|
||||
CTL_GET("arenas.narenas", &narenas, unsigned);
|
||||
size_t mib[3];
|
||||
@ -1185,10 +1185,10 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
if (merged && (ninitialized > 1 || !unmerged)) {
|
||||
/* Print merged arena stats. */
|
||||
emitter_table_printf(emitter, "Merged arenas stats:\n");
|
||||
emitter_json_dict_begin(emitter, "merged");
|
||||
emitter_json_object_kv_begin(emitter, "merged");
|
||||
stats_arena_print(emitter, MALLCTL_ARENAS_ALL, bins,
|
||||
large, mutex);
|
||||
emitter_json_dict_end(emitter); /* Close "merged". */
|
||||
emitter_json_object_end(emitter); /* Close "merged". */
|
||||
}
|
||||
|
||||
/* Destroyed stats. */
|
||||
@ -1196,10 +1196,10 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
/* Print destroyed arena stats. */
|
||||
emitter_table_printf(emitter,
|
||||
"Destroyed arenas stats:\n");
|
||||
emitter_json_dict_begin(emitter, "destroyed");
|
||||
emitter_json_object_kv_begin(emitter, "destroyed");
|
||||
stats_arena_print(emitter, MALLCTL_ARENAS_DESTROYED,
|
||||
bins, large, mutex);
|
||||
emitter_json_dict_end(emitter); /* Close "destroyed". */
|
||||
emitter_json_object_end(emitter); /* Close "destroyed". */
|
||||
}
|
||||
|
||||
/* Unmerged stats. */
|
||||
@ -1209,18 +1209,18 @@ stats_print_helper(emitter_t *emitter, bool merged, bool destroyed,
|
||||
char arena_ind_str[20];
|
||||
malloc_snprintf(arena_ind_str,
|
||||
sizeof(arena_ind_str), "%u", i);
|
||||
emitter_json_dict_begin(emitter,
|
||||
emitter_json_object_kv_begin(emitter,
|
||||
arena_ind_str);
|
||||
emitter_table_printf(emitter,
|
||||
"arenas[%s]:\n", arena_ind_str);
|
||||
stats_arena_print(emitter, i, bins,
|
||||
large, mutex);
|
||||
/* Close "<arena-ind>". */
|
||||
emitter_json_dict_end(emitter);
|
||||
emitter_json_object_end(emitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
emitter_json_dict_end(emitter); /* Close "stats.arenas". */
|
||||
emitter_json_object_end(emitter); /* Close "stats.arenas". */
|
||||
}
|
||||
}
|
||||
|
||||
@ -1273,7 +1273,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
cbopaque);
|
||||
emitter_begin(&emitter);
|
||||
emitter_table_printf(&emitter, "___ Begin jemalloc statistics ___\n");
|
||||
emitter_json_dict_begin(&emitter, "jemalloc");
|
||||
emitter_json_object_kv_begin(&emitter, "jemalloc");
|
||||
|
||||
if (general) {
|
||||
stats_general_print(&emitter);
|
||||
@ -1283,7 +1283,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
bins, large, mutex);
|
||||
}
|
||||
|
||||
emitter_json_dict_end(&emitter); /* Closes the "jemalloc" dict. */
|
||||
emitter_json_object_end(&emitter); /* Closes the "jemalloc" dict. */
|
||||
emitter_table_printf(&emitter, "--- End jemalloc statistics ---\n");
|
||||
emitter_end(&emitter);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ static void emit_nested_dict(emitter_t *emitter) {
|
||||
emitter_end(emitter);
|
||||
}
|
||||
|
||||
static const char *nested_dict_json =
|
||||
static const char *nested_object_json =
|
||||
"{\n"
|
||||
"\t\"json1\": {\n"
|
||||
"\t\t\"json2\": {\n"
|
||||
@ -183,7 +183,7 @@ static const char *nested_dict_json =
|
||||
"\t}\n"
|
||||
"}\n";
|
||||
|
||||
static const char *nested_dict_table =
|
||||
static const char *nested_object_table =
|
||||
"Dict 1\n"
|
||||
" Dict 2\n"
|
||||
" A primitive: 123\n"
|
||||
@ -192,8 +192,8 @@ static const char *nested_dict_table =
|
||||
" Another primitive: 123\n";
|
||||
|
||||
TEST_BEGIN(test_nested_dict) {
|
||||
assert_emit_output(&emit_nested_dict, nested_dict_json,
|
||||
nested_dict_table);
|
||||
assert_emit_output(&emit_nested_dict, nested_object_json,
|
||||
nested_object_table);
|
||||
}
|
||||
TEST_END
|
||||
|
||||
@ -256,13 +256,14 @@ emit_modal(emitter_t *emitter) {
|
||||
int val = 123;
|
||||
emitter_begin(emitter);
|
||||
emitter_dict_begin(emitter, "j0", "T0");
|
||||
emitter_json_dict_begin(emitter, "j1");
|
||||
emitter_json_key(emitter, "j1");
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_kv(emitter, "i1", "I1", emitter_type_int, &val);
|
||||
emitter_json_kv(emitter, "i2", emitter_type_int, &val);
|
||||
emitter_table_kv(emitter, "I3", emitter_type_int, &val);
|
||||
emitter_table_dict_begin(emitter, "T1");
|
||||
emitter_kv(emitter, "i4", "I4", emitter_type_int, &val);
|
||||
emitter_json_dict_end(emitter); /* Close j1 */
|
||||
emitter_json_object_end(emitter); /* Close j1 */
|
||||
emitter_kv(emitter, "i5", "I5", emitter_type_int, &val);
|
||||
emitter_table_dict_end(emitter); /* Close T1 */
|
||||
emitter_kv(emitter, "i6", "I6", emitter_type_int, &val);
|
||||
@ -302,24 +303,26 @@ emit_json_arr(emitter_t *emitter) {
|
||||
int ival = 123;
|
||||
|
||||
emitter_begin(emitter);
|
||||
emitter_json_dict_begin(emitter, "dict");
|
||||
emitter_json_arr_begin(emitter, "arr");
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_key(emitter, "dict");
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_json_key(emitter, "arr");
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_json_kv(emitter, "foo", emitter_type_int, &ival);
|
||||
emitter_json_arr_obj_end(emitter); /* Close arr[0] */
|
||||
emitter_json_object_end(emitter); /* Close arr[0] */
|
||||
/* arr[1] and arr[2] are primitives. */
|
||||
emitter_json_arr_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_arr_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_arr_obj_begin(emitter);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_object_begin(emitter);
|
||||
emitter_json_kv(emitter, "bar", emitter_type_int, &ival);
|
||||
emitter_json_kv(emitter, "baz", emitter_type_int, &ival);
|
||||
emitter_json_arr_obj_end(emitter); /* Close arr[3]. */
|
||||
emitter_json_arr_end(emitter); /* Close arr. */
|
||||
emitter_json_dict_end(emitter); /* Close dict. */
|
||||
emitter_json_object_end(emitter); /* Close arr[3]. */
|
||||
emitter_json_array_end(emitter); /* Close arr. */
|
||||
emitter_json_object_end(emitter); /* Close dict. */
|
||||
emitter_end(emitter);
|
||||
}
|
||||
|
||||
static const char *json_arr_json =
|
||||
static const char *json_array_json =
|
||||
"{\n"
|
||||
"\t\"dict\": {\n"
|
||||
"\t\t\"arr\": [\n"
|
||||
@ -336,10 +339,62 @@ static const char *json_arr_json =
|
||||
"\t}\n"
|
||||
"}\n";
|
||||
|
||||
static const char *json_arr_table = "";
|
||||
static const char *json_array_table = "";
|
||||
|
||||
TEST_BEGIN(test_json_arr) {
|
||||
assert_emit_output(&emit_json_arr, json_arr_json, json_arr_table);
|
||||
assert_emit_output(&emit_json_arr, json_array_json, json_array_table);
|
||||
}
|
||||
TEST_END
|
||||
|
||||
static void
|
||||
emit_json_nested_array(emitter_t *emitter) {
|
||||
int ival = 123;
|
||||
char *sval = "foo";
|
||||
emitter_begin(emitter);
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_value(emitter, emitter_type_string, &sval);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_value(emitter, emitter_type_string, &sval);
|
||||
emitter_json_array_end(emitter);
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_array_end(emitter);
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_value(emitter, emitter_type_string, &sval);
|
||||
emitter_json_value(emitter, emitter_type_int, &ival);
|
||||
emitter_json_array_end(emitter);
|
||||
emitter_json_array_begin(emitter);
|
||||
emitter_json_array_end(emitter);
|
||||
emitter_json_array_end(emitter);
|
||||
emitter_end(emitter);
|
||||
}
|
||||
|
||||
static const char *json_nested_array_json =
|
||||
"{\n"
|
||||
"\t[\n"
|
||||
"\t\t[\n"
|
||||
"\t\t\t123,\n"
|
||||
"\t\t\t\"foo\",\n"
|
||||
"\t\t\t123,\n"
|
||||
"\t\t\t\"foo\"\n"
|
||||
"\t\t],\n"
|
||||
"\t\t[\n"
|
||||
"\t\t\t123\n"
|
||||
"\t\t],\n"
|
||||
"\t\t[\n"
|
||||
"\t\t\t\"foo\",\n"
|
||||
"\t\t\t123\n"
|
||||
"\t\t],\n"
|
||||
"\t\t[\n"
|
||||
"\t\t]\n"
|
||||
"\t]\n"
|
||||
"}\n";
|
||||
|
||||
TEST_BEGIN(test_json_nested_arr) {
|
||||
assert_emit_output(&emit_json_nested_array, json_nested_array_json,
|
||||
json_array_table);
|
||||
}
|
||||
TEST_END
|
||||
|
||||
@ -409,5 +464,6 @@ main(void) {
|
||||
test_types,
|
||||
test_modal,
|
||||
test_json_arr,
|
||||
test_json_nested_arr,
|
||||
test_table_row);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user