mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-24 21:24:05 -08:00
promql: use natural sort in sort_by_label and sort_by_label_desc (#13411)
These functions are intended for humans, as robots can already sort the results however they please. Humans like things sorted "naturally": * https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ A similar thing has been done to Grafana, which is also used by humans: * https://github.com/grafana/grafana/pull/78024 * https://github.com/grafana/grafana/pull/78494 Signed-off-by: Ivan Babrou <github@ivan.computer>
This commit is contained in:
parent
7153f61790
commit
a6b35ff304
|
@ -594,6 +594,8 @@ Same as `sort`, but sorts in descending order.
|
|||
|
||||
Please note that the sort by label functions only affect the results of instant queries, as range query results always have a fixed output ordering.
|
||||
|
||||
This function uses [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order).
|
||||
|
||||
## `sort_by_label_desc()`
|
||||
|
||||
**This function has to be enabled via the [feature flag](../feature_flags/) `--enable-feature=promql-experimental-functions`.**
|
||||
|
@ -602,6 +604,8 @@ Same as `sort_by_label`, but sorts in descending order.
|
|||
|
||||
Please note that the sort by label functions only affect the results of instant queries, as range query results always have a fixed output ordering.
|
||||
|
||||
This function uses [natural sort order](https://en.wikipedia.org/wiki/Natural_sort_order).
|
||||
|
||||
## `sqrt()`
|
||||
|
||||
`sqrt(v instant-vector)` calculates the square root of all elements in `v`.
|
||||
|
|
1
go.mod
1
go.mod
|
@ -19,6 +19,7 @@ require (
|
|||
github.com/edsrzf/mmap-go v1.1.0
|
||||
github.com/envoyproxy/go-control-plane v0.11.1
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-kit/log v0.2.1
|
||||
github.com/go-logfmt/logfmt v0.6.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -166,6 +166,8 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBF
|
|||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
|
||||
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/facette/natsort"
|
||||
"github.com/grafana/regexp"
|
||||
"github.com/prometheus/common/model"
|
||||
"golang.org/x/exp/slices"
|
||||
|
@ -380,15 +381,16 @@ func funcSortByLabel(vals []parser.Value, args parser.Expressions, enh *EvalNode
|
|||
for _, label := range labels {
|
||||
lv1 := a.Metric.Get(label)
|
||||
lv2 := b.Metric.Get(label)
|
||||
// 0 if a == b, -1 if a < b, and +1 if a > b.
|
||||
switch strings.Compare(lv1, lv2) {
|
||||
case -1:
|
||||
return -1
|
||||
case +1:
|
||||
return +1
|
||||
default:
|
||||
|
||||
if lv1 == lv2 {
|
||||
continue
|
||||
}
|
||||
|
||||
if natsort.Compare(lv1, lv2) {
|
||||
return -1
|
||||
}
|
||||
|
||||
return +1
|
||||
}
|
||||
|
||||
return 0
|
||||
|
@ -409,19 +411,16 @@ func funcSortByLabelDesc(vals []parser.Value, args parser.Expressions, enh *Eval
|
|||
for _, label := range labels {
|
||||
lv1 := a.Metric.Get(label)
|
||||
lv2 := b.Metric.Get(label)
|
||||
// If label values are the same, continue to the next label
|
||||
|
||||
if lv1 == lv2 {
|
||||
continue
|
||||
}
|
||||
// 0 if a == b, -1 if a < b, and +1 if a > b.
|
||||
switch strings.Compare(lv1, lv2) {
|
||||
case -1:
|
||||
|
||||
if natsort.Compare(lv1, lv2) {
|
||||
return +1
|
||||
case +1:
|
||||
return -1
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
|
|
35
promql/testdata/functions.test
vendored
35
promql/testdata/functions.test
vendored
|
@ -482,6 +482,19 @@ load 5m
|
|||
http_requests{job="app-server", instance="0", group="canary"} 0+70x10
|
||||
http_requests{job="app-server", instance="1", group="canary"} 0+80x10
|
||||
http_requests{job="api-server", instance="2", group="production"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="0"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="1"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="2"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="3"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="10"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="11"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="12"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="20"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="21"} 0+10x10
|
||||
cpu_time_total{job="cpu", cpu="100"} 0+10x10
|
||||
node_uname_info{job="node_exporter", instance="4m600", release="1.2.3"} 0+10x10
|
||||
node_uname_info{job="node_exporter", instance="4m5", release="1.11.3"} 0+10x10
|
||||
node_uname_info{job="node_exporter", instance="4m1000", release="1.111.3"} 0+10x10
|
||||
|
||||
eval_ordered instant at 50m sort_by_label(http_requests, "instance")
|
||||
http_requests{group="production", instance="0", job="api-server"} 100
|
||||
|
@ -579,6 +592,28 @@ eval_ordered instant at 50m sort_by_label_desc(http_requests, "instance", "group
|
|||
http_requests{group="canary", instance="0", job="app-server"} 700
|
||||
http_requests{group="canary", instance="0", job="api-server"} 300
|
||||
|
||||
eval_ordered instant at 50m sort_by_label(cpu_time_total, "cpu")
|
||||
cpu_time_total{job="cpu", cpu="0"} 100
|
||||
cpu_time_total{job="cpu", cpu="1"} 100
|
||||
cpu_time_total{job="cpu", cpu="2"} 100
|
||||
cpu_time_total{job="cpu", cpu="3"} 100
|
||||
cpu_time_total{job="cpu", cpu="10"} 100
|
||||
cpu_time_total{job="cpu", cpu="11"} 100
|
||||
cpu_time_total{job="cpu", cpu="12"} 100
|
||||
cpu_time_total{job="cpu", cpu="20"} 100
|
||||
cpu_time_total{job="cpu", cpu="21"} 100
|
||||
cpu_time_total{job="cpu", cpu="100"} 100
|
||||
|
||||
eval_ordered instant at 50m sort_by_label(node_uname_info, "instance")
|
||||
node_uname_info{job="node_exporter", instance="4m5", release="1.11.3"} 100
|
||||
node_uname_info{job="node_exporter", instance="4m600", release="1.2.3"} 100
|
||||
node_uname_info{job="node_exporter", instance="4m1000", release="1.111.3"} 100
|
||||
|
||||
eval_ordered instant at 50m sort_by_label(node_uname_info, "release")
|
||||
node_uname_info{job="node_exporter", instance="4m600", release="1.2.3"} 100
|
||||
node_uname_info{job="node_exporter", instance="4m5", release="1.11.3"} 100
|
||||
node_uname_info{job="node_exporter", instance="4m1000", release="1.111.3"} 100
|
||||
|
||||
# Tests for holt_winters
|
||||
clear
|
||||
|
||||
|
|
Loading…
Reference in a new issue