diff --git a/Makefile b/Makefile index 34c0d8b61..7ac08e594 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ lint-mixins: tests: pushd . && cd ./common-lib && make vendor && make tests + pushd . && cd ./mixin-utils/test && make tests drone: drone jsonnet --stream --source .drone/drone.jsonnet --target .drone/drone.yml --format yaml diff --git a/grafana-builder/grafana.libsonnet b/grafana-builder/grafana.libsonnet index f4a9745a6..435575803 100644 --- a/grafana-builder/grafana.libsonnet +++ b/grafana-builder/grafana.libsonnet @@ -531,13 +531,13 @@ local utils = import 'mixin-utils/utils.libsonnet'; }, targets: [ { - expr: utils.showClassicHistogramQuery(sumByStatus(utils.nativeClassicHistogramCountRate(metricName, selector))), + expr: utils.showClassicHistogramQuery(sumByStatus(utils.ncHistogramCountRate(metricName, selector))), format: 'time_series', legendFormat: '{{status}}', refId: 'A_classic', }, { - expr: utils.showNativeHistogramQuery(sumByStatus(utils.nativeClassicHistogramCountRate(metricName, selector))), + expr: utils.showNativeHistogramQuery(sumByStatus(utils.ncHistogramCountRate(metricName, selector))), format: 'time_series', legendFormat: '{{status}}', refId: 'A', @@ -583,37 +583,37 @@ local utils = import 'mixin-utils/utils.libsonnet'; }, targets: [ { - expr: utils.showNativeHistogramQuery(utils.nativeClassicHistogramQuantile('0.99', metricName, selector, multiplier=multiplier)), + expr: utils.showNativeHistogramQuery(utils.ncHistogramQuantile('0.99', metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: '99th percentile', refId: 'A', }, { - expr: utils.showClassicHistogramQuery(utils.nativeClassicHistogramQuantile('0.99', metricName, selector, multiplier=multiplier)), + expr: utils.showClassicHistogramQuery(utils.ncHistogramQuantile('0.99', metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: '99th percentile', refId: 'A_classic', }, { - expr: utils.showNativeHistogramQuery(utils.nativeClassicHistogramQuantile('0.50', metricName, selector, multiplier=multiplier)), + expr: utils.showNativeHistogramQuery(utils.ncHistogramQuantile('0.50', metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: '50th percentile', refId: 'B', }, { - expr: utils.showClassicHistogramQuery(utils.nativeClassicHistogramQuantile('0.50', metricName, selector, multiplier=multiplier)), + expr: utils.showClassicHistogramQuery(utils.ncHistogramQuantile('0.50', metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: '50th percentile', refId: 'B_classic', }, { - expr: utils.showNativeHistogramQuery(utils.nativeClassicHistogramAverageRate(metricName, selector, multiplier=multiplier)), + expr: utils.showNativeHistogramQuery(utils.ncHistogramAverageRate(metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: 'Average', refId: 'C', }, { - expr: utils.showClassicHistogramQuery(utils.nativeClassicHistogramAverageRate(metricName, selector, multiplier=multiplier)), + expr: utils.showClassicHistogramQuery(utils.ncHistogramAverageRate(metricName, selector, multiplier=multiplier)), format: 'time_series', legendFormat: 'Average', refId: 'C_classic', diff --git a/mixin-utils/test/.gitignore b/mixin-utils/test/.gitignore new file mode 100644 index 000000000..80243dae6 --- /dev/null +++ b/mixin-utils/test/.gitignore @@ -0,0 +1,2 @@ +vendor/ +jsonnetfile.lock.json diff --git a/mixin-utils/test/Makefile b/mixin-utils/test/Makefile new file mode 100644 index 000000000..ea444b444 --- /dev/null +++ b/mixin-utils/test/Makefile @@ -0,0 +1,7 @@ +.PHONY: tests + +vendor jsonnetfile.lock.json: jsonnetfile.json + jb install + +tests: jsonnetfile.lock.json vendor + jsonnet -J vendor/ test_*.libsonnet diff --git a/mixin-utils/test/jsonnetfile.json b/mixin-utils/test/jsonnetfile.json new file mode 100644 index 000000000..c14684195 --- /dev/null +++ b/mixin-utils/test/jsonnetfile.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "dependencies": [ + { + "source": { + "git": { + "remote": "https://github.com/jsonnet-libs/testonnet.git" + } + }, + "version": "master" + } + ], + "legacyImports": true +} diff --git a/mixin-utils/test/test_native-classic-histogram.libsonnet b/mixin-utils/test/test_native-classic-histogram.libsonnet new file mode 100644 index 000000000..6c1a3fbb3 --- /dev/null +++ b/mixin-utils/test/test_native-classic-histogram.libsonnet @@ -0,0 +1,191 @@ +local utils = import '../utils.libsonnet'; +local test = import 'github.com/jsonnet-libs/testonnet/main.libsonnet'; + +test.new(std.thisFile) + ++ test.case.new( + name='Quantile defaults', + test=test.expect.eq( + actual=utils.ncHistogramQuantile('0.95', 'request_duration_seconds', 'cluster="cluster1", job="job1"'), + expected={ + classic: 'histogram_quantile(0.95, sum by (le) (rate(request_duration_seconds_bucket{cluster="cluster1", job="job1"}[$__rate_interval])))', + native: 'histogram_quantile(0.95, sum (rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval])))', + }, + ) +) ++ test.case.new( + name='Quantile different groups, interval, multiplier', + test=test.expect.eq( + actual=utils.ncHistogramQuantile('0.95', 'request_duration_seconds', 'cluster="cluster1", job="job1"', ['namespace', 'route'], '5m', '42'), + expected={ + classic: 'histogram_quantile(0.95, sum by (le,namespace,route) (rate(request_duration_seconds_bucket{cluster="cluster1", job="job1"}[5m]))) * 42', + native: 'histogram_quantile(0.95, sum by (namespace,route) (rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))) * 42', + }, + ) +) ++ test.case.new( + name='Quantile in recording rule with different groups, interval, multiplier, rate', + test=test.expect.eq( + actual=utils.ncHistogramQuantile('0.95', 'request_duration_seconds', 'cluster="cluster1", job="job1"', ['namespace', 'route'], '5m', '42', true), + expected={ + classic: 'histogram_quantile(0.95, sum by (le,namespace,route) (request_duration_seconds_bucket:sum_rate{cluster="cluster1", job="job1"})) * 42', + native: 'histogram_quantile(0.95, sum by (namespace,route) (request_duration_seconds:sum_rate{cluster="cluster1", job="job1"})) * 42', + }, + ) +) + ++ test.case.new( + name='rate of sum defaults', + test=test.expect.eq( + actual=utils.ncHistogramSumRate('request_duration_seconds', 'cluster="cluster1", job="job1"'), + expected={ + classic: 'rate(request_duration_seconds_sum{cluster="cluster1", job="job1"}[$__rate_interval])', + native: 'histogram_sum(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))', + }, + ) +) ++ test.case.new( + name='rate of sum with different interval', + test=test.expect.eq( + actual=utils.ncHistogramSumRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m'), + expected={ + classic: 'rate(request_duration_seconds_sum{cluster="cluster1", job="job1"}[5m])', + native: 'histogram_sum(rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))', + }, + ) +) ++ test.case.new( + name='rate of sum in recording rule with different interval', + test=test.expect.eq( + actual=utils.ncHistogramSumRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m', true), + expected={ + classic: 'request_duration_seconds_sum:sum_rate{cluster="cluster1", job="job1"}', + native: 'histogram_sum(request_duration_seconds:sum_rate{cluster="cluster1", job="job1"})', + }, + ) +) + ++ test.case.new( + name='rate of count defaults', + test=test.expect.eq( + actual=utils.ncHistogramCountRate('request_duration_seconds', 'cluster="cluster1", job="job1"'), + expected={ + classic: 'rate(request_duration_seconds_count{cluster="cluster1", job="job1"}[$__rate_interval])', + native: 'histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))', + }, + ) +) ++ test.case.new( + name='rate of count with different interval', + test=test.expect.eq( + actual=utils.ncHistogramCountRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m'), + expected={ + classic: 'rate(request_duration_seconds_count{cluster="cluster1", job="job1"}[5m])', + native: 'histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))', + }, + ) +) ++ test.case.new( + name='rate of count in recording rule with different interval', + test=test.expect.eq( + actual=utils.ncHistogramCountRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m', true), + expected={ + classic: 'request_duration_seconds_count:sum_rate{cluster="cluster1", job="job1"}', + native: 'histogram_count(request_duration_seconds:sum_rate{cluster="cluster1", job="job1"})', + }, + ) +) + ++ test.case.new( + name='rate of average defaults', + test=test.expect.eq( + actual=utils.ncHistogramAverageRate('request_duration_seconds', 'cluster="cluster1", job="job1"'), + expected={ + classic: 'sum(rate(request_duration_seconds_sum{cluster="cluster1", job="job1"}[$__rate_interval])) /\nsum(rate(request_duration_seconds_count{cluster="cluster1", job="job1"}[$__rate_interval]))\n', + native: 'sum(histogram_sum(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))) /\nsum(histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval])))\n', + }, + ) +) ++ test.case.new( + name='rate of average with different interval, multiplier', + test=test.expect.eq( + actual=utils.ncHistogramAverageRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m', '42'), + expected={ + classic: '42 * sum(rate(request_duration_seconds_sum{cluster="cluster1", job="job1"}[5m])) /\nsum(rate(request_duration_seconds_count{cluster="cluster1", job="job1"}[5m]))\n', + native: '42 * sum(histogram_sum(rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))) /\nsum(histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m])))\n', + }, + ) +) ++ test.case.new( + name='rate of average in recording rule with different interval, multiplier', + test=test.expect.eq( + actual=utils.ncHistogramAverageRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '5m', '42', true), + expected={ + classic: '42 * sum(request_duration_seconds_sum:sum_rate{cluster="cluster1", job="job1"}) /\nsum(request_duration_seconds_count:sum_rate{cluster="cluster1", job="job1"})\n', + native: '42 * sum(histogram_sum(request_duration_seconds:sum_rate{cluster="cluster1", job="job1"})) /\nsum(histogram_count(request_duration_seconds:sum_rate{cluster="cluster1", job="job1"}))\n', + }, + ) +) + ++ test.case.new( + name='histogram sum by defaults', + test=test.expect.eq( + actual=utils.ncHistogramSumBy(utils.ncHistogramCountRate('request_duration_seconds_sum', '{cluster="cluster1", job="job1"}')), + expected={ + classic: 'sum (rate(request_duration_seconds_sum_count{{cluster="cluster1", job="job1"}}[$__rate_interval]))', + native: 'sum (histogram_count(rate(request_duration_seconds_sum{{cluster="cluster1", job="job1"}}[$__rate_interval])))', + }, + ) +) ++ test.case.new( + name='histogram sum by with different labels and multiplier', + test=test.expect.eq( + actual=utils.ncHistogramSumBy(utils.ncHistogramCountRate('request_duration_seconds_sum', '{cluster="cluster1", job="job1"}'), ['namespace', 'route'], '42'), + expected={ + classic: 'sum by (namespace, route) (rate(request_duration_seconds_sum_count{{cluster="cluster1", job="job1"}}[$__rate_interval])) * 42', + native: 'sum by (namespace, route) (histogram_count(rate(request_duration_seconds_sum{{cluster="cluster1", job="job1"}}[$__rate_interval]))) * 42', + }, + ) +) + ++ test.case.new( + name='histogram le rate defaults and le is float', + test=test.expect.eq( + actual=utils.ncHistogramLeRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '0.1'), + expected={ + classic: 'rate(request_duration_seconds_bucket{cluster="cluster1", job="job1", le=~"0.1"}[$__rate_interval])', + native: 'histogram_fraction(0, 0.1, rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))*histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))', + }, + ) +) ++ test.case.new( + name='histogram le rate defaults and le is whole', + test=test.expect.eq( + actual=utils.ncHistogramLeRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '10'), + expected={ + classic: 'rate(request_duration_seconds_bucket{cluster="cluster1", job="job1", le=~"10|10\\\\.0"}[$__rate_interval])', + native: 'histogram_fraction(0, 10.0, rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))*histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[$__rate_interval]))', + }, + ) +) ++ test.case.new( + name='histogram le rate defaults and le is float with different interval', + test=test.expect.eq( + actual=utils.ncHistogramLeRate('request_duration_seconds', 'cluster="cluster1", job="job1"', '0.1', '5m'), + expected={ + classic: 'rate(request_duration_seconds_bucket{cluster="cluster1", job="job1", le=~"0.1"}[5m])', + native: 'histogram_fraction(0, 0.1, rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))*histogram_count(rate(request_duration_seconds{cluster="cluster1", job="job1"}[5m]))', + }, + ) +) + ++ test.case.new( + name='commenting histogram query', + test=test.expect.eq( + actual=utils.ncHistogramComment({ classic: 'classic_query', native: 'native_query' }, 'comment\n'), + expected={ + classic: 'comment\nclassic_query\n', + native: 'comment\nnative_query\n', + }, + ) +) diff --git a/mixin-utils/utils.libsonnet b/mixin-utils/utils.libsonnet index 7d042989a..ada9574b1 100644 --- a/mixin-utils/utils.libsonnet +++ b/mixin-utils/utils.libsonnet @@ -1,10 +1,12 @@ local g = import 'grafana-builder/grafana.libsonnet'; { - // The classicNativeHistogramQuantile function is used to calculate histogram quantiles from native histograms or classic histograms. - // Metric name should be provided without _bucket suffix. - // If from_recording is true, the function will assume :sum_rate metric suffix and no rate needed. - nativeClassicHistogramQuantile(percentile, metric, selector, sum_by=[], rate_interval='$__rate_interval', multiplier='', from_recording=false):: + // The ncHistogramQuantile (native classic histogram quantile) function is + // used to calculate histogram quantiles from native histograms or classic + // histograms. Metric name should be provided without _bucket suffix. + // If from_recording is true, the function will assume :sum_rate metric + // suffix and no rate needed. + ncHistogramQuantile(percentile, metric, selector, sum_by=[], rate_interval='$__rate_interval', multiplier='', from_recording=false):: local classicSumBy = if std.length(sum_by) > 0 then ' by (%(lbls)s) ' % { lbls: std.join(',', ['le'] + sum_by) } else ' by (le) '; local nativeSumBy = if std.length(sum_by) > 0 then ' by (%(lbls)s) ' % { lbls: std.join(',', sum_by) } else ' '; local multiplierStr = if multiplier == '' then '' else ' * %s' % multiplier; @@ -35,10 +37,12 @@ local g = import 'grafana-builder/grafana.libsonnet'; }, }, - // The classicNativeHistogramSumRate function is used to calculate the histogram sum of rate from native histograms or classic histograms. - // Metric name should be provided without _sum suffix. - // If from_recording is true, the function will assume :sum_rate metric suffix and no rate needed. - nativeClassicHistogramSumRate(metric, selector, rate_interval='$__rate_interval', from_recording=false):: + // The ncHistogramSumRate (native classic histogram sum rate) function is + // used to calculate the histogram rate of the sum from native histograms or + // classic histograms. Metric name should be provided without _sum suffix. + // If from_recording is true, the function will assume :sum_rate metric + // suffix and no rate needed. + ncHistogramSumRate(metric, selector, rate_interval='$__rate_interval', from_recording=false):: local rateOpen = if from_recording then '' else 'rate('; local rateClose = if from_recording then '' else '[%s])' % rate_interval; { @@ -61,10 +65,12 @@ local g = import 'grafana-builder/grafana.libsonnet'; }, - // The classicNativeHistogramCountRate function is used to calculate the histogram count of rate from native histograms or classic histograms. - // Metric name should be provided without _count suffix. - // If from_recording is true, the function will assume :sum_rate metric suffix and no rate needed. - nativeClassicHistogramCountRate(metric, selector, rate_interval='$__rate_interval', from_recording=false):: + // The ncHistogramCountRate (native classic histogram count rate) function is + // used to calculate the histogram rate of count from native histograms or + // classic histograms. Metric name should be provided without _count suffix. + // If from_recording is true, the function will assume :sum_rate metric + // suffix and no rate needed. + ncHistogramCountRate(metric, selector, rate_interval='$__rate_interval', from_recording=false):: local rateOpen = if from_recording then '' else 'rate('; local rateClose = if from_recording then '' else '[%s])' % rate_interval; { @@ -87,30 +93,36 @@ local g = import 'grafana-builder/grafana.libsonnet'; }, // TODO(krajorama) Switch to histogram_avg function for native histograms later. - // nativeClassicHistogramAverageRate function is used to calculate the histogram average rate from native histograms or classic histograms. - // If from_recording is true, the function will assume :sum_rate metric suffix and no rate needed. - nativeClassicHistogramAverageRate(metric, selector, rate_interval='$__rate_interval', multiplier='', from_recording=false):: + // ncHistogramAverageRate (native classic histogram average rate) function is + // used to calculate the histogram average rate from native histograms or + // classic histograms. + // If from_recording is true, the function will assume :sum_rate metric + // suffix and no rate needed. + ncHistogramAverageRate(metric, selector, rate_interval='$__rate_interval', multiplier='', from_recording=false):: local multiplierStr = if multiplier == '' then '' else '%s * ' % multiplier; { classic: ||| %(multiplier)ssum(%(sumMetricQuery)s) / sum(%(countMetricQuery)s) ||| % { - sumMetricQuery: $.nativeClassicHistogramSumRate(metric, selector, rate_interval, from_recording).classic, - countMetricQuery: $.nativeClassicHistogramCountRate(metric, selector, rate_interval, from_recording).classic, + sumMetricQuery: $.ncHistogramSumRate(metric, selector, rate_interval, from_recording).classic, + countMetricQuery: $.ncHistogramCountRate(metric, selector, rate_interval, from_recording).classic, multiplier: multiplierStr, }, native: ||| %(multiplier)ssum(%(sumMetricQuery)s) / sum(%(countMetricQuery)s) ||| % { - sumMetricQuery: $.nativeClassicHistogramSumRate(metric, selector, rate_interval, from_recording).native, - countMetricQuery: $.nativeClassicHistogramCountRate(metric, selector, rate_interval, from_recording).native, + sumMetricQuery: $.ncHistogramSumRate(metric, selector, rate_interval, from_recording).native, + countMetricQuery: $.ncHistogramCountRate(metric, selector, rate_interval, from_recording).native, multiplier: multiplierStr, }, }, - nativeClassicSumBy(query, sum_by=[], multiplier=''):: + // ncHistogramSumBy (native classic histogram sum by) function is used to + // generate a query that sums the results of a subquery by the given labels. + // The function can be used with native histograms or classic histograms. + ncHistogramSumBy(query, sum_by=[], multiplier=''):: local sumBy = if std.length(sum_by) > 0 then ' by (%(lbls)s) ' % { lbls: std.join(', ', sum_by) } else ' '; local multiplierStr = if multiplier == '' then '' else ' * %s' % multiplier; { @@ -126,6 +138,41 @@ local g = import 'grafana-builder/grafana.libsonnet'; }, }, + // ncHistogramLeRate (native classic histogram le rate) calculates the rate + // of requests that have a value less than or equal to the given "le" value. + // The "le" value matcher for classic histograms can handle both Prometheus + // or OpenMetrics formats, where whole numbers may or may not have ".0" at + // the end. + ncHistogramLeRate(metric, selector, le, rate_interval='$__rate_interval'):: + local isWholeNumber(str) = str != '' && std.foldl(function(acc, c) acc && (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'), std.stringChars(str), true); + { + native: 'histogram_fraction(0, %(le)s, rate(%(metric)s{%(selector)s}[%(rateInterval)s]))*histogram_count(rate(%(metric)s{%(selector)s}[%(rateInterval)s]))' % { + le: if isWholeNumber(le) then le + '.0' else le, // Treated as float number. + metric: metric, + rateInterval: rate_interval, + selector: selector, + }, + classic: 'rate(%(metric)s_bucket{%(selector)s, le=~"%(le)s"}[%(rateInterval)s])' % { + // le is treated as string, thus it needs to account for Prometheus text format not having '.0', but OpenMetrics having it. + // Also the resulting string in yaml is stored directly, so the \\ needs to be escaped to \\\\. + le: if isWholeNumber(le) then '%(le)s|%(le)s\\\\.0' % { le: le } else le, + metric: metric, + rateInterval: rate_interval, + selector: selector, + }, + }, + + // ncHistogramComment (native classic histogram comment) helps attach + // comments to the query and also keep multiline strings where applicable. + ncHistogramComment(query, comment):: { + native: ||| + %s%s + ||| % [comment, query.native], + classic: ||| + %s%s + ||| % [comment, query.classic], + }, + // showClassicHistogramQuery wraps a query defined as map {classic: q, native: q}, and compares the classic query // to dashboard variable which should take -1 or +1 as values in order to hide or show the classic query. showClassicHistogramQuery(query, dashboard_variable='latency_metrics'):: '%s < ($%s * +Inf)' % [query.classic, dashboard_variable], @@ -270,37 +317,37 @@ local g = import 'grafana-builder/grafana.libsonnet'; yaxes: g.yaxes('ms'), targets: [ { - expr: $.showClassicHistogramQuery($.nativeClassicHistogramQuantile('0.99', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), + expr: $.showClassicHistogramQuery($.ncHistogramQuantile('0.99', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)s99th percentile' % legend, refId: 'A_classic', }, { - expr: $.showNativeHistogramQuery($.nativeClassicHistogramQuantile('0.99', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), + expr: $.showNativeHistogramQuery($.ncHistogramQuantile('0.99', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)s99th percentile' % legend, refId: 'A_native', }, { - expr: $.showClassicHistogramQuery($.nativeClassicHistogramQuantile('0.50', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), + expr: $.showClassicHistogramQuery($.ncHistogramQuantile('0.50', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)s50th percentile' % legend, refId: 'B_classic', }, { - expr: $.showNativeHistogramQuery($.nativeClassicHistogramQuantile('0.50', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), + expr: $.showNativeHistogramQuery($.ncHistogramQuantile('0.50', metricStr, selectorStr, sum_by=sum_by, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)s50th percentile' % legend, refId: 'B_native', }, { - expr: $.showClassicHistogramQuery($.nativeClassicHistogramAverageRate(metricStr, selectorStr, multiplier=multiplier, from_recording=true)), + expr: $.showClassicHistogramQuery($.ncHistogramAverageRate(metricStr, selectorStr, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)sAverage' % legend, refId: 'C_classic', }, { - expr: $.showNativeHistogramQuery($.nativeClassicHistogramAverageRate(metricStr, selectorStr, multiplier=multiplier, from_recording=true)), + expr: $.showNativeHistogramQuery($.ncHistogramAverageRate(metricStr, selectorStr, multiplier=multiplier, from_recording=true)), format: 'time_series', legendFormat: '%(legend)sAverage' % legend, refId: 'C_native',