Skip to content

Commit

Permalink
percentileOfSeries: return first of filtered datapoints in case only …
Browse files Browse the repository at this point in the history
…one series have valid data

percentileOfSeries should return first of filtered datapoints and not first of all datapoints in case
all other series have NaNs for the values.

Fixes #516
  • Loading branch information
Civil committed Aug 19, 2020
1 parent 4f73530 commit cf06aa7
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ CHANGELOG
- [Fix] prometheus backend: carbonapi should send 'end' instead of 'stop' in queries (thx to Alexandre Vincent)
- [Fix] change metrics resulting tags to match graphite-web in some cases (thx to @Felixoid)
- [Fix] Prometheus backend: trust timestamps from the backend (Fixes #504, Fixes #514)
- [Fix] percentileOfSeries: return first of filtered datapoints in case only one series have valid data (Fixes #516)
- [Code] merge aliasByNode and aliasByTags (thx to @Felixoid)

**0.14.0**
Expand Down
9 changes: 9 additions & 0 deletions cmd/mockbackend/e2etesting.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"io/ioutil"
"math"
"net/http"
"net/url"
"strconv"
Expand Down Expand Up @@ -74,6 +75,10 @@ func (d *Datapoint) UnmarshalJSON(data []byte) error {
return fmt.Errorf("failed to parse Timestamp: %v", err)
}

if valueStr == "null" || valueStr == "\"null\"" {
d.Value = math.NaN()
return nil
}
d.Value, err = strconv.ParseFloat(valueStr, 64)
if err != nil {
return fmt.Errorf("failed to parse Value: %v", err)
Expand Down Expand Up @@ -101,6 +106,10 @@ func (d *Datapoint) UnmarshalYAML(unmarshal func(interface{}) error) error {
return fmt.Errorf("failed to parse Timestamp: %v", err)
}

if valueStr == "null" || valueStr == "\"null\"" {
d.Value = math.NaN()
return nil
}
d.Value, err = strconv.ParseFloat(valueStr, 64)
if err != nil {
return fmt.Errorf("failed to parse Value: %v", err)
Expand Down
36 changes: 36 additions & 0 deletions cmd/mockbackend/testcases/i516/i516.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
version: "v1"
test:
apps:
- name: "carbonapi"
binary: "./carbonapi"
args:
- "-config"
- "./cmd/mockbackend/carbonapi_singlebackend.yaml"
queries:
- endpoint: "http://127.0.0.1:8081"
delay: 1
type: "GET"
URL: "/render?format=json&target=percentileOfSeries(carbon.api.*.cache_size, 95, false)"
expectedResponse:
httpCode: 200
contentType: "application/json"
expectedResults:
- metrics:
- target: "percentileOfSeries(carbon.api.*.cache_size, 95, false)"
datapoints: [[0.0, 1],[0.0, 2],[0.0, 3],[100500.0, 4],[100500.0, 5],[100500.0, 6]]
listeners:
- address: ":9070"
expressions:
"carbon.api.*.cache_size":
pathExpression: "carbon.api.*.cache_size"
data:
- metricName: "carbon.api.host001.cache_size"
values: [.NaN, .NaN, .NaN, .NaN, .NaN, .NaN]
- metricName: "carbon.api.host002.cache_size"
values: [.NaN, .NaN, .NaN, .NaN, .NaN, .NaN]
- metricName: "carbon.api.host003.cache_size"
values: [0.0, 0.0, 0.0, 100500.0, 100500.0, 100500.0]
- metricName: "carbon.api.host004.cache_size"
values: [.NaN, .NaN, .NaN, .NaN, .NaN, .NaN]
- metricName: "carbon.api.host005.cache_size"
values: [.NaN, .NaN, .NaN, .NaN, .NaN, .NaN]
4 changes: 4 additions & 0 deletions e2e_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

TESTS=$(ls cmd/mockbackend/testcases/)

if [[ ! -z "${1}" ]]; then
TESTS="${1}"
fi

FAILED_TESTS=""
for t in ${TESTS}; do
if [[ "${TRAVIS}" == "true" ]]; then
Expand Down
2 changes: 1 addition & 1 deletion expr/consolidations/consolidations.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func Percentile(data []float64, percent float64, interpolate bool) float64 {
return math.NaN()
}
if len(dataFiltered) == 1 {
return data[0]
return dataFiltered[0]
}

k := (float64(len(dataFiltered)-1) * percent) / 100
Expand Down
13 changes: 13 additions & 0 deletions expr/functions/percentileOfSeries/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ func TestPercentileOfSeriesSeries(t *testing.T) {
},
[]*types.MetricData{types.MakeMetricData("percentileOfSeries(metric1.foo.*.*,50,interpolate=true)", []float64{6.5, 7.5, 8.5, 9.5, 11, math.NaN()}, 1, now32)},
},
{
`percentileOfSeries(metric1.foo.*.*,95,false)`,
map[parser.MetricRequest][]*types.MetricData{
{"metric1.foo.*.*", 0, 1}: {
types.MakeMetricData("metric1.foo.bar1.qux", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN()}, 1, now32),
types.MakeMetricData("metric1.foo.bar2.qux", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 0}, 1, now32),
types.MakeMetricData("metric1.foo.bar3.qux", []float64{0, 0, 0, 100500, 100501, 1005002}, 1, now32),
types.MakeMetricData("metric1.foo.bar4.qux", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 0}, 1, now32),
types.MakeMetricData("metric1.foo.bar5.qux", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.NaN(), 0}, 1, now32),
},
},
[]*types.MetricData{types.MakeMetricData("percentileOfSeries(metric1.foo.*.*,95,false)", []float64{0, 0, 0, 100500, 100501, 1005002}, 1, now32)},
},
}

for _, tt := range tests {
Expand Down

0 comments on commit cf06aa7

Please sign in to comment.