From 876eeb218bbc8ae3b86482c257a7fd38650c9125 Mon Sep 17 00:00:00 2001 From: Alexandr Yepishev Date: Thu, 2 Apr 2026 14:15:19 +0100 Subject: [PATCH 1/2] Add query options Inreval to that may be used by interval/range vars --- observability-lib/grafana/panels.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/observability-lib/grafana/panels.go b/observability-lib/grafana/panels.go index e90dcce32b..23eb81c334 100644 --- a/observability-lib/grafana/panels.go +++ b/observability-lib/grafana/panels.go @@ -1,6 +1,8 @@ package grafana import ( + "time" + "github.com/grafana/grafana-foundation-sdk/go/alerting" "github.com/grafana/grafana-foundation-sdk/go/bargauge" "github.com/grafana/grafana-foundation-sdk/go/cog" @@ -29,6 +31,7 @@ const ( type Query struct { Expr string Legend string + Interval string // i.e. 30s, 2m, a lower limit for the interval that will be sent to datasource and used by $__interval/range variables Instant bool Min float64 Format prometheus.PromQueryFormat @@ -41,6 +44,10 @@ func newQuery(query Query) *prometheus.DataqueryBuilder { LegendFormat(query.Legend). Format(query.Format) + if isValidDuration(query.Interval) { + res.Interval(query.Interval) + } + if query.Instant { res.Instant() } @@ -51,6 +58,11 @@ func newQuery(query Query) *prometheus.DataqueryBuilder { return res } +func isValidDuration(s string) bool { + _, err := time.ParseDuration(s) + return err == nil +} + type LegendOptions struct { Placement common.LegendPlacement DisplayMode common.LegendDisplayMode From fa62effbbf4e40ccc3b54934f16bd08e872abc73 Mon Sep 17 00:00:00 2001 From: Alexandr Yepishev Date: Thu, 2 Apr 2026 14:32:23 +0100 Subject: [PATCH 2/2] Extend grafana interval validation; fix row.Collapsed option usage --- observability-lib/grafana/builder.go | 4 +--- observability-lib/grafana/panels.go | 14 ++++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/observability-lib/grafana/builder.go b/observability-lib/grafana/builder.go index c62a70e258..93f559c8fe 100644 --- a/observability-lib/grafana/builder.go +++ b/observability-lib/grafana/builder.go @@ -80,9 +80,7 @@ func (b *Builder) AddVars(items ...cog.Builder[dashboard.VariableModel]) { func (b *Builder) AddRow(title string, options ...RowOptions) { row := dashboard.NewRowBuilder(title) for _, o := range options { - if o.Collapsed { - row.Collapsed(true) - } + row.Collapsed(o.Collapsed) } b.dashboardBuilder.WithRow(row) } diff --git a/observability-lib/grafana/panels.go b/observability-lib/grafana/panels.go index 23eb81c334..172865b74a 100644 --- a/observability-lib/grafana/panels.go +++ b/observability-lib/grafana/panels.go @@ -1,7 +1,8 @@ package grafana import ( - "time" + "regexp" + "strconv" "github.com/grafana/grafana-foundation-sdk/go/alerting" "github.com/grafana/grafana-foundation-sdk/go/bargauge" @@ -58,9 +59,14 @@ func newQuery(query Query) *prometheus.DataqueryBuilder { return res } -func isValidDuration(s string) bool { - _, err := time.ParseDuration(s) - return err == nil +func isValidDuration(interval string) bool { + var grafanaDurationRegexp = regexp.MustCompile(`^(\d+)(ms|[smhdwMy])$`) // ms, s, m, h, d, w, M, y + m := grafanaDurationRegexp.FindStringSubmatch(interval) + if m == nil { + return false + } + n, _ := strconv.ParseInt(m[1], 10, 64) + return n > 0 } type LegendOptions struct {