12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "json_wrapper.h"
- static void jsonwrap_query_metric_plan(BUFFER *wb, QUERY_METRIC *qm) {
- buffer_json_member_add_array(wb, "plans");
- for (size_t p = 0; p < qm->plan.used; p++) {
- QUERY_PLAN_ENTRY *qp = &qm->plan.array[p];
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_uint64(wb, "tr", qp->tier);
- buffer_json_member_add_time_t(wb, "af", qp->after);
- buffer_json_member_add_time_t(wb, "bf", qp->before);
- buffer_json_object_close(wb);
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "tiers");
- for (size_t tier = 0; tier < storage_tiers; tier++) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_uint64(wb, "tr", tier);
- buffer_json_member_add_time_t(wb, "fe", qm->tiers[tier].db_first_time_s);
- buffer_json_member_add_time_t(wb, "le", qm->tiers[tier].db_last_time_s);
- buffer_json_member_add_int64(wb, "wg", qm->tiers[tier].weight);
- buffer_json_object_close(wb);
- }
- buffer_json_array_close(wb);
- }
- void jsonwrap_query_plan(RRDR *r, BUFFER *wb) {
- QUERY_TARGET *qt = r->internal.qt;
- buffer_json_member_add_object(wb, "query_plan");
- for(size_t m = 0; m < qt->query.used; m++) {
- QUERY_METRIC *qm = query_metric(qt, m);
- buffer_json_member_add_object(wb, query_metric_id(qt, qm));
- jsonwrap_query_metric_plan(wb, qm);
- buffer_json_object_close(wb);
- }
- buffer_json_object_close(wb);
- }
- static inline size_t rrdr_dimension_names(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- const size_t dimensions = r->d;
- size_t c, i;
- buffer_json_member_add_array(wb, key);
- for(c = 0, i = 0; c < dimensions ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_string(wb, string2str(r->dn[c]));
- i++;
- }
- buffer_json_array_close(wb);
- return i;
- }
- static inline size_t rrdr_dimension_ids(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- const size_t dimensions = r->d;
- size_t c, i;
- buffer_json_member_add_array(wb, key);
- for(c = 0, i = 0; c < dimensions ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_string(wb, string2str(r->di[c]));
- i++;
- }
- buffer_json_array_close(wb);
- return i;
- }
- static inline long jsonwrap_v1_chart_ids(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- QUERY_TARGET *qt = r->internal.qt;
- const long query_used = qt->query.used;
- long c, i;
- buffer_json_member_add_array(wb, key);
- for (c = 0, i = 0; c < query_used; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- QUERY_METRIC *qm = query_metric(qt, c);
- QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id);
- buffer_json_add_array_item_string(wb, rrdinstance_acquired_id(qi->ria));
- i++;
- }
- buffer_json_array_close(wb);
- return i;
- }
- struct summary_total_counts {
- size_t selected;
- size_t excluded;
- size_t queried;
- size_t failed;
- };
- static inline void aggregate_into_summary_totals(struct summary_total_counts *totals, QUERY_METRICS_COUNTS *metrics) {
- if(unlikely(!totals || !metrics))
- return;
- if(metrics->selected) {
- totals->selected++;
- if(metrics->queried)
- totals->queried++;
- else if(metrics->failed)
- totals->failed++;
- }
- else
- totals->excluded++;
- }
- static inline void query_target_total_counts(BUFFER *wb, const char *key, struct summary_total_counts *totals) {
- if(!totals->selected && !totals->queried && !totals->failed && !totals->excluded)
- return;
- buffer_json_member_add_object(wb, key);
- if(totals->selected)
- buffer_json_member_add_uint64(wb, "sl", totals->selected);
- if(totals->excluded)
- buffer_json_member_add_uint64(wb, "ex", totals->excluded);
- if(totals->queried)
- buffer_json_member_add_uint64(wb, "qr", totals->queried);
- if(totals->failed)
- buffer_json_member_add_uint64(wb, "fl", totals->failed);
- buffer_json_object_close(wb);
- }
- static inline void query_target_metric_counts(BUFFER *wb, QUERY_METRICS_COUNTS *metrics) {
- if(!metrics->selected && !metrics->queried && !metrics->failed && !metrics->excluded)
- return;
- buffer_json_member_add_object(wb, "ds");
- if(metrics->selected)
- buffer_json_member_add_uint64(wb, "sl", metrics->selected);
- if(metrics->excluded)
- buffer_json_member_add_uint64(wb, "ex", metrics->excluded);
- if(metrics->queried)
- buffer_json_member_add_uint64(wb, "qr", metrics->queried);
- if(metrics->failed)
- buffer_json_member_add_uint64(wb, "fl", metrics->failed);
- buffer_json_object_close(wb);
- }
- static inline void query_target_instance_counts(BUFFER *wb, QUERY_INSTANCES_COUNTS *instances) {
- if(!instances->selected && !instances->queried && !instances->failed && !instances->excluded)
- return;
- buffer_json_member_add_object(wb, "is");
- if(instances->selected)
- buffer_json_member_add_uint64(wb, "sl", instances->selected);
- if(instances->excluded)
- buffer_json_member_add_uint64(wb, "ex", instances->excluded);
- if(instances->queried)
- buffer_json_member_add_uint64(wb, "qr", instances->queried);
- if(instances->failed)
- buffer_json_member_add_uint64(wb, "fl", instances->failed);
- buffer_json_object_close(wb);
- }
- static inline void query_target_alerts_counts(BUFFER *wb, QUERY_ALERTS_COUNTS *alerts, const char *name, bool array) {
- if(!alerts->clear && !alerts->other && !alerts->critical && !alerts->warning)
- return;
- if(array)
- buffer_json_add_array_item_object(wb);
- else
- buffer_json_member_add_object(wb, "al");
- if(name)
- buffer_json_member_add_string(wb, "nm", name);
- if(alerts->clear)
- buffer_json_member_add_uint64(wb, "cl", alerts->clear);
- if(alerts->warning)
- buffer_json_member_add_uint64(wb, "wr", alerts->warning);
- if(alerts->critical)
- buffer_json_member_add_uint64(wb, "cr", alerts->critical);
- if(alerts->other)
- buffer_json_member_add_uint64(wb, "ot", alerts->other);
- buffer_json_object_close(wb);
- }
- static inline void query_target_points_statistics(BUFFER *wb, QUERY_TARGET *qt, STORAGE_POINT *sp) {
- if(!sp->count)
- return;
- buffer_json_member_add_object(wb, "sts");
- buffer_json_member_add_double(wb, "min", sp->min);
- buffer_json_member_add_double(wb, "max", sp->max);
- if(query_target_aggregatable(qt)) {
- buffer_json_member_add_uint64(wb, "cnt", sp->count);
- if(sp->sum != 0.0) {
- buffer_json_member_add_double(wb, "sum", sp->sum);
- buffer_json_member_add_double(wb, "vol", sp->sum * (NETDATA_DOUBLE) query_view_update_every(qt));
- }
- if(sp->anomaly_count != 0)
- buffer_json_member_add_double(wb, "ars", storage_point_anomaly_rate(*sp));
- }
- else {
- NETDATA_DOUBLE avg = (sp->count) ? sp->sum / (NETDATA_DOUBLE)sp->count : 0.0;
- if(avg != 0.0)
- buffer_json_member_add_double(wb, "avg", avg);
- NETDATA_DOUBLE arp = storage_point_anomaly_rate(*sp);
- if(arp != 0.0)
- buffer_json_member_add_double(wb, "arp", arp);
- NETDATA_DOUBLE con = (qt->query_points.sum > 0.0) ? sp->sum * 100.0 / qt->query_points.sum : 0.0;
- if(con != 0.0)
- buffer_json_member_add_double(wb, "con", con);
- }
- buffer_json_object_close(wb);
- }
- static void query_target_summary_nodes_v2(BUFFER *wb, QUERY_TARGET *qt, const char *key, struct summary_total_counts *totals) {
- buffer_json_member_add_array(wb, key);
- for (size_t c = 0; c < qt->nodes.used; c++) {
- QUERY_NODE *qn = query_node(qt, c);
- RRDHOST *host = qn->rrdhost;
- buffer_json_add_array_item_object(wb);
- buffer_json_node_add_v2(wb, host, qn->slot, qn->duration_ut);
- query_target_instance_counts(wb, &qn->instances);
- query_target_metric_counts(wb, &qn->metrics);
- query_target_alerts_counts(wb, &qn->alerts, NULL, false);
- query_target_points_statistics(wb, qt, &qn->query_points);
- buffer_json_object_close(wb);
- aggregate_into_summary_totals(totals, &qn->metrics);
- }
- buffer_json_array_close(wb);
- }
- static size_t query_target_summary_contexts_v2(BUFFER *wb, QUERY_TARGET *qt, const char *key, struct summary_total_counts *totals) {
- buffer_json_member_add_array(wb, key);
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- struct {
- STORAGE_POINT query_points;
- QUERY_INSTANCES_COUNTS instances;
- QUERY_METRICS_COUNTS metrics;
- QUERY_ALERTS_COUNTS alerts;
- } *z;
- for (long c = 0; c < (long) qt->contexts.used; c++) {
- QUERY_CONTEXT *qc = query_context(qt, c);
- z = dictionary_set(dict, rrdcontext_acquired_id(qc->rca), NULL, sizeof(*z));
- z->instances.selected += qc->instances.selected;
- z->instances.excluded += qc->instances.selected;
- z->instances.queried += qc->instances.queried;
- z->instances.failed += qc->instances.failed;
- z->metrics.selected += qc->metrics.selected;
- z->metrics.excluded += qc->metrics.excluded;
- z->metrics.queried += qc->metrics.queried;
- z->metrics.failed += qc->metrics.failed;
- z->alerts.clear += qc->alerts.clear;
- z->alerts.warning += qc->alerts.warning;
- z->alerts.critical += qc->alerts.critical;
- storage_point_merge_to(z->query_points, qc->query_points);
- }
- size_t unique_contexts = dictionary_entries(dict);
- dfe_start_read(dict, z) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "id", z_dfe.name);
- query_target_instance_counts(wb, &z->instances);
- query_target_metric_counts(wb, &z->metrics);
- query_target_alerts_counts(wb, &z->alerts, NULL, false);
- query_target_points_statistics(wb, qt, &z->query_points);
- buffer_json_object_close(wb);
- aggregate_into_summary_totals(totals, &z->metrics);
- }
- dfe_done(z);
- buffer_json_array_close(wb);
- dictionary_destroy(dict);
- return unique_contexts;
- }
- static void query_target_summary_instances_v1(BUFFER *wb, QUERY_TARGET *qt, const char *key) {
- char name[RRD_ID_LENGTH_MAX * 2 + 2];
- buffer_json_member_add_array(wb, key);
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- for (long c = 0; c < (long) qt->instances.used; c++) {
- QUERY_INSTANCE *qi = query_instance(qt, c);
- snprintfz(name, RRD_ID_LENGTH_MAX * 2 + 1, "%s:%s",
- rrdinstance_acquired_id(qi->ria),
- rrdinstance_acquired_name(qi->ria));
- bool *set = dictionary_set(dict, name, NULL, sizeof(*set));
- if (!*set) {
- *set = true;
- buffer_json_add_array_item_array(wb);
- buffer_json_add_array_item_string(wb, rrdinstance_acquired_id(qi->ria));
- buffer_json_add_array_item_string(wb, rrdinstance_acquired_name(qi->ria));
- buffer_json_array_close(wb);
- }
- }
- dictionary_destroy(dict);
- buffer_json_array_close(wb);
- }
- static void query_target_summary_instances_v2(BUFFER *wb, QUERY_TARGET *qt, const char *key, struct summary_total_counts *totals) {
- buffer_json_member_add_array(wb, key);
- for (long c = 0; c < (long) qt->instances.used; c++) {
- QUERY_INSTANCE *qi = query_instance(qt, c);
- // QUERY_HOST *qh = query_host(qt, qi->query_host_id);
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "id", rrdinstance_acquired_id(qi->ria));
- if(!rrdinstance_acquired_id_and_name_are_same(qi->ria))
- buffer_json_member_add_string(wb, "nm", rrdinstance_acquired_name(qi->ria));
- buffer_json_member_add_uint64(wb, "ni", qi->query_host_id);
- // buffer_json_member_add_string(wb, "id", string2str(qi->id_fqdn));
- // buffer_json_member_add_string(wb, "nm", string2str(qi->name_fqdn));
- // buffer_json_member_add_string(wb, "lc", rrdinstance_acquired_name(qi->ria));
- // buffer_json_member_add_string(wb, "mg", qh->host->machine_guid);
- // if(qh->node_id[0])
- // buffer_json_member_add_string(wb, "nd", qh->node_id);
- query_target_metric_counts(wb, &qi->metrics);
- query_target_alerts_counts(wb, &qi->alerts, NULL, false);
- query_target_points_statistics(wb, qt, &qi->query_points);
- buffer_json_object_close(wb);
- aggregate_into_summary_totals(totals, &qi->metrics);
- }
- buffer_json_array_close(wb);
- }
- static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, const char *key, bool v2, struct summary_total_counts *totals) {
- char name[RRD_ID_LENGTH_MAX * 2 + 2];
- buffer_json_member_add_array(wb, key);
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- struct {
- const char *id;
- const char *name;
- STORAGE_POINT query_points;
- QUERY_METRICS_COUNTS metrics;
- } *z;
- size_t q = 0;
- for (long c = 0; c < (long) qt->dimensions.used; c++) {
- QUERY_DIMENSION * qd = query_dimension(qt, c);
- RRDMETRIC_ACQUIRED *rma = qd->rma;
- QUERY_METRIC *qm = NULL;
- for( ; q < qt->query.used ;q++) {
- QUERY_METRIC *tqm = query_metric(qt, q);
- QUERY_DIMENSION *tqd = query_dimension(qt, tqm->link.query_dimension_id);
- if(tqd->rma != rma) break;
- qm = tqm;
- }
- if(v2) {
- z = dictionary_set(dict, rrdmetric_acquired_name(rma), NULL, sizeof(*z));
- if(!z->id)
- z->id = rrdmetric_acquired_name(rma);
- if(!z->name)
- z->name = rrdmetric_acquired_name(rma);
- }
- else {
- snprintfz(name, RRD_ID_LENGTH_MAX * 2 + 1, "%s:%s",
- rrdmetric_acquired_id(rma),
- rrdmetric_acquired_name(rma));
- z = dictionary_set(dict, name, NULL, sizeof(*z));
- if (!z->id)
- z->id = rrdmetric_acquired_id(rma);
- if (!z->name)
- z->name = rrdmetric_acquired_name(rma);
- }
- if(qm) {
- z->metrics.selected += (qm->status & RRDR_DIMENSION_SELECTED) ? 1 : 0;
- z->metrics.failed += (qm->status & RRDR_DIMENSION_FAILED) ? 1 : 0;
- if(qm->status & RRDR_DIMENSION_QUERIED) {
- z->metrics.queried++;
- storage_point_merge_to(z->query_points, qm->query_points);
- }
- }
- else
- z->metrics.excluded++;
- }
- dfe_start_read(dict, z) {
- if(v2) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "id", z->id);
- if(z->id != z->name)
- buffer_json_member_add_string(wb, "nm", z->name);
- query_target_metric_counts(wb, &z->metrics);
- query_target_points_statistics(wb, qt, &z->query_points);
- buffer_json_object_close(wb);
- aggregate_into_summary_totals(totals, &z->metrics);
- }
- else {
- buffer_json_add_array_item_array(wb);
- buffer_json_add_array_item_string(wb, z->id);
- buffer_json_add_array_item_string(wb, z->name);
- buffer_json_array_close(wb);
- }
- }
- dfe_done(z);
- dictionary_destroy(dict);
- buffer_json_array_close(wb);
- }
- struct rrdlabels_formatting_v2 {
- DICTIONARY *keys;
- QUERY_INSTANCE *qi;
- bool v2;
- };
- struct rrdlabels_keys_dict_entry {
- const char *name;
- DICTIONARY *values;
- STORAGE_POINT query_points;
- QUERY_METRICS_COUNTS metrics;
- };
- struct rrdlabels_key_value_dict_entry {
- const char *key;
- const char *value;
- STORAGE_POINT query_points;
- QUERY_METRICS_COUNTS metrics;
- };
- static int rrdlabels_formatting_v2(const char *name, const char *value, RRDLABEL_SRC ls __maybe_unused, void *data) {
- struct rrdlabels_formatting_v2 *t = data;
- struct rrdlabels_keys_dict_entry *d = dictionary_set(t->keys, name, NULL, sizeof(*d));
- if(!d->values) {
- d->name = name;
- d->values = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- }
- char n[RRD_ID_LENGTH_MAX * 2 + 2];
- snprintfz(n, RRD_ID_LENGTH_MAX * 2, "%s:%s", name, value);
- struct rrdlabels_key_value_dict_entry *z = dictionary_set(d->values, n, NULL, sizeof(*z));
- if(!z->key) {
- z->key = name;
- z->value = value;
- }
- if(t->v2) {
- QUERY_INSTANCE *qi = t->qi;
- z->metrics.selected += qi->metrics.selected;
- z->metrics.excluded += qi->metrics.excluded;
- z->metrics.queried += qi->metrics.queried;
- z->metrics.failed += qi->metrics.failed;
- d->metrics.selected += qi->metrics.selected;
- d->metrics.excluded += qi->metrics.excluded;
- d->metrics.queried += qi->metrics.queried;
- d->metrics.failed += qi->metrics.failed;
- storage_point_merge_to(z->query_points, qi->query_points);
- storage_point_merge_to(d->query_points, qi->query_points);
- }
- return 1;
- }
- static void query_target_summary_labels_v12(BUFFER *wb, QUERY_TARGET *qt, const char *key, bool v2, struct summary_total_counts *key_totals, struct summary_total_counts *value_totals) {
- buffer_json_member_add_array(wb, key);
- struct rrdlabels_formatting_v2 t = {
- .keys = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE),
- .v2 = v2,
- };
- for (long c = 0; c < (long) qt->instances.used; c++) {
- QUERY_INSTANCE *qi = query_instance(qt, c);
- RRDINSTANCE_ACQUIRED *ria = qi->ria;
- t.qi = qi;
- rrdlabels_walkthrough_read(rrdinstance_acquired_labels(ria), rrdlabels_formatting_v2, &t);
- }
- struct rrdlabels_keys_dict_entry *d;
- dfe_start_read(t.keys, d) {
- if(v2) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "id", d_dfe.name);
- query_target_metric_counts(wb, &d->metrics);
- query_target_points_statistics(wb, qt, &d->query_points);
- aggregate_into_summary_totals(key_totals, &d->metrics);
- buffer_json_member_add_array(wb, "vl");
- }
- struct rrdlabels_key_value_dict_entry *z;
- dfe_start_read(d->values, z){
- if (v2) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "id", z->value);
- query_target_metric_counts(wb, &z->metrics);
- query_target_points_statistics(wb, qt, &z->query_points);
- buffer_json_object_close(wb);
- aggregate_into_summary_totals(value_totals, &z->metrics);
- } else {
- buffer_json_add_array_item_array(wb);
- buffer_json_add_array_item_string(wb, z->key);
- buffer_json_add_array_item_string(wb, z->value);
- buffer_json_array_close(wb);
- }
- }
- dfe_done(z);
- dictionary_destroy(d->values);
- if(v2) {
- buffer_json_array_close(wb);
- buffer_json_object_close(wb);
- }
- }
- dfe_done(d);
- dictionary_destroy(t.keys);
- buffer_json_array_close(wb);
- }
- static void query_target_summary_alerts_v2(BUFFER *wb, QUERY_TARGET *qt, const char *key) {
- buffer_json_member_add_array(wb, key);
- QUERY_ALERTS_COUNTS *z;
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- for (long c = 0; c < (long) qt->instances.used; c++) {
- QUERY_INSTANCE *qi = query_instance(qt, c);
- RRDSET *st = rrdinstance_acquired_rrdset(qi->ria);
- if (st) {
- netdata_rwlock_rdlock(&st->alerts.rwlock);
- if (st->alerts.base) {
- for (RRDCALC *rc = st->alerts.base; rc; rc = rc->next) {
- z = dictionary_set(dict, string2str(rc->name), NULL, sizeof(*z));
- switch(rc->status) {
- case RRDCALC_STATUS_CLEAR:
- z->clear++;
- break;
- case RRDCALC_STATUS_WARNING:
- z->warning++;
- break;
- case RRDCALC_STATUS_CRITICAL:
- z->critical++;
- break;
- default:
- case RRDCALC_STATUS_UNINITIALIZED:
- case RRDCALC_STATUS_UNDEFINED:
- case RRDCALC_STATUS_REMOVED:
- z->other++;
- break;
- }
- }
- }
- netdata_rwlock_unlock(&st->alerts.rwlock);
- }
- }
- dfe_start_read(dict, z)
- query_target_alerts_counts(wb, z, z_dfe.name, true);
- dfe_done(z);
- dictionary_destroy(dict);
- buffer_json_array_close(wb); // alerts
- }
- static inline void query_target_functions(BUFFER *wb, const char *key, RRDR *r) {
- QUERY_TARGET *qt = r->internal.qt;
- const long query_used = qt->query.used;
- DICTIONARY *funcs = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_DONT_OVERWRITE_VALUE);
- RRDINSTANCE_ACQUIRED *ria = NULL;
- for (long c = 0; c < query_used ; c++) {
- QUERY_METRIC *qm = query_metric(qt, c);
- QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id);
- if(qi->ria == ria)
- continue;
- ria = qi->ria;
- chart_functions_to_dict(rrdinstance_acquired_functions(ria), funcs);
- }
- buffer_json_member_add_array(wb, key);
- void *t; (void)t;
- dfe_start_read(funcs, t)
- buffer_json_add_array_item_string(wb, t_dfe.name);
- dfe_done(t);
- dictionary_destroy(funcs);
- buffer_json_array_close(wb);
- }
- static inline long query_target_chart_labels_filter_v1(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- QUERY_TARGET *qt = r->internal.qt;
- const long query_used = qt->query.used;
- long c, i = 0;
- buffer_json_member_add_object(wb, key);
- SIMPLE_PATTERN *pattern = qt->instances.chart_label_key_pattern;
- char *label_key = NULL;
- while (pattern && (label_key = simple_pattern_iterate(&pattern))) {
- buffer_json_member_add_array(wb, label_key);
- for (c = 0, i = 0; c < query_used; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- QUERY_METRIC *qm = query_metric(qt, c);
- QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id);
- rrdlabels_value_to_buffer_array_item_or_null(rrdinstance_acquired_labels(qi->ria), wb, label_key);
- i++;
- }
- buffer_json_array_close(wb);
- }
- buffer_json_object_close(wb);
- return i;
- }
- static inline long query_target_metrics_latest_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- QUERY_TARGET *qt = r->internal.qt;
- const long query_used = qt->query.used;
- long c, i;
- buffer_json_member_add_array(wb, key);
- for(c = 0, i = 0; c < query_used ;c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- QUERY_METRIC *qm = query_metric(qt, c);
- QUERY_DIMENSION *qd = query_dimension(qt, qm->link.query_dimension_id);
- buffer_json_add_array_item_double(wb, rrdmetric_acquired_last_stored_value(qd->rma));
- i++;
- }
- buffer_json_array_close(wb);
- return i;
- }
- static inline size_t rrdr_dimension_view_latest_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- buffer_json_member_add_array(wb, key);
- size_t c, i;
- for(c = 0, i = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- i++;
- NETDATA_DOUBLE *cn = &r->v[ (rrdr_rows(r) - 1) * r->d ];
- RRDR_VALUE_FLAGS *co = &r->o[ (rrdr_rows(r) - 1) * r->d ];
- NETDATA_DOUBLE n = cn[c];
- if(co[c] & RRDR_VALUE_EMPTY) {
- if(options & RRDR_OPTION_NULL2ZERO)
- buffer_json_add_array_item_double(wb, 0.0);
- else
- buffer_json_add_array_item_double(wb, NAN);
- }
- else
- buffer_json_add_array_item_double(wb, n);
- }
- buffer_json_array_close(wb);
- return i;
- }
- static inline void rrdr_dimension_query_points_statistics(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options, bool dview) {
- STORAGE_POINT *sp = (dview) ? r->dview : r->dqp;
- NETDATA_DOUBLE anomaly_rate_multiplier = (dview) ? RRDR_DVIEW_ANOMALY_COUNT_MULTIPLIER : 1.0;
- if(unlikely(!sp))
- return;
- if(key)
- buffer_json_member_add_object(wb, key);
- buffer_json_member_add_array(wb, "min");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_double(wb, sp[c].min);
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "max");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_double(wb, sp[c].max);
- }
- buffer_json_array_close(wb);
- if(options & RRDR_OPTION_RETURN_RAW) {
- buffer_json_member_add_array(wb, "sum");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_double(wb, sp[c].sum);
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "cnt");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_uint64(wb, sp[c].count);
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "ars");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_uint64(wb, sp[c].anomaly_count * 100 / anomaly_rate_multiplier);
- }
- buffer_json_array_close(wb);
- }
- else {
- NETDATA_DOUBLE sum = 0.0;
- for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- sum += ABS(sp[c].sum);
- }
- buffer_json_member_add_array(wb, "avg");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_double(wb, storage_point_average_value(sp[c]));
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "arp");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_double(wb, storage_point_anomaly_rate(sp[c]) / anomaly_rate_multiplier);
- }
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "con");
- for(size_t c = 0; c < r->d ; c++) {
- if (!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- NETDATA_DOUBLE con = (sum > 0.0) ? ABS(sp[c].sum) * 100.0 / sum : 0.0;
- buffer_json_add_array_item_double(wb, con);
- }
- buffer_json_array_close(wb);
- }
- if(key)
- buffer_json_object_close(wb);
- }
- static void rrdr_timings_v12(BUFFER *wb, const char *key, RRDR *r) {
- QUERY_TARGET *qt = r->internal.qt;
- qt->timings.finished_ut = now_monotonic_usec();
- buffer_json_member_add_object(wb, key);
- buffer_json_member_add_double(wb, "prep_ms", (NETDATA_DOUBLE)(qt->timings.preprocessed_ut - qt->timings.received_ut) / USEC_PER_MS);
- buffer_json_member_add_double(wb, "query_ms", (NETDATA_DOUBLE)(qt->timings.executed_ut - qt->timings.preprocessed_ut) / USEC_PER_MS);
- buffer_json_member_add_double(wb, "output_ms", (NETDATA_DOUBLE)(qt->timings.finished_ut - qt->timings.executed_ut) / USEC_PER_MS);
- buffer_json_member_add_double(wb, "total_ms", (NETDATA_DOUBLE)(qt->timings.finished_ut - qt->timings.received_ut) / USEC_PER_MS);
- buffer_json_object_close(wb);
- }
- void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb) {
- QUERY_TARGET *qt = r->internal.qt;
- DATASOURCE_FORMAT format = qt->request.format;
- RRDR_OPTIONS options = qt->window.options;
- long rows = rrdr_rows(r);
- char kq[2] = "", // key quote
- sq[2] = ""; // string quote
- if( options & RRDR_OPTION_GOOGLE_JSON ) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- else {
- kq[0] = '"';
- sq[0] = '"';
- }
- buffer_json_initialize(wb, kq, sq, 0, true, options & RRDR_OPTION_MINIFY);
- buffer_json_member_add_uint64(wb, "api", 1);
- buffer_json_member_add_string(wb, "id", qt->id);
- buffer_json_member_add_string(wb, "name", qt->id);
- buffer_json_member_add_time_t(wb, "view_update_every", r->view.update_every);
- buffer_json_member_add_time_t(wb, "update_every", qt->db.minimum_latest_update_every_s);
- buffer_json_member_add_time_t(wb, "first_entry", qt->db.first_time_s);
- buffer_json_member_add_time_t(wb, "last_entry", qt->db.last_time_s);
- buffer_json_member_add_time_t(wb, "after", r->view.after);
- buffer_json_member_add_time_t(wb, "before", r->view.before);
- buffer_json_member_add_string(wb, "group", time_grouping_tostring(qt->request.time_group_method));
- web_client_api_request_v1_data_options_to_buffer_json_array(wb, "options", options);
- if(!rrdr_dimension_names(wb, "dimension_names", r, options))
- rows = 0;
- if(!rrdr_dimension_ids(wb, "dimension_ids", r, options))
- rows = 0;
- if (options & RRDR_OPTION_ALL_DIMENSIONS) {
- query_target_summary_instances_v1(wb, qt, "full_chart_list");
- query_target_summary_dimensions_v12(wb, qt, "full_dimension_list", false, NULL);
- query_target_summary_labels_v12(wb, qt, "full_chart_labels", false, NULL, NULL);
- }
- query_target_functions(wb, "functions", r);
- if (!qt->request.st && !jsonwrap_v1_chart_ids(wb, "chart_ids", r, options))
- rows = 0;
- if (qt->instances.chart_label_key_pattern && !query_target_chart_labels_filter_v1(wb, "chart_labels", r, options))
- rows = 0;
- if(!query_target_metrics_latest_values(wb, "latest_values", r, options))
- rows = 0;
- size_t dimensions = rrdr_dimension_view_latest_values(wb, "view_latest_values", r, options);
- if(!dimensions)
- rows = 0;
- buffer_json_member_add_uint64(wb, "dimensions", dimensions);
- buffer_json_member_add_uint64(wb, "points", rows);
- buffer_json_member_add_string(wb, "format", rrdr_format_to_string(format));
- buffer_json_member_add_array(wb, "db_points_per_tier");
- for(size_t tier = 0; tier < storage_tiers ; tier++)
- buffer_json_add_array_item_uint64(wb, qt->db.tiers[tier].points);
- buffer_json_array_close(wb);
- if(options & RRDR_OPTION_DEBUG)
- jsonwrap_query_plan(r, wb);
- }
- static void rrdset_rrdcalc_entries_v2(BUFFER *wb, RRDINSTANCE_ACQUIRED *ria) {
- RRDSET *st = rrdinstance_acquired_rrdset(ria);
- if(st) {
- netdata_rwlock_rdlock(&st->alerts.rwlock);
- if(st->alerts.base) {
- buffer_json_member_add_object(wb, "alerts");
- for(RRDCALC *rc = st->alerts.base; rc ;rc = rc->next) {
- if(rc->status < RRDCALC_STATUS_CLEAR)
- continue;
- buffer_json_member_add_object(wb, string2str(rc->name));
- buffer_json_member_add_string(wb, "st", rrdcalc_status2string(rc->status));
- buffer_json_member_add_double(wb, "vl", rc->value);
- buffer_json_member_add_string(wb, "un", string2str(rc->units));
- buffer_json_object_close(wb);
- }
- buffer_json_object_close(wb);
- }
- netdata_rwlock_unlock(&st->alerts.rwlock);
- }
- }
- static void query_target_combined_units_v2(BUFFER *wb, QUERY_TARGET *qt, size_t contexts) {
- if(query_target_has_percentage_units(qt)) {
- buffer_json_member_add_string(wb, "units", "%");
- }
- else if(contexts == 1) {
- buffer_json_member_add_string(wb, "units", rrdcontext_acquired_units(qt->contexts.array[0].rca));
- }
- else if(contexts > 1) {
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- for(size_t c = 0; c < qt->contexts.used ;c++)
- dictionary_set(dict, rrdcontext_acquired_units(qt->contexts.array[c].rca), NULL, 0);
- if(dictionary_entries(dict) == 1)
- buffer_json_member_add_string(wb, "units", rrdcontext_acquired_units(qt->contexts.array[0].rca));
- else {
- buffer_json_member_add_array(wb, "units");
- const char *s;
- dfe_start_read(dict, s)
- buffer_json_add_array_item_string(wb, s_dfe.name);
- dfe_done(s);
- buffer_json_array_close(wb);
- }
- dictionary_destroy(dict);
- }
- }
- static void query_target_combined_chart_type(BUFFER *wb, QUERY_TARGET *qt, size_t contexts) {
- if(contexts >= 1)
- buffer_json_member_add_string(wb, "chart_type", rrdset_type_name(rrdcontext_acquired_chart_type(qt->contexts.array[0].rca)));
- }
- static void rrdr_grouped_by_array_v2(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options __maybe_unused) {
- QUERY_TARGET *qt = r->internal.qt;
- buffer_json_member_add_array(wb, key);
- if(qt->request.group_by & RRDR_GROUP_BY_SELECTED)
- buffer_json_add_array_item_string(wb, "selected");
- else {
- if(qt->request.group_by & RRDR_GROUP_BY_DIMENSION)
- buffer_json_add_array_item_string(wb, "dimension");
- if(qt->request.group_by & RRDR_GROUP_BY_INSTANCE)
- buffer_json_add_array_item_string(wb, "instance");
- if(qt->request.group_by & RRDR_GROUP_BY_LABEL) {
- BUFFER *b = buffer_create(0, NULL);
- for (size_t l = 0; l < qt->group_by.used; l++) {
- buffer_flush(b);
- buffer_fast_strcat(b, "label:", 6);
- buffer_strcat(b, qt->group_by.label_keys[l]);
- buffer_json_add_array_item_string(wb, buffer_tostring(b));
- }
- buffer_free(b);
- }
- if(qt->request.group_by & RRDR_GROUP_BY_NODE)
- buffer_json_add_array_item_string(wb, "node");
- if(qt->request.group_by & RRDR_GROUP_BY_CONTEXT)
- buffer_json_add_array_item_string(wb, "context");
- if(qt->request.group_by & RRDR_GROUP_BY_UNITS)
- buffer_json_add_array_item_string(wb, "units");
- }
- buffer_json_array_close(wb); // group_by_order
- }
- static void rrdr_dimension_units_array_v2(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->du)
- return;
- bool percentage = query_target_has_percentage_units(r->internal.qt);
- buffer_json_member_add_array(wb, key);
- for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- if(percentage)
- buffer_json_add_array_item_string(wb, "%");
- else
- buffer_json_add_array_item_string(wb, string2str(r->du[c]));
- }
- buffer_json_array_close(wb);
- }
- static void rrdr_dimension_priority_array_v2(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->dp)
- return;
- buffer_json_member_add_array(wb, key);
- for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_uint64(wb, r->dp[c]);
- }
- buffer_json_array_close(wb);
- }
- static void rrdr_dimension_aggregated_array_v2(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->dgbc)
- return;
- buffer_json_member_add_array(wb, key);
- for(size_t c = 0; c < r->d ;c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
- buffer_json_add_array_item_uint64(wb, r->dgbc[c]);
- }
- buffer_json_array_close(wb);
- }
- static void query_target_title(BUFFER *wb, QUERY_TARGET *qt, size_t contexts) {
- if(contexts == 1) {
- buffer_json_member_add_string(wb, "title", rrdcontext_acquired_title(qt->contexts.array[0].rca));
- }
- else if(contexts > 1) {
- BUFFER *t = buffer_create(0, NULL);
- DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
- buffer_strcat(t, "Chart for contexts: ");
- size_t added = 0;
- for(size_t c = 0; c < qt->contexts.used ;c++) {
- bool *set = dictionary_set(dict, rrdcontext_acquired_id(qt->contexts.array[c].rca), NULL, sizeof(*set));
- if(!*set) {
- *set = true;
- if(added)
- buffer_fast_strcat(t, ", ", 2);
- buffer_strcat(t, rrdcontext_acquired_id(qt->contexts.array[c].rca));
- added++;
- }
- }
- buffer_json_member_add_string(wb, "title", buffer_tostring(t));
- dictionary_destroy(dict);
- buffer_free(t);
- }
- }
- static void query_target_detailed_objects_tree(BUFFER *wb, RRDR *r, RRDR_OPTIONS options) {
- QUERY_TARGET *qt = r->internal.qt;
- buffer_json_member_add_object(wb, "nodes");
- time_t now_s = now_realtime_sec();
- RRDHOST *last_host = NULL;
- RRDCONTEXT_ACQUIRED *last_rca = NULL;
- RRDINSTANCE_ACQUIRED *last_ria = NULL;
- size_t h = 0, c = 0, i = 0, m = 0, q = 0;
- for(; h < qt->nodes.used ; h++) {
- QUERY_NODE *qn = query_node(qt, h);
- RRDHOST *host = qn->rrdhost;
- for( ;c < qt->contexts.used ;c++) {
- QUERY_CONTEXT *qc = query_context(qt, c);
- RRDCONTEXT_ACQUIRED *rca = qc->rca;
- if(!rrdcontext_acquired_belongs_to_host(rca, host)) break;
- for( ;i < qt->instances.used ;i++) {
- QUERY_INSTANCE *qi = query_instance(qt, i);
- RRDINSTANCE_ACQUIRED *ria = qi->ria;
- if(!rrdinstance_acquired_belongs_to_context(ria, rca)) break;
- for( ; m < qt->dimensions.used ; m++) {
- QUERY_DIMENSION *qd = query_dimension(qt, m);
- RRDMETRIC_ACQUIRED *rma = qd->rma;
- if(!rrdmetric_acquired_belongs_to_instance(rma, ria)) break;
- QUERY_METRIC *qm = NULL;
- bool queried = false;
- for( ; q < qt->query.used ;q++) {
- QUERY_METRIC *tqm = query_metric(qt, q);
- QUERY_DIMENSION *tqd = query_dimension(qt, tqm->link.query_dimension_id);
- if(tqd->rma != rma) break;
- queried = tqm->status & RRDR_DIMENSION_QUERIED;
- qm = tqm;
- }
- if(!queried & !(options & RRDR_OPTION_ALL_DIMENSIONS))
- continue;
- if(host != last_host) {
- if(last_host) {
- if(last_rca) {
- if(last_ria) {
- buffer_json_object_close(wb); // dimensions
- buffer_json_object_close(wb); // instance
- last_ria = NULL;
- }
- buffer_json_object_close(wb); // instances
- buffer_json_object_close(wb); // context
- last_rca = NULL;
- }
- buffer_json_object_close(wb); // contexts
- buffer_json_object_close(wb); // host
- last_host = NULL;
- }
- buffer_json_member_add_object(wb, host->machine_guid);
- if(qn->node_id[0])
- buffer_json_member_add_string(wb, "nd", qn->node_id);
- buffer_json_member_add_uint64(wb, "ni", qn->slot);
- buffer_json_member_add_string(wb, "nm", rrdhost_hostname(host));
- buffer_json_member_add_object(wb, "contexts");
- last_host = host;
- }
- if(rca != last_rca) {
- if(last_rca) {
- if(last_ria) {
- buffer_json_object_close(wb); // dimensions
- buffer_json_object_close(wb); // instance
- last_ria = NULL;
- }
- buffer_json_object_close(wb); // instances
- buffer_json_object_close(wb); // context
- last_rca = NULL;
- }
- buffer_json_member_add_object(wb, rrdcontext_acquired_id(rca));
- buffer_json_member_add_object(wb, "instances");
- last_rca = rca;
- }
- if(ria != last_ria) {
- if(last_ria) {
- buffer_json_object_close(wb); // dimensions
- buffer_json_object_close(wb); // instance
- last_ria = NULL;
- }
- buffer_json_member_add_object(wb, rrdinstance_acquired_id(ria));
- buffer_json_member_add_string(wb, "nm", rrdinstance_acquired_name(ria));
- buffer_json_member_add_time_t(wb, "ue", rrdinstance_acquired_update_every(ria));
- DICTIONARY *labels = rrdinstance_acquired_labels(ria);
- if(labels) {
- buffer_json_member_add_object(wb, "labels");
- rrdlabels_to_buffer_json_members(labels, wb);
- buffer_json_object_close(wb);
- }
- rrdset_rrdcalc_entries_v2(wb, ria);
- buffer_json_member_add_object(wb, "dimensions");
- last_ria = ria;
- }
- buffer_json_member_add_object(wb, rrdmetric_acquired_id(rma));
- {
- buffer_json_member_add_string(wb, "nm", rrdmetric_acquired_name(rma));
- buffer_json_member_add_uint64(wb, "qr", queried ? 1 : 0);
- time_t first_entry_s = rrdmetric_acquired_first_entry(rma);
- time_t last_entry_s = rrdmetric_acquired_last_entry(rma);
- buffer_json_member_add_time_t(wb, "fe", first_entry_s);
- buffer_json_member_add_time_t(wb, "le", last_entry_s ? last_entry_s : now_s);
- if(qm) {
- if(qm->status & RRDR_DIMENSION_GROUPED) {
- // buffer_json_member_add_string(wb, "grouped_as_id", string2str(qm->grouped_as.id));
- buffer_json_member_add_string(wb, "as", string2str(qm->grouped_as.name));
- }
- query_target_points_statistics(wb, qt, &qm->query_points);
- if(options & RRDR_OPTION_DEBUG)
- jsonwrap_query_metric_plan(wb, qm);
- }
- }
- buffer_json_object_close(wb); // metric
- }
- }
- }
- }
- if(last_host) {
- if(last_rca) {
- if(last_ria) {
- buffer_json_object_close(wb); // dimensions
- buffer_json_object_close(wb); // instance
- last_ria = NULL;
- }
- buffer_json_object_close(wb); // instances
- buffer_json_object_close(wb); // context
- last_rca = NULL;
- }
- buffer_json_object_close(wb); // contexts
- buffer_json_object_close(wb); // host
- last_host = NULL;
- }
- buffer_json_object_close(wb); // hosts
- }
- void version_hashes_api_v2(BUFFER *wb, struct query_versions *versions) {
- buffer_json_member_add_object(wb, "versions");
- buffer_json_member_add_uint64(wb, "nodes_hard_hash", dictionary_version(rrdhost_root_index));
- buffer_json_member_add_uint64(wb, "contexts_hard_hash", versions->contexts_hard_hash);
- buffer_json_member_add_uint64(wb, "contexts_soft_hash", versions->contexts_soft_hash);
- buffer_json_member_add_uint64(wb, "alerts_hard_hash", versions->alerts_hard_hash);
- buffer_json_member_add_uint64(wb, "alerts_soft_hash", versions->alerts_soft_hash);
- buffer_json_object_close(wb);
- }
- void rrdr_json_wrapper_begin2(RRDR *r, BUFFER *wb) {
- QUERY_TARGET *qt = r->internal.qt;
- RRDR_OPTIONS options = qt->window.options;
- char kq[2] = "\"", // key quote
- sq[2] = "\""; // string quote
- if(unlikely(options & RRDR_OPTION_GOOGLE_JSON)) {
- kq[0] = '\0';
- sq[0] = '\'';
- }
- buffer_json_initialize(wb, kq, sq, 0, true, options & RRDR_OPTION_MINIFY);
- buffer_json_member_add_uint64(wb, "api", 2);
- buffer_json_agents_array_v2(wb, 0);
- if(options & RRDR_OPTION_DEBUG) {
- buffer_json_member_add_string(wb, "id", qt->id);
- buffer_json_member_add_object(wb, "request");
- {
- buffer_json_member_add_string(wb, "format", rrdr_format_to_string(qt->request.format));
- web_client_api_request_v1_data_options_to_buffer_json_array(wb, "options", qt->request.options);
- buffer_json_member_add_object(wb, "scope");
- buffer_json_member_add_string(wb, "scope_nodes", qt->request.scope_nodes);
- buffer_json_member_add_string(wb, "scope_contexts", qt->request.scope_contexts);
- buffer_json_object_close(wb); // scope
- buffer_json_member_add_object(wb, "selectors");
- if (qt->request.host)
- buffer_json_member_add_string(wb, "nodes", rrdhost_hostname(qt->request.host));
- else
- buffer_json_member_add_string(wb, "nodes", qt->request.nodes);
- buffer_json_member_add_string(wb, "contexts", qt->request.contexts);
- buffer_json_member_add_string(wb, "instances", qt->request.instances);
- buffer_json_member_add_string(wb, "dimensions", qt->request.dimensions);
- buffer_json_member_add_string(wb, "labels", qt->request.labels);
- buffer_json_member_add_string(wb, "alerts", qt->request.alerts);
- buffer_json_object_close(wb); // selectors
- buffer_json_member_add_object(wb, "window");
- buffer_json_member_add_time_t(wb, "after", qt->request.after);
- buffer_json_member_add_time_t(wb, "before", qt->request.before);
- buffer_json_member_add_uint64(wb, "points", qt->request.points);
- if (qt->request.options & RRDR_OPTION_SELECTED_TIER)
- buffer_json_member_add_uint64(wb, "tier", qt->request.tier);
- else
- buffer_json_member_add_string(wb, "tier", NULL);
- buffer_json_object_close(wb); // window
- buffer_json_member_add_object(wb, "aggregations");
- {
- buffer_json_member_add_object(wb, "time");
- buffer_json_member_add_string(wb, "time_group", time_grouping_tostring(qt->request.time_group_method));
- buffer_json_member_add_string(wb, "time_group_options", qt->request.time_group_options);
- if (qt->request.resampling_time > 0)
- buffer_json_member_add_time_t(wb, "time_resampling", qt->request.resampling_time);
- else
- buffer_json_member_add_string(wb, "time_resampling", NULL);
- buffer_json_object_close(wb); // time
- buffer_json_member_add_object(wb, "metrics");
- buffer_json_member_add_array(wb, "group_by");
- buffer_json_group_by_to_array(wb, qt->request.group_by);
- buffer_json_array_close(wb);
- buffer_json_member_add_array(wb, "group_by_label");
- for(size_t l = 0; l < qt->group_by.used ;l++)
- buffer_json_add_array_item_string(wb, qt->group_by.label_keys[l]);
- buffer_json_array_close(wb);
- buffer_json_member_add_string(wb, "aggregation",
- group_by_aggregate_function_to_string(
- qt->request.group_by_aggregate_function));
- buffer_json_object_close(wb); // dimensions
- }
- buffer_json_object_close(wb); // aggregations
- buffer_json_member_add_uint64(wb, "timeout", qt->request.timeout_ms);
- }
- buffer_json_object_close(wb); // request
- }
- version_hashes_api_v2(wb, &qt->versions);
- buffer_json_member_add_object(wb, "summary");
- struct summary_total_counts
- nodes_totals = { 0 },
- contexts_totals = { 0 },
- instances_totals = { 0 },
- metrics_totals = { 0 },
- label_key_totals = { 0 },
- label_key_value_totals = { 0 };
- {
- query_target_summary_nodes_v2(wb, qt, "nodes", &nodes_totals);
- r->internal.contexts = query_target_summary_contexts_v2(wb, qt, "contexts", &contexts_totals);
- query_target_summary_instances_v2(wb, qt, "instances", &instances_totals);
- query_target_summary_dimensions_v12(wb, qt, "dimensions", true, &metrics_totals);
- query_target_summary_labels_v12(wb, qt, "labels", true, &label_key_totals, &label_key_value_totals);
- query_target_summary_alerts_v2(wb, qt, "alerts");
- }
- buffer_json_object_close(wb); // summary
- buffer_json_member_add_object(wb, "totals");
- query_target_total_counts(wb, "nodes", &nodes_totals);
- query_target_total_counts(wb, "contexts", &contexts_totals);
- query_target_total_counts(wb, "instances", &instances_totals);
- query_target_total_counts(wb, "dimensions", &metrics_totals);
- query_target_total_counts(wb, "label_keys", &label_key_totals);
- query_target_total_counts(wb, "label_key_values", &label_key_value_totals);
- buffer_json_object_close(wb); // totals
- if(options & RRDR_OPTION_SHOW_DETAILS) {
- buffer_json_member_add_object(wb, "detailed");
- query_target_detailed_objects_tree(wb, r, options);
- buffer_json_object_close(wb); // detailed
- }
- query_target_functions(wb, "functions", r);
- buffer_json_member_add_object(wb, "db");
- {
- buffer_json_member_add_uint64(wb, "tiers", storage_tiers);
- buffer_json_member_add_time_t(wb, "update_every", qt->db.minimum_latest_update_every_s);
- buffer_json_member_add_time_t(wb, "first_entry", qt->db.first_time_s);
- buffer_json_member_add_time_t(wb, "last_entry", qt->db.last_time_s);
- buffer_json_member_add_array(wb, "per_tier");
- for(size_t tier = 0; tier < storage_tiers ; tier++) {
- buffer_json_add_array_item_object(wb);
- buffer_json_member_add_uint64(wb, "tier", tier);
- buffer_json_member_add_uint64(wb, "queries", qt->db.tiers[tier].queries);
- buffer_json_member_add_uint64(wb, "points", qt->db.tiers[tier].points);
- buffer_json_member_add_time_t(wb, "update_every", qt->db.tiers[tier].update_every);
- buffer_json_member_add_time_t(wb, "first_entry", qt->db.tiers[tier].retention.first_time_s);
- buffer_json_member_add_time_t(wb, "last_entry", qt->db.tiers[tier].retention.last_time_s);
- buffer_json_object_close(wb);
- }
- buffer_json_array_close(wb);
- }
- buffer_json_object_close(wb);
- }
- //static void annotations_range_for_value_flags(RRDR *r, BUFFER *wb, DATASOURCE_FORMAT format __maybe_unused, RRDR_OPTIONS options, RRDR_VALUE_FLAGS flags, const char *type) {
- // const size_t dims = r->d, rows = r->rows;
- // size_t next_d_idx = 0;
- // for(size_t d = 0; d < dims ; d++) {
- // if(!rrdr_dimension_should_be_exposed(r->od[d], options))
- // continue;
- //
- // size_t d_idx = next_d_idx++;
- //
- // size_t t = 0;
- // while(t < rows) {
- //
- // // find the beginning
- // time_t started = 0;
- // for(; t < rows ;t++) {
- // RRDR_VALUE_FLAGS o = r->o[t * r->d + d];
- // if(o & flags) {
- // started = r->t[t];
- // break;
- // }
- // }
- //
- // if(started) {
- // time_t ended = 0;
- // for(; t < rows ;t++) {
- // RRDR_VALUE_FLAGS o = r->o[t * r->d + d];
- // if(!(o & flags)) {
- // ended = r->t[t];
- // break;
- // }
- // }
- //
- // if(!ended)
- // ended = r->t[rows - 1];
- //
- // buffer_json_add_array_item_object(wb);
- // buffer_json_member_add_string(wb, "t", type);
- // // buffer_json_member_add_string(wb, "d", string2str(r->dn[d]));
- // buffer_json_member_add_uint64(wb, "d", d_idx);
- // if(started == ended) {
- // if(options & RRDR_OPTION_MILLISECONDS)
- // buffer_json_member_add_time_t2ms(wb, "x", started);
- // else
- // buffer_json_member_add_time_t(wb, "x", started);
- // }
- // else {
- // buffer_json_member_add_array(wb, "x");
- // if(options & RRDR_OPTION_MILLISECONDS) {
- // buffer_json_add_array_item_time_t2ms(wb, started);
- // buffer_json_add_array_item_time_t2ms(wb, ended);
- // }
- // else {
- // buffer_json_add_array_item_time_t(wb, started);
- // buffer_json_add_array_item_time_t(wb, ended);
- // }
- // buffer_json_array_close(wb);
- // }
- // buffer_json_object_close(wb);
- // }
- // }
- // }
- //}
- //
- //void rrdr_json_wrapper_annotations(RRDR *r, BUFFER *wb, DATASOURCE_FORMAT format __maybe_unused, RRDR_OPTIONS options) {
- // buffer_json_member_add_array(wb, "annotations");
- //
- // annotations_range_for_value_flags(r, wb, format, options, RRDR_VALUE_EMPTY, "G"); // Gap
- // annotations_range_for_value_flags(r, wb, format, options, RRDR_VALUE_RESET, "O"); // Overflow
- // annotations_range_for_value_flags(r, wb, format, options, RRDR_VALUE_PARTIAL, "P"); // Partial
- //
- // buffer_json_array_close(wb); // annotations
- //}
- void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb) {
- buffer_json_member_add_double(wb, "min", r->view.min);
- buffer_json_member_add_double(wb, "max", r->view.max);
- rrdr_timings_v12(wb, "timings", r);
- buffer_json_finalize(wb);
- }
- void rrdr_json_wrapper_end2(RRDR *r, BUFFER *wb) {
- QUERY_TARGET *qt = r->internal.qt;
- DATASOURCE_FORMAT format = qt->request.format;
- RRDR_OPTIONS options = qt->window.options;
- buffer_json_member_add_object(wb, "view");
- {
- query_target_title(wb, qt, r->internal.contexts);
- buffer_json_member_add_time_t(wb, "update_every", r->view.update_every);
- buffer_json_member_add_time_t(wb, "after", r->view.after);
- buffer_json_member_add_time_t(wb, "before", r->view.before);
- if(options & RRDR_OPTION_DEBUG) {
- buffer_json_member_add_string(wb, "format", rrdr_format_to_string(format));
- web_client_api_request_v1_data_options_to_buffer_json_array(wb, "options", options);
- buffer_json_member_add_string(wb, "time_group", time_grouping_tostring(qt->request.time_group_method));
- }
- if(options & RRDR_OPTION_DEBUG) {
- buffer_json_member_add_object(wb, "partial_data_trimming");
- buffer_json_member_add_time_t(wb, "max_update_every", r->partial_data_trimming.max_update_every);
- buffer_json_member_add_time_t(wb, "expected_after", r->partial_data_trimming.expected_after);
- buffer_json_member_add_time_t(wb, "trimmed_after", r->partial_data_trimming.trimmed_after);
- buffer_json_object_close(wb);
- }
- if(options & RRDR_OPTION_RETURN_RAW)
- buffer_json_member_add_uint64(wb, "points", rrdr_rows(r));
- query_target_combined_units_v2(wb, qt, r->internal.contexts);
- query_target_combined_chart_type(wb, qt, r->internal.contexts);
- buffer_json_member_add_object(wb, "dimensions");
- {
- rrdr_grouped_by_array_v2(wb, "grouped_by", r, options);
- rrdr_dimension_ids(wb, "ids", r, options);
- rrdr_dimension_names(wb, "names", r, options);
- rrdr_dimension_units_array_v2(wb, "units", r, options);
- rrdr_dimension_priority_array_v2(wb, "priorities", r, options);
- rrdr_dimension_aggregated_array_v2(wb, "aggregated", r, options);
- rrdr_dimension_query_points_statistics(wb, NULL, r, options, true);
- rrdr_dimension_query_points_statistics(wb, "sts", r, options, false);
- rrdr_json_group_by_labels(wb, "labels", r, options);
- }
- buffer_json_object_close(wb); // dimensions
- buffer_json_member_add_double(wb, "min", r->view.min);
- buffer_json_member_add_double(wb, "max", r->view.max);
- }
- buffer_json_object_close(wb); // view
- rrdr_timings_v12(wb, "timings", r);
- buffer_json_finalize(wb);
- }
|