2022-12-15 00:01:33 +00:00
// 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 (
"github.com/VictoriaMetrics/metricsql"
)
// ExpandWithExprsResponse returns a webpage, which expands with templates in q MetricsQL.
//line app/vmselect/prometheus/expand-with-exprs.qtpl:8
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:8
var (
_ = qtio422016 . Copy
_ = qt422016 . AcquireByteBuffer
)
//line app/vmselect/prometheus/expand-with-exprs.qtpl:8
func StreamExpandWithExprsResponse ( qw422016 * qt422016 . Writer , q string ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:8
qw422016 . N ( ) . S ( ` <html><head><title>Expand WITH expressions</title><style>p { font-weight: bold }textarea { margin: 1em }</style></head><body><div><form method="get"><div><p><a href="https://docs.victoriametrics.com/MetricsQL.html">MetricsQL</a> query with optional WITH expressions:</p><textarea name="query" style="height: 15em; width: 90%"> ` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:25
qw422016 . E ( ) . S ( q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:25
qw422016 . N ( ) . S ( ` </textarea><br/><input type="submit" value="Expand" /><p><a href="https://docs.victoriametrics.com/MetricsQL.html">MetricsQL</a> query after expanding WITH expressions and applying other optimizations:</p><textarea style="height: 5em; width: 90%" readonly="readonly"> ` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:31
streamexpandWithExprs ( qw422016 , q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:31
qw422016 . N ( ) . S ( ` </textarea></div></form></div><div> ` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:36
streamwithExprsTutorial ( qw422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:36
qw422016 . N ( ) . S ( ` </div></body></html> ` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
func WriteExpandWithExprsResponse ( qq422016 qtio422016 . Writer , q string ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
qw422016 := qt422016 . AcquireWriter ( qq422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
StreamExpandWithExprsResponse ( qw422016 , q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
qt422016 . ReleaseWriter ( qw422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
func ExpandWithExprsResponse ( q string ) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
qb422016 := qt422016 . AcquireByteBuffer ( )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
WriteExpandWithExprsResponse ( qb422016 , q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
qs422016 := string ( qb422016 . B )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
qt422016 . ReleaseByteBuffer ( qb422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:40
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:42
func streamexpandWithExprs ( qw422016 * qt422016 . Writer , q string ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:43
if len ( q ) == 0 {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:44
return
//line app/vmselect/prometheus/expand-with-exprs.qtpl:45
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:47
expr , err := metricsql . Parse ( q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:48
if err != nil {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:48
qw422016 . N ( ) . S ( ` Cannot parse query: ` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:49
qw422016 . E ( ) . V ( err )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:50
} else {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:51
expr = metricsql . Optimize ( expr )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:52
qw422016 . E ( ) . Z ( expr . AppendString ( nil ) )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:53
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
func writeexpandWithExprs ( qq422016 qtio422016 . Writer , q string ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
qw422016 := qt422016 . AcquireWriter ( qq422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
streamexpandWithExprs ( qw422016 , q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
qt422016 . ReleaseWriter ( qw422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
func expandWithExprs ( q string ) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
qb422016 := qt422016 . AcquireByteBuffer ( )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
writeexpandWithExprs ( qb422016 , q )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
qs422016 := string ( qb422016 . B )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
qt422016 . ReleaseByteBuffer ( qb422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:54
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
func streamwithExprsTutorial ( qw422016 * qt422016 . Writer ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:58
qw422016 . N ( ) . S ( `
< h3 > Tutorial for WITH expressions in < a href = "https://docs.victoriametrics.com/MetricsQL.html" > MetricsQL < / a > < / h3 >
< p >
2022-12-25 16:36:20 +00:00
Let ' s look at the following real query from < a href = "https://grafana.com/grafana/dashboards/1860-node-exporter-full/" > Node Exporter Full < / a > dashboard :
2022-12-15 00:01:33 +00:00
< / p >
< pre >
(
(
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
< / pre >
< p >
It is clear the query calculates the percentage of used memory
for the given $ node , $ port and $ job . Isn ' t it ? : )
< / p >
< p >
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 :
< / p >
< pre >
WITH (
commonFilters = { instance = ~ "$node:$port" , job = ~ "$job" }
)
(
node_memory_MemTotal_bytes { commonFilters }
-
node_memory_MemFree_bytes { commonFilters }
)
/
node_memory_MemTotal_bytes { commonFilters } * 100
< / pre >
< p >
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 :
< / p >
< pre >
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" } ,
)
< / pre >
< p >
Now the template function my_resource_utilization ( ) may be used for monitoring arbitrary
resources - memory , CPU , network , storage , you name it .
< / p >
< p >
2022-12-25 16:36:20 +00:00
Let ' s take another nice query from < a href = "https://grafana.com/grafana/dashboards/1860-node-exporter-full/" > Node Exporter Full < / a > dashboard :
2022-12-15 00:01:33 +00:00
< / p >
< pre >
(
(
(
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" } [ 5 m ] ) )
)
)
*
100
)
/
count (
count ( node_cpu_seconds_total { instance = ~ "$node:$port" , job = ~ "$job" } ) by ( cpu )
)
< / pre >
< p >
Do you understand what does this mess do ? Is it manageable ? : ) WITH expressions are happy to help in a few iterations .
< br / >
< br / >
1. Extract common filters used in multiple places into a commonFilters variable :
< / p >
< pre >
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 } [ 5 m ] ) )
)
)
*
100
)
/
count (
count ( node_cpu_seconds_total { commonFilters } ) by ( cpu )
)
< / pre >
< p >
2. Extract "count(count(...) by (cpu))" into cpuCount variable :
< / p >
< pre >
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 } [ 5 m ] ) )
)
)
*
100
) / cpuCount
< / pre >
< p >
3. Extract rate ( ... ) part into cpuIdle variable , since it is clear now that this part calculates the number of idle CPUs :
< / p >
< pre >
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 } [ 5 m ] ) )
)
( ( cpuCount - cpuIdle ) * 100 ) / cpuCount
< / pre >
< p >
4. Put node_cpu_seconds_total { commonFilters } into its own varialbe with the name cpuSeconds :
< / p >
< pre >
WITH (
cpuSeconds = node_cpu_seconds_total { instance = ~ "$node:$port" , job = ~ "$job" } ,
cpuCount = count ( count ( cpuSeconds ) by ( cpu ) ) ,
cpuIdle = sum ( rate ( cpuSeconds { mode = ' idle ' } [ 5 m ] ) )
)
( ( cpuCount - cpuIdle ) * 100 ) / cpuCount
< / pre >
< p >
Now the query became more clear comparing to the initial query .
< / p >
< p >
WITH expressions may be nested and may be put anywhere . Try expanding the following query :
< / p >
< pre >
WITH (
f ( a , b ) = WITH (
f1 ( x ) = b - x ,
f2 ( x ) = x + x
) f1 ( a ) * f2 ( b )
) f ( foo , with ( x = bar ) x )
< / pre >
` )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
func writewithExprsTutorial ( qq422016 qtio422016 . Writer ) {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
qw422016 := qt422016 . AcquireWriter ( qq422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
streamwithExprsTutorial ( qw422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
qt422016 . ReleaseWriter ( qw422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
}
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
func withExprsTutorial ( ) string {
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
qb422016 := qt422016 . AcquireByteBuffer ( )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
writewithExprsTutorial ( qb422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
qs422016 := string ( qb422016 . B )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
qt422016 . ReleaseByteBuffer ( qb422016 )
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
return qs422016
//line app/vmselect/prometheus/expand-with-exprs.qtpl:245
}