#include "rendering.h" #include #include #include int not_null(const entry_struct *entry, const jsmntok_t *t){ return strncmp("null", entry->json + t->start, min(4, t->end - t->start)) != 0; } inline void append_token(VALUE string, const entry_struct *entry, const jsmntok_t *t){ rb_str_cat(string, entry->json + t->start, t->end - t->start); //TODO: add token sanity checks } void append_entry(VALUE string, const entry_struct *entry){ jsmn_parser parser; jsmn_init(&parser); jsmntok_t t[128]; //TODO: document how many labels we can process int r = jsmn_parse(&parser, entry->json, entry->json_size, t, sizeof(t)/sizeof(t[0])); if (r < 3) { return; //TODO: better handle this case } //TODO: check (r - 4) % 2 == 0 int label_cnt = (r-5)/2; append_token(string, entry, &t[2]); if (label_cnt > 0){ rb_str_cat(string, "{", 1); for(int i = 0; i < label_cnt; i++){ int key = 4 + i; int val = 5 + label_cnt + i; //TODO: add type checks append_token(string, entry, &t[key]); rb_str_cat(string, "=", 1); rb_str_cat(string, "\"", 1); if (not_null(entry, &t[val])){ append_token(string, entry, &t[val]); } rb_str_cat(string, "\"", 1); if (i < label_cnt - 1){ rb_str_cat(string, ",", 1); } } if (is_pid_significant(entry)){ rb_str_cat(string, ",pid=\"", 6); rb_str_append(string, entry->pid); rb_str_cat(string, "\"", 1); } rb_str_cat(string, "}", 1); } char value[255]; //TODO: fix value representation %g doesn't math what Go expects int written = snprintf(value, sizeof(value), " %g\n", entry->value); rb_str_cat(string, value, written); } void append_entry_head(VALUE string, const entry_struct *entry){ static const char help_beg[] = "# HELP "; static const char help_fin[] = " Multiprocess metric\n"; rb_str_cat(string, help_beg, sizeof(help_beg) - 1); rb_str_cat(string, entry->name, entry->name_len); rb_str_cat(string, help_fin, sizeof(help_fin) - 1); static const char type_beg[] = "# TYPE "; rb_str_cat(string, type_beg, sizeof(type_beg) - 1); rb_str_cat(string, entry->name, entry->name_len); rb_str_cat(string, " ", 1); rb_str_cat2(string, rb_id2name(entry->type)); rb_str_cat(string, "\n", 1); } VALUE entries_to_string(entry_struct **sorted_entries, size_t entries_count){ VALUE rv = rb_str_new("", 0); entry_struct *previous = NULL; for(size_t i = 0; i < entries_count; i ++){ entry_struct *entry = sorted_entries[i]; if (!previous || previous->name_len != entry->name_len || strncmp(entry->name, previous->name, entry->name_len) != 0) { previous = entry; append_entry_head(rv, entry); } append_entry(rv, entry); } return rv; }