mirror of
https://github.com/prometheus/prometheus.git
synced 2025-02-21 03:16:00 -08:00
Merge pull request #508 from brian-brazil/round
Change the 2nd argument of round to toNearest.
This commit is contained in:
commit
6e296648ed
|
@ -31,14 +31,16 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stalenessDelta = flag.Duration("query.staleness-delta", 300*time.Second, "Staleness delta allowance during expression evaluations.")
|
stalenessDelta = flag.Duration("query.staleness-delta", 300*time.Second, "Staleness delta allowance during expression evaluations.")
|
||||||
queryTimeout = flag.Duration("query.timeout", 2*time.Minute, "Maximum time a query may take before being aborted.")
|
queryTimeout = flag.Duration("query.timeout", 2*time.Minute, "Maximum time a query may take before being aborted.")
|
||||||
)
|
)
|
||||||
|
|
||||||
type queryTimeoutError struct {
|
type queryTimeoutError struct {
|
||||||
timeoutAfter time.Duration
|
timeoutAfter time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e queryTimeoutError) Error() string { return fmt.Sprintf("query timeout after %v", e.timeoutAfter) }
|
func (e queryTimeoutError) Error() string {
|
||||||
|
return fmt.Sprintf("query timeout after %v", e.timeoutAfter)
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Raw data value types.
|
// Raw data value types.
|
||||||
|
|
|
@ -291,28 +291,22 @@ func dropCommonLabelsImpl(timestamp clientmodel.Timestamp, args []Node) interfac
|
||||||
return vector
|
return vector
|
||||||
}
|
}
|
||||||
|
|
||||||
// === round(vector VectorNode) Vector ===
|
// === round(vector VectorNode, toNearest=1 Scalar) Vector ===
|
||||||
func roundImpl(timestamp clientmodel.Timestamp, args []Node) interface{} {
|
func roundImpl(timestamp clientmodel.Timestamp, args []Node) interface{} {
|
||||||
// round returns a number rounded to nearest integer.
|
// round returns a number rounded to toNearest.
|
||||||
// Ties are solved by rounding towards the even integer.
|
// Ties are solved by rounding up.
|
||||||
round := func(n float64) float64 {
|
toNearest := float64(1)
|
||||||
if n-math.Floor(n) == 0.5 && int64(n)%2 == 0 {
|
|
||||||
n += math.Copysign(0.5, -n)
|
|
||||||
}
|
|
||||||
return math.Copysign(math.Floor(math.Abs(n)+0.5), n)
|
|
||||||
}
|
|
||||||
|
|
||||||
places := float64(0)
|
|
||||||
if len(args) >= 2 {
|
if len(args) >= 2 {
|
||||||
places = float64(args[1].(ScalarNode).Eval(timestamp))
|
toNearest = float64(args[1].(ScalarNode).Eval(timestamp))
|
||||||
}
|
}
|
||||||
pow := math.Pow(10, places)
|
// Invert as it seems to cause fewer floating point accuracy issues.
|
||||||
|
toNearestInverse := 1.0 / toNearest
|
||||||
|
|
||||||
n := args[0].(VectorNode)
|
n := args[0].(VectorNode)
|
||||||
vector := n.Eval(timestamp)
|
vector := n.Eval(timestamp)
|
||||||
for _, el := range vector {
|
for _, el := range vector {
|
||||||
el.Metric.Delete(clientmodel.MetricNameLabel)
|
el.Metric.Delete(clientmodel.MetricNameLabel)
|
||||||
el.Value = clientmodel.SampleValue(round(pow*float64(el.Value)) / pow)
|
el.Value = clientmodel.SampleValue(math.Floor(float64(el.Value)*toNearestInverse+0.5) / toNearestInverse)
|
||||||
}
|
}
|
||||||
return vector
|
return vector
|
||||||
}
|
}
|
||||||
|
|
|
@ -527,16 +527,16 @@ func TestExpressions(t *testing.T) {
|
||||||
{ // Round should correctly handle negative numbers.
|
{ // Round should correctly handle negative numbers.
|
||||||
expr: `round(-1 * (0.004 * http_requests{group="production",job="api-server"}))`,
|
expr: `round(-1 * (0.004 * http_requests{group="production",job="api-server"}))`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => -0 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 0 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => -1 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => -1 @[%v]`,
|
||||||
},
|
},
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{ // Round should round half to even.
|
{ // Round should round half up.
|
||||||
expr: `round(0.005 * http_requests{group="production",job="api-server"})`,
|
expr: `round(0.005 * http_requests{group="production",job="api-server"})`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => 0 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 1 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => 1 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => 1 @[%v]`,
|
||||||
},
|
},
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
|
@ -551,7 +551,7 @@ func TestExpressions(t *testing.T) {
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{ // Round should round half to even.
|
{
|
||||||
expr: `round(1 + 0.005 * http_requests{group="production",job="api-server"})`,
|
expr: `round(1 + 0.005 * http_requests{group="production",job="api-server"})`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => 2 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 2 @[%v]`,
|
||||||
|
@ -563,23 +563,23 @@ func TestExpressions(t *testing.T) {
|
||||||
{
|
{
|
||||||
expr: `round(-1 * (1 + 0.005 * http_requests{group="production",job="api-server"}))`,
|
expr: `round(-1 * (1 + 0.005 * http_requests{group="production",job="api-server"}))`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => -2 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => -1 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => -2 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => -2 @[%v]`,
|
||||||
},
|
},
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{ // Round should accept a number of decimal places to round to.
|
{ // Round should accept the number to round nearest to.
|
||||||
expr: `round(0.0005 * http_requests{group="production",job="api-server"}, 1)`,
|
expr: `round(0.0005 * http_requests{group="production",job="api-server"}, 0.1)`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => 0 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 0.1 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => 0.1 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => 0.1 @[%v]`,
|
||||||
},
|
},
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{ // Round should look at last decimal place parity.
|
{
|
||||||
expr: `round(2.1 + 0.0005 * http_requests{group="production",job="api-server"}, 1)`,
|
expr: `round(2.1 + 0.0005 * http_requests{group="production",job="api-server"}, 0.1)`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => 2.2 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 2.2 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => 2.2 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => 2.2 @[%v]`,
|
||||||
|
@ -588,16 +588,16 @@ func TestExpressions(t *testing.T) {
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expr: `round(5.2 + 0.0005 * http_requests{group="production",job="api-server"}, 1)`,
|
expr: `round(5.2 + 0.0005 * http_requests{group="production",job="api-server"}, 0.1)`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => 5.2 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => 5.3 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => 5.3 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => 5.3 @[%v]`,
|
||||||
},
|
},
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
{ // Round should work correctly with negative numbers and multiple decimal places.
|
{ // Round should work correctly with negative numbers and multiple decimal places.
|
||||||
expr: `round(-1 * (5.2 + 0.0005 * http_requests{group="production",job="api-server"}), 1)`,
|
expr: `round(-1 * (5.2 + 0.0005 * http_requests{group="production",job="api-server"}), 0.1)`,
|
||||||
output: []string{
|
output: []string{
|
||||||
`{group="production", instance="0", job="api-server"} => -5.2 @[%v]`,
|
`{group="production", instance="0", job="api-server"} => -5.2 @[%v]`,
|
||||||
`{group="production", instance="1", job="api-server"} => -5.3 @[%v]`,
|
`{group="production", instance="1", job="api-server"} => -5.3 @[%v]`,
|
||||||
|
@ -605,6 +605,24 @@ func TestExpressions(t *testing.T) {
|
||||||
fullRanges: 0,
|
fullRanges: 0,
|
||||||
intervalRanges: 2,
|
intervalRanges: 2,
|
||||||
},
|
},
|
||||||
|
{ // Round should work correctly with big toNearests.
|
||||||
|
expr: `round(0.025 * http_requests{group="production",job="api-server"}, 5)`,
|
||||||
|
output: []string{
|
||||||
|
`{group="production", instance="0", job="api-server"} => 5 @[%v]`,
|
||||||
|
`{group="production", instance="1", job="api-server"} => 5 @[%v]`,
|
||||||
|
},
|
||||||
|
fullRanges: 0,
|
||||||
|
intervalRanges: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expr: `round(0.045 * http_requests{group="production",job="api-server"}, 5)`,
|
||||||
|
output: []string{
|
||||||
|
`{group="production", instance="0", job="api-server"} => 5 @[%v]`,
|
||||||
|
`{group="production", instance="1", job="api-server"} => 10 @[%v]`,
|
||||||
|
},
|
||||||
|
fullRanges: 0,
|
||||||
|
intervalRanges: 2,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
expr: `avg_over_time(http_requests{group="production",job="api-server"}[1h])`,
|
expr: `avg_over_time(http_requests{group="production",job="api-server"}[1h])`,
|
||||||
output: []string{
|
output: []string{
|
||||||
|
|
Loading…
Reference in a new issue