Skip to content

Set quantile value to NAN if there are no samples provided for an age #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Throw an error when http_middelware is processing a wrong handler [#199](https://github.com/tarantool/metrics/issues/199)
- cartridge issues metric fails before cartridge.cfg() call [#298](https://github.com/tarantool/metrics/issues/298)

### Changed
- quantile metric is NAN if no samples provided for an age [#303](https://github.com/tarantool/metrics/issues/303)

## [0.10.0] - 2021-08-03
### Changed
- metrics registry refactoring to search with `O(1)` [#188](https://github.com/tarantool/metrics/issues/188)
Expand Down
2 changes: 1 addition & 1 deletion doc/monitoring/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Summary
see :ref:`counter_obj:collect() <counter-collect>`.
If ``max_age_time`` and ``age_buckets_count`` are set, quantile observations
will be collect only from the head bucket in sliding window and not from every
bucket.
bucket. If there was no observations returns NaN in values.

.. method:: remove(label_pairs)

Expand Down
1 change: 1 addition & 0 deletions metrics-scm-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ build = {
['metrics.collectors.counter'] = 'metrics/collectors/counter.lua',
['metrics.collectors.gauge'] = 'metrics/collectors/gauge.lua',
['metrics.collectors.histogram'] = 'metrics/collectors/histogram.lua',
['metrics.const'] = 'metrics/const.lua',
['metrics.plugins.graphite'] = 'metrics/plugins/graphite.lua',
['metrics.plugins.prometheus'] = 'metrics/plugins/prometheus.lua',
['metrics.plugins.json'] = 'metrics/plugins/json.lua',
Expand Down
4 changes: 4 additions & 0 deletions metrics/const.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
return {
INF = math.huge,
NAN = math.huge * 0,
}
5 changes: 3 additions & 2 deletions metrics/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
local checks = require('checks')
local log = require('log')

local Const = require('metrics.const')
local Registry = require('metrics.registry')

local Counter = require('metrics.collectors.counter')
Expand Down Expand Up @@ -108,8 +109,8 @@ return {
histogram = histogram,
summary = summary,

INF = math.huge,
NAN = math.huge * 0,
INF = Const.INF,
NAN = Const.NAN,

clear = clear,
collectors = collectors,
Expand Down
7 changes: 7 additions & 0 deletions metrics/quantile.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local ffi = require('ffi')
local const = require('metrics.const')

local quantile = {}

Expand Down Expand Up @@ -270,6 +271,12 @@ function quantile.Query(stream_obj, q)
-- Fast path when there hasn't been enough data for a flush;
-- this also yields better accuracy for small sets of data.
local l = stream_obj.b_len

-- if buffer is empty and wasn't flushed yet then quantile value is NaN
if l == 0 then
return const.NAN
end

local i = math.modf(l * q)
stream_obj:maybe_sort()
return stream_obj.b[i]
Expand Down
20 changes: 17 additions & 3 deletions test/quantile_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ g.test_query_on_empty_quantile = function()

local res = quantile.Query(emptyQuantile, 0.99)

t.assert_equals(res, math.huge)
t.assert_nan(res)
end

g.test_reset = function()
Expand All @@ -156,12 +156,12 @@ g.test_reset = function()
end

local res = quantile.Query(Quantile, 0.99)
t.assert_not_equals(res, math.huge)
t.assert_not_nan(res)

quantile.Reset(Quantile)

res = quantile.Query(Quantile, 0.99)
t.assert_equals(res, math.huge)
t.assert_nan(res)
end

g.test_quantile_insert_works_after_reset = function()
Expand All @@ -174,3 +174,17 @@ g.test_quantile_insert_works_after_reset = function()
local res = quantile.Query(Quantile, 0.5)
t.assert_not_equals(res, math.huge)
end

g.test_quantile_values_present_after_buffer_flush = function()
local Quantile = quantile.NewTargeted({[0.5]=0.01, [0.9]=0.01, [0.99]=0.01}, 10)

for _ = 1, 10 do
quantile.Insert(Quantile, math.random())
end

t.assert(Quantile:flushed())
-- buffer now is flushed

local res = quantile.Query(Quantile, 0.5)
t.assert_not_nan(res)
end