@cryptotaxi247 / netdata-1 / commits / 4680da48b

Compatibility with Prometheus HELP (#17191)

thiagoftsm committed Mar 29, 2024 at 20:43 UTC 4680da48b91a40e48f802627b81a67d5a5270fbd
5 files changed +277 -332
src/exporting/prometheus/prometheus.c
+272 -275
@@ -353,6 +353,7 @@ static int format_prometheus_chart_label_callback(const char *name, const char *
353 struct host_variables_callback_options {
354 RRDHOST *host;
355 BUFFER *wb;
356 + BUFFER *plabels_buffer;
357 EXPORTING_OPTIONS exporting_options;
358 PROMETHEUS_OUTPUT_OPTIONS output_options;
359 const char *prefix;
@@ -360,6 +361,9 @@ struct host_variables_callback_options {
361 time_t now;
362 int host_header_printed;
363 char name[PROMETHEUS_VARIABLE_MAX + 1];
364 + SIMPLE_PATTERN *pattern;
365 + struct instance *instance;
366 + STRING *prometheus;
367 };
368
369 /**
@@ -376,18 +380,10 @@ static int print_host_variables_callback(const DICTIONARY_ITEM *item __maybe_unu
380
381 if (!opts->host_header_printed) {
382 opts->host_header_printed = 1;
379 -
380 - if (opts->output_options & PROMETHEUS_OUTPUT_HELP) {
381 - buffer_sprintf(opts->wb, "\n# COMMENT global host and chart variables\n");
382 - }
383 }
384
385 NETDATA_DOUBLE value = rrdvar2number(rv);
386 if (isnan(value) || isinf(value)) {
387 - if (opts->output_options & PROMETHEUS_OUTPUT_HELP)
388 - buffer_sprintf(
389 - opts->wb, "# COMMENT variable \"%s\" is %s. Skipped.\n", rrdvar_name(rv), (isnan(value)) ? "NAN" : "INF");
390 -
387 return 0;
388 }
389
@@ -448,32 +444,32 @@ struct gen_parameters {
444 * Write an as-collected help comment to a buffer.
445 *
446 * @param wb the buffer to write the comment to.
451 - * @param p parameters for generating the comment string.
452 - * @param homogeneous a flag for homogeneous charts.
453 - * @param prometheus_collector a flag for metrics from prometheus collector.
447 + * @param context context name we are using
448 */
455 -static void generate_as_collected_prom_help(BUFFER *wb, struct gen_parameters *p, int homogeneous, int prometheus_collector)
449 +static inline void generate_as_collected_prom_help(BUFFER *wb,
450 + const char *prefix,
451 + char *context,
452 + char *units,
453 + char *suffix,
454 + RRDSET *st)
455 {
457 - buffer_sprintf(wb, "# COMMENT %s_%s", p->prefix, p->context);
458 -
459 - if (!homogeneous)
460 - buffer_sprintf(wb, "_%s", p->dimension);
461 -
462 - buffer_sprintf(
463 - wb,
464 - "%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * ",
465 - p->suffix,
466 - (p->output_options & PROMETHEUS_OUTPUT_NAMES && p->st->name) ? rrdset_name(p->st) : rrdset_id(p->st),
467 - rrdset_context(p->st),
468 - rrdset_family(p->st),
469 - (p->output_options & PROMETHEUS_OUTPUT_NAMES && p->rd->name) ? rrddim_name(p->rd) : rrddim_id(p->rd));
470 -
471 - if (prometheus_collector)
472 - buffer_sprintf(wb, "1 / 1");
473 - else
474 - buffer_sprintf(wb, "%d / %d", p->rd->multiplier, p->rd->divisor);
456 + buffer_sprintf(wb, "# HELP %s_%s%s%s %s\n", prefix, context, units, suffix, rrdset_title(st));
457 +}
458
476 - buffer_sprintf(wb, " %s %s (%s)\n", p->relation, rrdset_units(p->st), p->type);
459 +/**
460 + * Write an as-collected help comment to a buffer.
461 + *
462 + * @param wb the buffer to write the comment to.
463 + * @param context context name we are using
464 + */
465 +static inline void generate_as_collected_prom_type(BUFFER *wb,
466 + const char *prefix,
467 + char *context,
468 + char *units,
469 + char *suffix,
470 + const char *type)
471 +{
472 + buffer_sprintf(wb, "# TYPE %s_%s%s%s %s\n", prefix, context, units, suffix, type);
473 }
474
475 /**
@@ -485,7 +481,7 @@ static void generate_as_collected_prom_help(BUFFER *wb, struct gen_parameters *p
481 * @param prometheus_collector a flag for metrics from prometheus collector.
482 * @param chart_labels the dictionary with chart labels
483 */
488 -static void generate_as_collected_prom_metric(BUFFER *wb,
484 +static void generate_as_collected_from_metric(BUFFER *wb,
485 struct gen_parameters *p,
486 int homogeneous,
487 int prometheus_collector,
@@ -602,6 +598,220 @@ static void prometheus_print_os_info(
598
599 fclose(fp);
600 }
601 +
602 +/**
603 + * RRDSET to JSON
604 + *
605 + * From RRDSET extract content necessary to write JSON output.
606 + *
607 + * @param st netdata chart structure
608 + * @param data structure with necessary data and to build expected result.
609 + *
610 + * @return I returns 1 when content was used and 0 otherwise.
611 + */
612 +static int prometheus_rrdset_to_json(RRDSET *st, void *data)
613 +{
614 + struct host_variables_callback_options *opts = data;
615 +
616 + if (likely(can_send_rrdset(opts->instance, st, opts->pattern))) {
617 + PROMETHEUS_OUTPUT_OPTIONS output_options = opts->output_options;
618 + BUFFER *wb = opts->wb;
619 + const char *prefix = opts->prefix;
620 +
621 + BUFFER *plabels_buffer = opts->plabels_buffer;
622 + const char *plabels_prefix = opts->instance->config.label_prefix;
623 +
624 + STRING *prometheus = opts->prometheus;
625 +
626 + char chart[PROMETHEUS_ELEMENT_MAX + 1];
627 + char context[PROMETHEUS_ELEMENT_MAX + 1];
628 + char family[PROMETHEUS_ELEMENT_MAX + 1];
629 + char units[PROMETHEUS_ELEMENT_MAX + 1] = "";
630 +
631 + prometheus_label_copy(chart,
632 + (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ?
633 + rrdset_name(st) : rrdset_id(st), PROMETHEUS_ELEMENT_MAX);
634 + prometheus_label_copy(family, rrdset_family(st), PROMETHEUS_ELEMENT_MAX);
635 + prometheus_name_copy(context, rrdset_context(st), PROMETHEUS_ELEMENT_MAX);
636 +
637 + int as_collected = (EXPORTING_OPTIONS_DATA_SOURCE(opts->exporting_options)
638 + == EXPORTING_SOURCE_DATA_AS_COLLECTED);
639 + int homogeneous = 1;
640 + int prometheus_collector = 0;
641 + RRDSET_FLAGS flags = rrdset_flag_get(st);
642 + if (as_collected) {
643 + if (flags & RRDSET_FLAG_HOMOGENEOUS_CHECK)
644 + rrdset_update_heterogeneous_flag(st);
645 +
646 + if (flags & RRDSET_FLAG_HETEROGENEOUS)
647 + homogeneous = 0;
648 +
649 + if (st->module_name == prometheus)
650 + prometheus_collector = 1;
651 + }
652 + else {
653 + if (EXPORTING_OPTIONS_DATA_SOURCE(opts->exporting_options) == EXPORTING_SOURCE_DATA_AVERAGE &&
654 + !(output_options & PROMETHEUS_OUTPUT_HIDEUNITS))
655 + prometheus_units_copy(units,
656 + rrdset_units(st),
657 + PROMETHEUS_ELEMENT_MAX,
658 + output_options & PROMETHEUS_OUTPUT_OLDUNITS);
659 + }
660 +
661 + // for each dimension
662 + RRDDIM *rd;
663 + rrddim_foreach_read(rd, st) {
664 +
665 + if (rd->collector.counter && !rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
666 + char dimension[PROMETHEUS_ELEMENT_MAX + 1];
667 + char *suffix = "";
668 +
669 + struct gen_parameters p;
670 + p.prefix = prefix;
671 + p.labels_prefix = plabels_prefix;
672 + p.context = context;
673 + p.suffix = suffix;
674 + p.chart = chart;
675 + p.dimension = dimension;
676 + p.family = family;
677 + p.labels = (char *)opts->labels;
678 + p.output_options = output_options;
679 + p.st = st;
680 + p.rd = rd;
681 +
682 + if (as_collected) {
683 + // we need as-collected / raw data
684 +
685 + if (unlikely(rd->collector.last_collected_time.tv_sec < opts->instance->after))
686 + continue;
687 +
688 + p.type = "gauge";
689 + p.relation = "gives";
690 + if (rd->algorithm == RRD_ALGORITHM_INCREMENTAL ||
691 + rd->algorithm == RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL) {
692 + p.type = "counter";
693 + p.relation = "delta gives";
694 + if (!prometheus_collector)
695 + p.suffix = "_total";
696 + }
697 +
698 + if (opts->output_options & PROMETHEUS_OUTPUT_HELP_TYPE) {
699 + generate_as_collected_prom_help(wb, prefix, context, units, suffix, st);
700 + generate_as_collected_prom_type(wb, prefix, context, units, p.suffix, p.type);
701 + opts->output_options &= ~PROMETHEUS_OUTPUT_HELP_TYPE;
702 + }
703 +
704 + if (homogeneous) {
705 + // all the dimensions of the chart, has the same algorithm, multiplier and divisor
706 + // we add all dimensions as labels
707 +
708 + prometheus_label_copy(
709 + dimension,
710 + (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
711 + PROMETHEUS_ELEMENT_MAX);
712 + }
713 + else {
714 + // the dimensions of the chart, do not have the same algorithm, multiplier or divisor
715 + // we create a metric per dimension
716 +
717 + prometheus_name_copy(
718 + dimension,
719 + (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
720 + PROMETHEUS_ELEMENT_MAX);
721 + }
722 + generate_as_collected_from_metric(wb, &p, homogeneous, prometheus_collector, st->rrdlabels);
723 + }
724 + else {
725 + // we need average or sum of the data
726 +
727 + time_t last_time = opts->instance->before;
728 + NETDATA_DOUBLE value = exporting_calculate_value_from_stored_data(opts->instance, rd, &last_time);
729 +
730 + if (!isnan(value) && !isinf(value)) {
731 + if (EXPORTING_OPTIONS_DATA_SOURCE(opts->exporting_options)
732 + == EXPORTING_SOURCE_DATA_AVERAGE)
733 + suffix = "_average";
734 + else if (EXPORTING_OPTIONS_DATA_SOURCE(opts->exporting_options)
735 + == EXPORTING_SOURCE_DATA_SUM)
736 + suffix = "_sum";
737 +
738 + prometheus_label_copy(
739 + dimension,
740 + (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
741 + PROMETHEUS_ELEMENT_MAX);
742 +
743 + if (opts->output_options & PROMETHEUS_OUTPUT_HELP_TYPE) {
744 + generate_as_collected_prom_help(wb, prefix, context, units, suffix, st);
745 + generate_as_collected_prom_type(wb, prefix, context, units, p.suffix, "gauge");
746 + opts->output_options &= ~PROMETHEUS_OUTPUT_HELP_TYPE;
747 + }
748 +
749 + buffer_flush(plabels_buffer);
750 + buffer_sprintf(plabels_buffer,
751 + "%1$schart=\"%2$s\",%1$sdimension=\"%3$s\",%1$sfamily=\"%4$s\"",
752 + plabels_prefix,
753 + chart,
754 + dimension,
755 + family);
756 + rrdlabels_walkthrough_read(st->rrdlabels,
757 + format_prometheus_chart_label_callback,
758 + plabels_buffer);
759 +
760 + if (output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
761 + buffer_sprintf(wb,
762 + "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT " %llu\n",
763 + prefix,
764 + context,
765 + units,
766 + suffix,
767 + buffer_tostring(plabels_buffer),
768 + opts->labels,
769 + value,
770 + last_time * MSEC_PER_SEC);
771 + else
772 + buffer_sprintf(wb, "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT "\n",
773 + prefix,
774 + context,
775 + units,
776 + suffix,
777 + buffer_tostring(plabels_buffer),
778 + opts->labels,
779 + value);
780 + }
781 + }
782 + }
783 + }
784 + rrddim_foreach_done(rd);
785 +
786 + return 1;
787 + }
788 +
789 + return 0;
790 +}
791 +
792 +/**
793 + * RRDCONTEXT callback
794 + *
795 + * Callback used to parse dictionary
796 + *
797 + * @param item the dictionary structure
798 + * @param value unused element
799 + * @param data structure used to store data.
800 + *
801 + * @return It always returns HTTP_RESP_OK
802 + */
803 +static inline int prometheus_rrdcontext_callback(const DICTIONARY_ITEM *item, void *value, void *data)
804 +{
805 + const char *context_name = dictionary_acquired_item_name(item);
806 + struct host_variables_callback_options *opts = data;
807 + (void)value;
808 +
809 + opts->output_options |= PROMETHEUS_OUTPUT_HELP_TYPE;
810 + (void)rrdcontext_foreach_instance_with_rrdset_in_context(opts->host, context_name, prometheus_rrdset_to_json, data);
811 +
812 + return HTTP_RESP_OK;
813 +}
814 +
815 /**
816 * Write metrics in Prometheus format to a buffer.
817 *
@@ -658,219 +868,41 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
868 if (instance->config.options & EXPORTING_OPTION_SEND_AUTOMATIC_LABELS)
869 prometheus_print_os_info(wb, host, output_options);
870
661 - // send custom variables set for the host
662 - if (output_options & PROMETHEUS_OUTPUT_VARIABLES) {
663 -
664 - struct host_variables_callback_options opts = {
665 - .host = host,
666 - .wb = wb,
667 - .labels = (labels[0] == ',') ? &labels[1] : labels,
668 - .exporting_options = exporting_options,
669 - .output_options = output_options,
670 - .prefix = prefix,
671 - .now = now_realtime_sec(),
672 - .host_header_printed = 0
673 - };
674 -
675 - rrdvar_walkthrough_read(host->rrdvars, print_host_variables_callback, &opts);
676 - }
677 -
678 - // for each chart
679 - RRDSET *st;
871
872 BUFFER *plabels_buffer = buffer_create(0, NULL);
682 - const char *plabels_prefix = instance->config.label_prefix;
683 -
684 - STRING *prometheus = string_strdupz("prometheus");
685 - rrdset_foreach_read(st, host) {
686 -
687 - if (likely(can_send_rrdset(instance, st, filter))) {
688 - char chart[PROMETHEUS_ELEMENT_MAX + 1];
689 - char context[PROMETHEUS_ELEMENT_MAX + 1];
690 - char family[PROMETHEUS_ELEMENT_MAX + 1];
691 - char units[PROMETHEUS_ELEMENT_MAX + 1] = "";
692 -
693 - prometheus_label_copy(chart, (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? rrdset_name(st) : rrdset_id(st), PROMETHEUS_ELEMENT_MAX);
694 - prometheus_label_copy(family, rrdset_family(st), PROMETHEUS_ELEMENT_MAX);
695 - prometheus_name_copy(context, rrdset_context(st), PROMETHEUS_ELEMENT_MAX);
696 -
697 - int as_collected = (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_AS_COLLECTED);
698 - int homogeneous = 1;
699 - int prometheus_collector = 0;
700 - RRDSET_FLAGS flags = rrdset_flag_get(st);
701 - if (as_collected) {
702 - if (flags & RRDSET_FLAG_HOMOGENEOUS_CHECK)
703 - rrdset_update_heterogeneous_flag(st);
704 -
705 - if (flags & RRDSET_FLAG_HETEROGENEOUS)
706 - homogeneous = 0;
707 -
708 - if (st->module_name == prometheus)
709 - prometheus_collector = 1;
710 - }
711 - else {
712 - if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_AVERAGE &&
713 - !(output_options & PROMETHEUS_OUTPUT_HIDEUNITS))
714 - prometheus_units_copy(
715 - units, rrdset_units(st), PROMETHEUS_ELEMENT_MAX, output_options & PROMETHEUS_OUTPUT_OLDUNITS);
716 - }
717 -
718 - if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
719 - buffer_sprintf(
720 - wb,
721 - "\n# COMMENT %s chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n",
722 - (homogeneous) ? "homogeneous" : "heterogeneous",
723 - (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? rrdset_name(st) : rrdset_id(st),
724 - rrdset_context(st),
725 - rrdset_family(st),
726 - rrdset_units(st));
727 -
728 - // for each dimension
729 - RRDDIM *rd;
730 - rrddim_foreach_read(rd, st) {
731 - if (rd->collector.counter && !rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) {
732 - char dimension[PROMETHEUS_ELEMENT_MAX + 1];
733 - char *suffix = "";
734 -
735 - if (as_collected) {
736 - // we need as-collected / raw data
737 -
738 - struct gen_parameters p;
739 - p.prefix = prefix;
740 - p.labels_prefix = instance->config.label_prefix;
741 - p.context = context;
742 - p.suffix = suffix;
743 - p.chart = chart;
744 - p.dimension = dimension;
745 - p.family = family;
746 - p.labels = labels;
747 - p.output_options = output_options;
748 - p.st = st;
749 - p.rd = rd;
750 -
751 - if (unlikely(rd->collector.last_collected_time.tv_sec < instance->after))
752 - continue;
753 -
754 - p.type = "gauge";
755 - p.relation = "gives";
756 - if (rd->algorithm == RRD_ALGORITHM_INCREMENTAL ||
757 - rd->algorithm == RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL) {
758 - p.type = "counter";
759 - p.relation = "delta gives";
760 - if (!prometheus_collector)
761 - p.suffix = "_total";
762 - }
763 -
764 - if (homogeneous) {
765 - // all the dimensions of the chart, has the same algorithm, multiplier and divisor
766 - // we add all dimensions as labels
767 -
768 - prometheus_label_copy(
769 - dimension,
770 - (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
771 - PROMETHEUS_ELEMENT_MAX);
772 -
773 - if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
774 - generate_as_collected_prom_help(wb, &p, homogeneous, prometheus_collector);
775 -
776 - if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
777 - buffer_sprintf(wb, "# TYPE %s_%s%s %s\n", prefix, context, suffix, p.type);
778 -
779 - generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector, st->rrdlabels);
780 - }
781 - else {
782 - // the dimensions of the chart, do not have the same algorithm, multiplier or divisor
783 - // we create a metric per dimension
784 -
785 - prometheus_name_copy(
786 - dimension,
787 - (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
788 - PROMETHEUS_ELEMENT_MAX);
873
790 - if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
791 - generate_as_collected_prom_help(wb, &p, homogeneous, prometheus_collector);
874 + struct host_variables_callback_options opts = {
875 + .host = host,
876 + .wb = wb,
877 + .plabels_buffer = plabels_buffer,
878 + .labels = (labels[0] == ',') ? &labels[1] : labels,
879 + .exporting_options = exporting_options,
880 + .output_options = output_options,
881 + .prefix = prefix,
882 + .now = now_realtime_sec(),
883 + .host_header_printed = 0,
884 + .pattern = filter,
885 + .instance = instance,
886 + .prometheus = string_strdupz("prometheus")
887 + };
888
793 - if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
794 - buffer_sprintf(
795 - wb, "# TYPE %s_%s_%s%s %s\n", prefix, context, dimension, suffix, p.type);
889 + // send custom variables set for the host
890 + if (output_options & PROMETHEUS_OUTPUT_VARIABLES) {
891 + rrdvar_walkthrough_read(host->rrdvars, print_host_variables_callback, &opts);
892 + }
893
797 - generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector, st->rrdlabels);
798 - }
799 - }
800 - else {
801 - // we need average or sum of the data
802 -
803 - time_t first_time = instance->after;
804 - time_t last_time = instance->before;
805 - NETDATA_DOUBLE value = exporting_calculate_value_from_stored_data(instance, rd, &last_time);
806 -
807 - if (!isnan(value) && !isinf(value)) {
808 - if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_AVERAGE)
809 - suffix = "_average";
810 - else if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_SUM)
811 - suffix = "_sum";
812 -
813 - prometheus_label_copy(
814 - dimension,
815 - (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
816 - PROMETHEUS_ELEMENT_MAX);
817 -
818 - buffer_flush(plabels_buffer);
819 - buffer_sprintf(plabels_buffer, "%1$schart=\"%2$s\",%1$sdimension=\"%3$s\",%1$sfamily=\"%4$s\"", plabels_prefix, chart, dimension, family);
820 - rrdlabels_walkthrough_read(st->rrdlabels, format_prometheus_chart_label_callback, plabels_buffer);
821 -
822 - if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
823 - buffer_sprintf(
824 - wb,
825 - "# COMMENT %s_%s%s%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n",
826 - prefix,
827 - context,
828 - units,
829 - suffix,
830 - (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
831 - rrdset_units(st),
832 - (unsigned long long)first_time,
833 - (unsigned long long)last_time);
834 -
835 - if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
836 - buffer_sprintf(wb, "# TYPE %s_%s%s%s gauge\n", prefix, context, units, suffix);
837 -
838 - if (output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
839 - buffer_sprintf(
840 - wb,
841 - "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT
842 - " %llu\n",
843 - prefix,
844 - context,
845 - units,
846 - suffix,
847 - buffer_tostring(plabels_buffer),
848 - labels,
849 - value,
850 - last_time * MSEC_PER_SEC);
851 - else
852 - buffer_sprintf(
853 - wb,
854 - "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT
855 - "\n",
856 - prefix,
857 - context,
858 - units,
859 - suffix,
860 - buffer_tostring(plabels_buffer),
861 - labels,
862 - value);
863 - }
864 - }
865 - }
866 - }
867 - rrddim_foreach_done(rd);
868 - }
894 + // for each context
895 + if (!host->rrdctx.contexts) {
896 + netdata_log_error("%s(): request for host '%s' that does not have rrdcontexts initialized.", __FUNCTION__, rrdhost_hostname(host));
897 + goto allmetrics_cleanup;
898 }
870 - rrdset_foreach_done(st);
899
872 - buffer_free(plabels_buffer);
900 + dictionary_walkthrough_read(host->rrdctx.contexts, prometheus_rrdcontext_callback, &opts);
901 +
902 +allmetrics_cleanup:
903 simple_pattern_free(filter);
904 + buffer_free(plabels_buffer);
905 + string_freez(opts.prometheus);
906 }
907
908 /**
@@ -888,11 +920,8 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
920 static inline time_t prometheus_preparation(
921 struct instance *instance,
922 RRDHOST *host,
891 - BUFFER *wb,
892 - EXPORTING_OPTIONS exporting_options,
923 const char *server,
894 - time_t now,
895 - PROMETHEUS_OUTPUT_OPTIONS output_options)
924 + time_t now)
925 {
926 #ifndef UNIT_TESTING
927 analytics_log_prometheus();
@@ -902,10 +931,8 @@ static inline time_t prometheus_preparation(
931
932 time_t after = prometheus_server_last_access(server, host, now);
933
905 - int first_seen = 0;
934 if (!after) {
935 after = now - instance->config.update_every;
908 - first_seen = 1;
936 }
937
938 if (after > now) {
@@ -913,30 +940,6 @@ static inline time_t prometheus_preparation(
940 after = now - instance->config.update_every;
941 }
942
916 - if (output_options & PROMETHEUS_OUTPUT_HELP) {
917 - char *mode;
918 - if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_AS_COLLECTED)
919 - mode = "as collected";
920 - else if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_AVERAGE)
921 - mode = "average";
922 - else if (EXPORTING_OPTIONS_DATA_SOURCE(exporting_options) == EXPORTING_SOURCE_DATA_SUM)
923 - mode = "sum";
924 - else
925 - mode = "unknown";
926 -
927 - buffer_sprintf(
928 - wb,
929 - "# COMMENT netdata \"%s\" to %sprometheus \"%s\", source \"%s\", last seen %lu %s, time range %lu to %lu\n\n",
930 - rrdhost_hostname(host),
931 - (first_seen) ? "FIRST SEEN " : "",
932 - server,
933 - mode,
934 - (unsigned long)((first_seen) ? 0 : (now - after)),
935 - (first_seen) ? "never" : "seconds ago",
936 - (unsigned long)after,
937 - (unsigned long)now);
938 - }
939 -
943 return after;
944 }
945
@@ -969,11 +972,8 @@ void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(
972 prometheus_exporter_instance->after = prometheus_preparation(
973 prometheus_exporter_instance,
974 host,
972 - wb,
973 - exporting_options,
975 server,
975 - prometheus_exporter_instance->before,
976 - output_options);
976 + prometheus_exporter_instance->before);
977
978 rrd_stats_api_v1_charts_allmetrics_prometheus(
979 prometheus_exporter_instance, host, filter_string, wb, prefix, exporting_options, 0, output_options);
@@ -1008,11 +1008,8 @@ void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(
1008 prometheus_exporter_instance->after = prometheus_preparation(
1009 prometheus_exporter_instance,
1010 host,
1011 - wb,
1012 - exporting_options,
1011 server,
1014 - prometheus_exporter_instance->before,
1015 - output_options);
1012 + prometheus_exporter_instance->before);
1013
1014 dfe_start_reentrant(rrdhost_root_index, host)
1015 {
src/exporting/prometheus/prometheus.h
+3 -4
@@ -11,13 +11,12 @@
11
12 typedef enum prometheus_output_flags {
13 PROMETHEUS_OUTPUT_NONE = 0,
14 - PROMETHEUS_OUTPUT_HELP = (1 << 0),
15 - PROMETHEUS_OUTPUT_TYPES = (1 << 1),
14 + PROMETHEUS_OUTPUT_HELP_TYPE = (1 << 1),
15 PROMETHEUS_OUTPUT_NAMES = (1 << 2),
16 PROMETHEUS_OUTPUT_TIMESTAMPS = (1 << 3),
17 PROMETHEUS_OUTPUT_VARIABLES = (1 << 4),
19 - PROMETHEUS_OUTPUT_OLDUNITS = (1 << 5),
20 - PROMETHEUS_OUTPUT_HIDEUNITS = (1 << 6)
18 + PROMETHEUS_OUTPUT_OLDUNITS = (1 << 5),
19 + PROMETHEUS_OUTPUT_HIDEUNITS = (1 << 6)
20 } PROMETHEUS_OUTPUT_OPTIONS;
21
22 void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(
src/web/api/exporters/allmetrics.c
+2 -3
@@ -6,8 +6,6 @@ struct prometheus_output_options {
6 char *name;
7 PROMETHEUS_OUTPUT_OPTIONS flag;
8 } prometheus_output_flags_root[] = {
9 - { "help", PROMETHEUS_OUTPUT_HELP },
10 - { "types", PROMETHEUS_OUTPUT_TYPES },
9 { "names", PROMETHEUS_OUTPUT_NAMES },
10 { "timestamps", PROMETHEUS_OUTPUT_TIMESTAMPS },
11 { "variables", PROMETHEUS_OUTPUT_VARIABLES },
@@ -76,8 +74,9 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
74 if(!strcmp(name, prometheus_output_flags_root[i].name)) {
75 if(!strcmp(value, "yes") || !strcmp(value, "1") || !strcmp(value, "true"))
76 prometheus_output_options |= prometheus_output_flags_root[i].flag;
79 - else
77 + else {
78 prometheus_output_options &= ~prometheus_output_flags_root[i].flag;
79 + }
80
81 break;
82 }
src/web/api/netdata-swagger.json
-28
@@ -901,34 +901,6 @@
901 "default": "no"
902 }
903 },
904 - {
905 - "name": "help",
906 - "in": "query",
907 - "description": "Enable or disable HELP lines in prometheus output.\n",
908 - "required": false,
909 - "schema": {
910 - "type": "string",
911 - "enum": [
912 - "yes",
913 - "no"
914 - ],
915 - "default": "no"
916 - }
917 - },
918 - {
919 - "name": "types",
920 - "in": "query",
921 - "description": "Enable or disable TYPE lines in prometheus output.\n",
922 - "required": false,
923 - "schema": {
924 - "type": "string",
925 - "enum": [
926 - "yes",
927 - "no"
928 - ],
929 - "default": "no"
930 - }
931 - },
904 {
905 "name": "timestamps",
906 "in": "query",
src/web/api/netdata-swagger.yaml
-22
@@ -554,28 +554,6 @@ paths:
554 - yes
555 - no
556 default: no
557 - - name: help
558 - in: query
559 - description: |
560 - Enable or disable HELP lines in prometheus output.
561 - required: false
562 - schema:
563 - type: string
564 - enum:
565 - - yes
566 - - no
567 - default: no
568 - - name: types
569 - in: query
570 - description: |
571 - Enable or disable TYPE lines in prometheus output.
572 - required: false
573 - schema:
574 - type: string
575 - enum:
576 - - yes
577 - - no
578 - default: no
557 - name: timestamps
558 in: query
559 description: |