promqlbuilder

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2025 License: Apache-2.0 Imports: 5 Imported by: 15

README

PromQL Builder

A library to build PromQL expression fully in Golang.

Usage

Create an instant vector

To handle this use case, we are providing the package vector that proposes various options to create your instant vector.

For example:

package main

import (
	"fmt"

	"github.com/perses/promql-builder/label"
	"github.com/perses/promql-builder/vector"
)

func main() {
	v1 := vector.New(
		vector.WithMetricName("foo"),
		vector.WithLabelMatchers(
			label.New("namespace").Equal("monitoring"),
			label.New("pod-name").EqualRegexp("prom-.+"),
		),
	)
	fmt.Print(v1.String())
}

It will give the following output:

foo{namespace="monitoring",pod-name=~"prom-.+"}
Create a range vector

To handle this usecase, we are providing the package matrix that proposes various options to create your range vector.

For example:

package main

import (
	"fmt"

	"github.com/perses/promql-builder/label"
	"github.com/perses/promql-builder/matrix"
	"github.com/perses/promql-builder/vector"
)

func main() {
	v1 := vector.New(
		vector.WithMetricName("foo"),
		vector.WithLabelMatchers(
			label.New("namespace").Equal("monitoring"),
			label.New("pod-name").EqualRegexp("prom-.+"),
		),
	)
	m := matrix.New(v1, matrix.WithRangeAsVariable("$__rate_interval"))
	fmt.Print(m.String())
}

It will give the following output:

foo{namespace="monitoring",pod-name=~"prom-.+"}[$__rate_interval]

Note that as a duration we are using a variable. This is useful when you are using this library in a Dashboard As Code context, because likely the range duration will use the building variable coming with the dashboard tools like Grafana or Perses.

Of course, you can define a proper range duration using the option WithRangeAsString:

package main

import (
	"fmt"

	"github.com/perses/promql-builder/matrix"
	"github.com/perses/promql-builder/vector"
)

func main() {
	m := matrix.New(
		vector.New(vector.WithMetricName("foo")),
		matrix.WithRangeAsString("1h2m4s"),
	)
	fmt.Print(m.String())
}

It will give the following output:

foo[1h2m4s]
Use PromQL function

All functions, aggregations and binary operations are available at the root of this package promqlbuilder.

For example, with the function rate:

package main

import (
	"fmt"

	promqlbuilder "github.com/perses/promql-builder"
	"github.com/perses/promql-builder/matrix"
	"github.com/perses/promql-builder/vector"
)

func main() {
	m := promqlbuilder.Rate(
		matrix.New(
			vector.New(vector.WithMetricName("foo")),
			matrix.WithRangeAsString("1h2m4s"),
		),
	)
	fmt.Print(m.String())
}

It will give the following output:

rate(foo[1h2m4s])
Use aggregation function

As you may know, all aggregation functions can be combined with the keywords by or without in order to specify on which labels you would like to aggregate the timeseries.

In this builder, these keywords are a function that you can use once you have created the aggregation function.

For example, with the aggregation function sum:

package main

import (
	"fmt"

	promqlbuilder "github.com/perses/promql-builder"
	"github.com/perses/promql-builder/matrix"
	"github.com/perses/promql-builder/vector"
)

func main() {
	m :=
		promqlbuilder.Sum(
			promqlbuilder.Rate(
				matrix.New(
					vector.New(vector.WithMetricName("foo")),
					matrix.WithRangeAsString("1h2m4s"),
				),
			),
		).By("namespace")
	fmt.Print(m.String())
}

It will give the following output:

```text
sum by("namespace") (rate(foo[1h2m4s]))
Use binary operation

Binary operation can be used with the vector matching keywords on, ignoring. Same like the aggregation function, the usage of these keywords can be done once you have built your binary operation.

package main

import (
	"fmt"

	promqlbuilder "github.com/perses/promql-builder"
	"github.com/perses/promql-builder/matrix"
	"github.com/perses/promql-builder/vector"
)

func main() {
	m :=
		promqlbuilder.Add(
			promqlbuilder.Rate(
				matrix.New(
					vector.New(vector.WithMetricName("foo")),
					matrix.WithRangeAsString("1h2m4s"),
				),
			),
			promqlbuilder.Vector(123),
		).On("namespace")
	fmt.Print(m.String())
}

rate(foo[1h2m4s]) + on("namespace") vector(123)

Note: the Group modifiers (group_left or group_right) can be used once the vector matching keywords are used.

Iterate through PromQL AST

This lib also provides Prometheus-inspired PromQL AST iteration methods such as Inspect, Walk, Children, that can handle the custom nodes of expressions constructed using this lib, as well as PromQL expression deep copying using DeepCopyExpr.

This allows constructing utilities like,

func SetLabelMatchers(query parser.Expr, matchers []*labels.Matcher) parser.Expr {
	copy := promqlbuilder.DeepCopyExpr(query)
	for _, l := range matchers {
		copy = LabelsSetPromQL(copy, l.Type, l.Name, l.Value)
	}
	return copy
}

func LabelsSetPromQL(query parser.Expr, matchType labels.MatchType, name, value string) parser.Expr {
	if name == "" || value == "" {
		return query
	}

	promqlbuilder.Inspect(query, func(node parser.Node, path []parser.Node) error {
		if n, ok := node.(*parser.VectorSelector); ok {
			var found bool
			for i, l := range n.LabelMatchers {
				if l.Name == name {
					n.LabelMatchers[i].Type = matchType
					n.LabelMatchers[i].Value = value
					found = true
				}
			}
			if !found {
				n.LabelMatchers = append(n.LabelMatchers, &labels.Matcher{
					Type:  matchType,
					Name:  name,
					Value: value,
				})
			}
		}
		return nil
	})

	return query
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Abs

func Abs(vector parser.Expr) *parser.Call

func Absent

func Absent(vector parser.Expr) *parser.Call

func AbsentOverTime

func AbsentOverTime[T RangeVectorBuilder](input T) *parser.Call

func Acos

func Acos(vector parser.Expr) *parser.Call

func Acosh

func Acosh(vector parser.Expr) *parser.Call

func Asin

func Asin(vector parser.Expr) *parser.Call

func Asinh

func Asinh(vector parser.Expr) *parser.Call

func Atan

func Atan(vector parser.Expr) *parser.Call

func Atanh

func Atanh(vector parser.Expr) *parser.Call

func AvgOverTime

func AvgOverTime[T RangeVectorBuilder](input T) *parser.Call

func Ceil

func Ceil(vector parser.Expr) *parser.Call

func Changes

func Changes[T RangeVectorBuilder](input T) *parser.Call

func Children added in v0.2.0

func Children(node parser.Node) []parser.Node

Children returns a list of all child nodes of a syntax tree node.

Taken from https://github.com/prometheus/prometheus/blob/v3.4.0/promql/parser/ast.go#L377 But adds handling cases for promqlbuilder node types.

func Clamp

func Clamp(vector parser.Expr, min float64, max float64) *parser.Call

func ClampMax

func ClampMax(vector parser.Expr, max float64) *parser.Call

func ClampMin

func ClampMin(vector parser.Expr, min float64) *parser.Call

func Cos

func Cos(vector parser.Expr) *parser.Call

func Cosh

func Cosh(vector parser.Expr) *parser.Call

func CountOverTime

func CountOverTime[T RangeVectorBuilder](input T) *parser.Call

func DaysInMonth

func DaysInMonth(vector parser.Expr) *parser.Call

func DaysOfMonth

func DaysOfMonth(vector parser.Expr) *parser.Call

func DaysOfWeek

func DaysOfWeek(vector parser.Expr) *parser.Call

func DaysOfYear

func DaysOfYear(vector parser.Expr) *parser.Call

func DeepCopyExpr added in v0.2.0

func DeepCopyExpr(expr parser.Expr) parser.Expr

DeepCopyExpr copies an expression and all its children recursively. Handler promqlbuilder node types as well.

func Deg

func Deg(vector parser.Expr) *parser.Call

func Delta

func Delta[T RangeVectorBuilder](input T) *parser.Call

func Deriv

func Deriv[T RangeVectorBuilder](input T) *parser.Call

func DoubleExponentialSmoothing

func DoubleExponentialSmoothing[T RangeVectorBuilder](input T, smoothingFactor float64, trendFactor float64) *parser.Call

func Exp

func Exp(vector parser.Expr) *parser.Call

func Floor

func Floor(vector parser.Expr) *parser.Call

func HistogramAvg

func HistogramAvg(vector parser.Expr) *parser.Call

func HistogramCount

func HistogramCount(vector parser.Expr) *parser.Call

func HistogramFraction

func HistogramFraction(lower float64, upper float64, vector parser.Expr) *parser.Call

func HistogramQuantile

func HistogramQuantile(quantile float64, vector parser.Expr) *parser.Call

func HistogramStddev

func HistogramStddev(vector parser.Expr) *parser.Call

func HistogramStdvar

func HistogramStdvar(vector parser.Expr) *parser.Call

func HistogramSum

func HistogramSum(vector parser.Expr) *parser.Call

func Hour

func Hour(vector parser.Expr) *parser.Call

func IDelta

func IDelta[T RangeVectorBuilder](input T) *parser.Call

func IRate

func IRate[T RangeVectorBuilder](input T) *parser.Call

func Increase

func Increase[T RangeVectorBuilder](input T) *parser.Call

func Info

func Info(vector parser.Expr, dataLabelSelector parser.Expr) *parser.Call

func Inspect added in v0.2.0

func Inspect(node parser.Node, f inspector)

Inspect traverses an AST in depth-first order: It starts by calling f(node, path); node must not be nil. If f returns a nil error, Inspect invokes f for all the non-nil children of node, recursively.

Taken from https://github.com/prometheus/prometheus/blob/v3.4.0/promql/parser/ast.go#L370 But adds handling cases for promqlbuilder node types.

func LabelJoin

func LabelJoin(vector parser.Expr, destinationLabel string, replacement string, srcLabels ...string) *parser.Call

func LabelReplace

func LabelReplace(vector parser.Expr, destinationLabel string, replacement string, sourceLabel string, regexp string) *parser.Call

func LastOverTime

func LastOverTime[T RangeVectorBuilder](input T) *parser.Call

func Ln

func Ln(vector parser.Expr) *parser.Call

func Log2

func Log2(vector parser.Expr) *parser.Call

func Log10

func Log10(vector parser.Expr) *parser.Call

func MadOverTime

func MadOverTime[T RangeVectorBuilder](input T) *parser.Call

func MaxOverTime

func MaxOverTime[T RangeVectorBuilder](input T) *parser.Call

func MinOverTime

func MinOverTime[T RangeVectorBuilder](input T) *parser.Call

func Minute

func Minute(vector parser.Expr) *parser.Call

func Month

func Month(vector parser.Expr) *parser.Call

func NewNumber added in v0.2.0

func NewNumber(num float64) *parser.NumberLiteral

func NewString added in v0.2.0

func NewString(s string) *parser.StringLiteral

func PI

func PI() *parser.Call

func PredictLinear

func PredictLinear[T RangeVectorBuilder](input T, t float64) *parser.Call

func PresentOverTime

func PresentOverTime[T RangeVectorBuilder](input T) *parser.Call

func QuantileOverTime

func QuantileOverTime[T RangeVectorBuilder](t float64, input T) *parser.Call

func Rad

func Rad(vector parser.Expr) *parser.Call

func Rate

func Rate[T RangeVectorBuilder](input T) *parser.Call

func Resets

func Resets[T RangeVectorBuilder](input T) *parser.Call

func Round

func Round(vector parser.Expr, t float64) *parser.Call

func Scalar

func Scalar(vector parser.Expr) *parser.Call

func Sgn

func Sgn(vector parser.Expr) *parser.Call

func Sin

func Sin(vector parser.Expr) *parser.Call

func Sinh

func Sinh(vector parser.Expr) *parser.Call

func Sort

func Sort(vector parser.Expr) *parser.Call

func SortByLabel

func SortByLabel(vector parser.Expr, labels ...string) *parser.Call

func SortByLabelDesc

func SortByLabelDesc(vector parser.Expr, labels ...string) *parser.Call

func SortDesc

func SortDesc(vector parser.Expr) *parser.Call

func Sqrt

func Sqrt(vector parser.Expr) *parser.Call

func StddevOverTime

func StddevOverTime[T RangeVectorBuilder](input T) *parser.Call

func StdvarOverTime

func StdvarOverTime[T RangeVectorBuilder](input T) *parser.Call

func SumOverTime

func SumOverTime[T RangeVectorBuilder](input T) *parser.Call

func Tan

func Tan(vector parser.Expr) *parser.Call

func Tanh

func Tanh(vector parser.Expr) *parser.Call

func Time

func Time() *parser.Call

func Timestamp

func Timestamp(vector parser.Expr) *parser.Call

func Vector

func Vector(scalar float64) *parser.Call

func Walk added in v0.2.0

func Walk(v parser.Visitor, node parser.Node, path []parser.Node) error

Walk traverses an AST in depth-first order: It starts by calling v.Visit(node, path); node must not be nil. If the visitor w returned by v.Visit(node, path) is not nil and the visitor returns no error, Walk is invoked recursively with visitor w for each of the non-nil children of node, followed by a call of w.Visit(nil), returning an error As the tree is descended the path of previous nodes is provided.

Taken from https://github.com/prometheus/prometheus/blob/v3.4.0/promql/parser/ast.go#L325 But adds handling cases for promqlbuilder node types.

func Year

func Year(vector parser.Expr) *parser.Call

Types

type AggregationBuilder

type AggregationBuilder struct {
	parser.Expr
	// contains filtered or unexported fields
}

func Avg

func Avg(vector parser.Expr) *AggregationBuilder

func BottomK added in v0.2.0

func BottomK(vector parser.Expr, k float64) *AggregationBuilder

func Count

func Count(vector parser.Expr) *AggregationBuilder

func CountValues

func CountValues(vector parser.Expr) *AggregationBuilder

func Group

func Group(vector parser.Expr) *AggregationBuilder

func LimitK

func LimitK(vector parser.Expr, k float64) *AggregationBuilder

func LimitRatio

func LimitRatio(vector parser.Expr, ratio float64) *AggregationBuilder

func Max

func Max(vector parser.Expr) *AggregationBuilder

func Min

func Min(vector parser.Expr) *AggregationBuilder

func Quantile

func Quantile(vector parser.Expr, quantile float64) *AggregationBuilder

func Stddev

func Stddev(vector parser.Expr) *AggregationBuilder

func Stdvar

func Stdvar(vector parser.Expr) *AggregationBuilder

func Sum

func Sum(vector parser.Expr) *AggregationBuilder

func TopK added in v0.2.0

func TopK(vector parser.Expr, k float64) *AggregationBuilder

func (*AggregationBuilder) By

func (a *AggregationBuilder) By(labels ...string) *AggregationBuilder

func (*AggregationBuilder) PositionRange

func (a *AggregationBuilder) PositionRange() posrange.PositionRange

func (*AggregationBuilder) Pretty

func (a *AggregationBuilder) Pretty(level int) string

func (*AggregationBuilder) PromQLExpr

func (a *AggregationBuilder) PromQLExpr()

func (*AggregationBuilder) String

func (a *AggregationBuilder) String() string

func (*AggregationBuilder) Type

func (*AggregationBuilder) Without

func (a *AggregationBuilder) Without(labels ...string) *AggregationBuilder

type BinaryBuilder

type BinaryBuilder struct {
	// contains filtered or unexported fields
}

func Add

func Add(left parser.Expr, right parser.Expr) *BinaryBuilder

func And

func And(left parser.Expr, right parser.Expr) *BinaryBuilder

func Atan2

func Atan2(left parser.Expr, right parser.Expr) *BinaryBuilder

func Div

func Div(left parser.Expr, right parser.Expr) *BinaryBuilder

func Eql

func Eql(left parser.Expr, right parser.Expr) *BinaryBuilder

func EqlRegex added in v0.2.0

func EqlRegex(left parser.Expr, right parser.Expr) *BinaryBuilder

func Eqlc added in v0.2.0

func Eqlc(left parser.Expr, right parser.Expr) *BinaryBuilder

func Gte

func Gte(left parser.Expr, right parser.Expr) *BinaryBuilder

func Gtr

func Gtr(left parser.Expr, right parser.Expr) *BinaryBuilder

func Lss

func Lss(left parser.Expr, right parser.Expr) *BinaryBuilder

func Lte

func Lte(left parser.Expr, right parser.Expr) *BinaryBuilder

func Mod

func Mod(left parser.Expr, right parser.Expr) *BinaryBuilder

func Mul

func Mul(left parser.Expr, right parser.Expr) *BinaryBuilder

func Neq

func Neq(left parser.Expr, right parser.Expr) *BinaryBuilder

func NeqRegex added in v0.2.0

func NeqRegex(left parser.Expr, right parser.Expr) *BinaryBuilder

func Or

func Or(left parser.Expr, right parser.Expr) *BinaryBuilder

func Pow

func Pow(left parser.Expr, right parser.Expr) *BinaryBuilder

func Sub

func Sub(left parser.Expr, right parser.Expr) *BinaryBuilder

func Unless

func Unless(left parser.Expr, right parser.Expr) *BinaryBuilder

func (*BinaryBuilder) Bool added in v0.2.0

func (b *BinaryBuilder) Bool() *BinaryBuilder

func (*BinaryBuilder) Ignoring

func (b *BinaryBuilder) Ignoring(labels ...string) *BinaryWithVectorMatching

func (*BinaryBuilder) On

func (b *BinaryBuilder) On(labels ...string) *BinaryWithVectorMatching

func (*BinaryBuilder) PositionRange

func (b *BinaryBuilder) PositionRange() posrange.PositionRange

func (*BinaryBuilder) Pretty

func (b *BinaryBuilder) Pretty(level int) string

func (*BinaryBuilder) PromQLExpr

func (b *BinaryBuilder) PromQLExpr()

func (*BinaryBuilder) String

func (b *BinaryBuilder) String() string

func (*BinaryBuilder) Type

func (b *BinaryBuilder) Type() parser.ValueType

type BinaryWithVectorMatching

type BinaryWithVectorMatching struct {
	// contains filtered or unexported fields
}

func (*BinaryWithVectorMatching) Bool added in v0.2.0

func (*BinaryWithVectorMatching) GroupLeft

func (b *BinaryWithVectorMatching) GroupLeft(labels ...string) *BinaryWithVectorMatching

func (*BinaryWithVectorMatching) GroupRight

func (b *BinaryWithVectorMatching) GroupRight(labels ...string) *BinaryWithVectorMatching

func (*BinaryWithVectorMatching) PositionRange

func (b *BinaryWithVectorMatching) PositionRange() posrange.PositionRange

func (*BinaryWithVectorMatching) Pretty

func (b *BinaryWithVectorMatching) Pretty(level int) string

func (*BinaryWithVectorMatching) PromQLExpr

func (b *BinaryWithVectorMatching) PromQLExpr()

func (*BinaryWithVectorMatching) String

func (b *BinaryWithVectorMatching) String() string

func (*BinaryWithVectorMatching) Type

type RangeVectorBuilder added in v0.2.0

type RangeVectorBuilder interface {
	*matrix.Builder | *parser.SubqueryExpr
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL