// Code generated by qtc from "expand-with-exprs.qtpl". DO NOT EDIT.
// See https://github.com/valyala/quicktemplate for details.
//line app/vmselect/prometheus/expand-with-exprs.qtpl:1
package prometheus
//line app/vmselect/prometheus/expand-with-exprs.qtpl:1
import (
"fmt"
"github.com/VictoriaMetrics/metricsql"
)
// ExpandWithExprsResponse returns a webpage, which expands with templates in q MetricsQL.
//line app/vmselect/prometheus/expand-with-exprs.qtpl:9
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:9
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:9
func StreamExpandWithExprsResponse(qw422016 *qt422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:9
qw422016.N().S(`
Expand WITH expressions`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:37
streamwithExprsTutorial(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:37
qw422016.N().S(`
`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
func WriteExpandWithExprsResponse(qq422016 qtio422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
StreamExpandWithExprsResponse(qw422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
func ExpandWithExprsResponse(q string) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
WriteExpandWithExprsResponse(qb422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:41
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:43
func streamexpandWithExprs(qw422016 *qt422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:44
if len(q) == 0 {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:45
return
//line app/vmselect/prometheus/expand-with-exprs.qtpl:46
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:48
expr, err := metricsql.Parse(q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:49
if err != nil {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:49
qw422016.N().S(`Cannot parse query:`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:50
qw422016.E().V(err)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:51
} else {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:52
expr = metricsql.Optimize(expr)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:53
qw422016.E().Z(expr.AppendString(nil))
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
func writeexpandWithExprs(qq422016 qtio422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
streamexpandWithExprs(qw422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
func expandWithExprs(q string) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
writeexpandWithExprs(qb422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:55
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:57
func StreamExpandWithExprsJSONResponse(qw422016 *qt422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
if len(q) == 0 {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
qw422016.N().S(`{"status": "error","error": "query string cannot be empty"}`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:63
return
//line app/vmselect/prometheus/expand-with-exprs.qtpl:64
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:64
qw422016.N().S(`{`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:67
expr, err := metricsql.Parse(q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:68
if err != nil {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:68
qw422016.N().S(`"status": "error","error":`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:70
qw422016.E().Q(fmt.Sprintf("Cannot parse query: %s", err))
//line app/vmselect/prometheus/expand-with-exprs.qtpl:71
} else {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:72
expr = metricsql.Optimize(expr)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:72
qw422016.N().S(`"status": "success","expr":`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:74
qw422016.E().QZ(expr.AppendString(nil))
//line app/vmselect/prometheus/expand-with-exprs.qtpl:75
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:75
qw422016.N().S(`}`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
func WriteExpandWithExprsJSONResponse(qq422016 qtio422016.Writer, q string) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
StreamExpandWithExprsJSONResponse(qw422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
func ExpandWithExprsJSONResponse(q string) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
WriteExpandWithExprsJSONResponse(qb422016, q)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:77
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:81
func streamwithExprsTutorial(qw422016 *qt422016.Writer) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:81
qw422016.N().S(`
Tutorial for WITH expressions in MetricsQL
Let's look at the following real query from Node Exporter Full dashboard:
(
(
node_memory_MemTotal_bytes{instance=~"$node:$port", job=~"$job"}
-
node_memory_MemFree_bytes{instance=~"$node:$port", job=~"$job"}
)
/
node_memory_MemTotal_bytes{instance=~"$node:$port", job=~"$job"}
)
*
100
It is clear the query calculates the percentage of used memory
for the given $node, $port and $job. Isn't it? :)
What's wrong with this query? Copy-pasted label filters for distinct timeseries
which makes it easy to mistype these filters during modification.
Let's simplify the query with WITH expressions:
WITH (
commonFilters = {instance=~"$node:$port",job=~"$job"}
)
(
node_memory_MemTotal_bytes{commonFilters}
-
node_memory_MemFree_bytes{commonFilters}
)
/
node_memory_MemTotal_bytes{commonFilters} * 100
Now label filters are located in a single place instead of three distinct places.
The query mentions node_memory_MemTotal_bytes metric twice and {commonFilters}
three times. WITH expressions may improve this:
WITH (
my_resource_utilization(free, limit, filters) = (limit{filters} - free{filters}) / limit{filters} * 100
)
my_resource_utilization(
node_memory_MemFree_bytes,
node_memory_MemTotal_bytes,
{instance=~"$node:$port",job=~"$job"},
)
Now the template function my_resource_utilization() may be used for monitoring arbitrary
resources - memory, CPU, network, storage, you name it.
Let's take another nice query from Node Exporter Full dashboard:
(
(
(
count(
count(node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"}) by (cpu)
)
)
-
avg(
sum by (mode) (rate(node_cpu_seconds_total{mode='idle',instance=~"$node:$port",job=~"$job"}[5m]))
)
)
*
100
)
/
count(
count(node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"}) by (cpu)
)
Do you understand what does this mess do? Is it manageable? :) WITH expressions are happy to help in a few iterations.
1. Extract common filters used in multiple places into a commonFilters variable:
WITH (
commonFilters = {instance=~"$node:$port",job=~"$job"}
)
(
(
(
count(
count(node_cpu_seconds_total{commonFilters}) by (cpu)
)
)
-
avg(
sum by (mode) (rate(node_cpu_seconds_total{mode='idle',commonFilters}[5m]))
)
)
*
100
)
/
count(
count(node_cpu_seconds_total{commonFilters}) by (cpu)
)
2. Extract "count(count(...) by (cpu))" into cpuCount variable:
WITH (
commonFilters = {instance=~"$node:$port",job=~"$job"},
cpuCount = count(count(node_cpu_seconds_total{commonFilters}) by (cpu))
)
(
(
cpuCount
-
avg(
sum by (mode) (rate(node_cpu_seconds_total{mode='idle',commonFilters}[5m]))
)
)
*
100
) / cpuCount
3. Extract rate(...) part into cpuIdle variable, since it is clear now that this part calculates the number of idle CPUs:
WITH (
commonFilters = {instance=~"$node:$port",job=~"$job"},
cpuCount = count(count(node_cpu_seconds_total{commonFilters}) by (cpu)),
cpuIdle = sum(rate(node_cpu_seconds_total{mode='idle',commonFilters}[5m]))
)
((cpuCount - cpuIdle) * 100) / cpuCount
4. Put node_cpu_seconds_total{commonFilters} into its own varialbe with the name cpuSeconds:
WITH (
cpuSeconds = node_cpu_seconds_total{instance=~"$node:$port",job=~"$job"},
cpuCount = count(count(cpuSeconds) by (cpu)),
cpuIdle = sum(rate(cpuSeconds{mode='idle'}[5m]))
)
((cpuCount - cpuIdle) * 100) / cpuCount
Now the query became more clear comparing to the initial query.
WITH expressions may be nested and may be put anywhere. Try expanding the following query:
WITH (
f(a, b) = WITH (
f1(x) = b-x,
f2(x) = x+x
) f1(a)*f2(b)
) f(foo, with(x=bar) x)
`)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
func writewithExprsTutorial(qq422016 qtio422016.Writer) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
qw422016 := qt422016.AcquireWriter(qq422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
streamwithExprsTutorial(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
qt422016.ReleaseWriter(qw422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
func withExprsTutorial() string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
qb422016 := qt422016.AcquireByteBuffer()
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
writewithExprsTutorial(qb422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
qs422016 := string(qb422016.B)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
qt422016.ReleaseByteBuffer(qb422016)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:268
}