Skip to content

Commit 1749e16

Browse files
authored
feat(observability-lib): upgrade grafana-foundation-sdk to latest v0.0.18 (#2258)
* feat(observability-lib): upgrade grafana-foundation-sdk to latest v0.0.18 * chore: add tests with condition query
1 parent 9626707 commit 1749e16

4 files changed

Lines changed: 117 additions & 30 deletions

File tree

observability-lib/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ module github.com/smartcontractkit/chainlink-common/observability-lib
33
go 1.26.2
44

55
require (
6-
github.com/go-resty/resty/v2 v2.17.1
7-
github.com/grafana/grafana-foundation-sdk/go v0.0.12
6+
github.com/go-resty/resty/v2 v2.17.2
7+
github.com/grafana/grafana-foundation-sdk/go v0.0.18
88
github.com/spf13/cobra v1.10.2
99
github.com/stretchr/testify v1.11.1
1010
gopkg.in/yaml.v3 v3.0.1

observability-lib/go.sum

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

observability-lib/grafana/alerts.go

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type MathExpression struct {
7676

7777
type ResampleExpression struct {
7878
Expression string
79+
Window string
7980
DownSampler expr.TypeResampleDownsampler
8081
UpSampler expr.TypeResampleUpsampler
8182
}
@@ -137,47 +138,57 @@ func newConditionQuery(options ConditionQuery) *alerting.QueryBuilder {
137138
DatasourceUid("__expr__")
138139

139140
if options.ReduceExpression != nil {
140-
reduceBuider := expr.NewTypeReduceBuilder().
141+
reduceBuilder := expr.NewTypeReduceBuilder().
141142
RefId(options.RefID).
142143
Expression(options.ReduceExpression.Expression).
143144
IntervalMs(*options.IntervalMs).
144145
MaxDataPoints(*options.MaxDataPoints).
145146
Reducer(options.ReduceExpression.Reducer)
146147

147148
if options.ReduceExpression.ReduceSettings != nil && options.ReduceExpression.ReduceSettings.Mode != "" {
148-
reduceBuider.Settings(newReduceSettingsOptions(*options.ReduceExpression.ReduceSettings))
149+
reduceBuilder.Settings(newReduceSettingsOptions(*options.ReduceExpression.ReduceSettings))
149150
}
150-
res.Model(reduceBuider)
151+
res.Model(expr.NewTypeMathOrTypeReduceOrTypeResampleOrTypeClassicConditionsOrTypeThresholdOrTypeSqlBuilder().
152+
TypeReduce(reduceBuilder))
151153
}
152154

153155
if options.MathExpression != nil {
154-
res.Model(expr.NewTypeMathBuilder().
155-
RefId(options.RefID).
156-
Expression(options.MathExpression.Expression).
157-
IntervalMs(*options.IntervalMs).
158-
MaxDataPoints(*options.MaxDataPoints),
159-
)
156+
res.Model(expr.NewTypeMathOrTypeReduceOrTypeResampleOrTypeClassicConditionsOrTypeThresholdOrTypeSqlBuilder().
157+
TypeMath(expr.NewTypeMathBuilder().
158+
RefId(options.RefID).
159+
Expression(options.MathExpression.Expression).
160+
IntervalMs(*options.IntervalMs).
161+
MaxDataPoints(*options.MaxDataPoints),
162+
))
160163
}
161164

162165
if options.ResampleExpression != nil {
163-
res.Model(expr.NewTypeResampleBuilder().
164-
RefId(options.RefID).
165-
Expression(options.ResampleExpression.Expression).
166-
IntervalMs(*options.IntervalMs).
167-
MaxDataPoints(*options.MaxDataPoints).
168-
Downsampler(options.ResampleExpression.DownSampler).
169-
Upsampler(options.ResampleExpression.UpSampler),
170-
)
166+
window := options.ResampleExpression.Window
167+
if window == "" {
168+
// Window is required (>= 1 char) by the SDK; default to the relative time range.
169+
window = "10m"
170+
}
171+
res.Model(expr.NewTypeMathOrTypeReduceOrTypeResampleOrTypeClassicConditionsOrTypeThresholdOrTypeSqlBuilder().
172+
TypeResample(expr.NewTypeResampleBuilder().
173+
RefId(options.RefID).
174+
Expression(options.ResampleExpression.Expression).
175+
IntervalMs(*options.IntervalMs).
176+
MaxDataPoints(*options.MaxDataPoints).
177+
Window(window).
178+
Downsampler(options.ResampleExpression.DownSampler).
179+
Upsampler(options.ResampleExpression.UpSampler),
180+
))
171181
}
172182

173183
if options.ThresholdExpression != nil {
174-
res.Model(expr.NewTypeThresholdBuilder().
175-
RefId(options.RefID).
176-
Expression(options.ThresholdExpression.Expression).
177-
IntervalMs(*options.IntervalMs).
178-
MaxDataPoints(*options.MaxDataPoints).
179-
Conditions(newThresholdConditionsOptions(options.ThresholdExpression.ThresholdConditionsOptions)),
180-
)
184+
res.Model(expr.NewTypeMathOrTypeReduceOrTypeResampleOrTypeClassicConditionsOrTypeThresholdOrTypeSqlBuilder().
185+
TypeThreshold(expr.NewTypeThresholdBuilder().
186+
RefId(options.RefID).
187+
Expression(options.ThresholdExpression.Expression).
188+
IntervalMs(*options.IntervalMs).
189+
MaxDataPoints(*options.MaxDataPoints).
190+
Conditions(newThresholdConditionsOptions(options.ThresholdExpression.ThresholdConditionsOptions)),
191+
))
181192
}
182193

183194
return res

observability-lib/grafana/builder_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package grafana_test
22

33
import (
4+
"encoding/json"
45
"testing"
56

67
"github.com/grafana/grafana-foundation-sdk/go/alerting"
@@ -481,6 +482,81 @@ func TestBuilder_AddPanel(t *testing.T) {
481482
})
482483
}
483484

485+
func TestNewAlertRule_ConditionExpressionModels(t *testing.T) {
486+
t.Run("builds a model for every expression type", func(t *testing.T) {
487+
ruleBuilder := grafana.NewAlertRule(&grafana.AlertOptions{
488+
Title: "Expression Alert",
489+
Query: []grafana.RuleQuery{
490+
{
491+
Expr: `my_metric`,
492+
Instant: true,
493+
RefID: "A",
494+
Datasource: "datasource-uid",
495+
},
496+
},
497+
QueryRefCondition: "E",
498+
Condition: []grafana.ConditionQuery{
499+
{
500+
RefID: "B",
501+
ReduceExpression: &grafana.ReduceExpression{
502+
Expression: "A",
503+
Reducer: expr.TypeReduceReducerSum,
504+
},
505+
},
506+
{
507+
RefID: "C",
508+
MathExpression: &grafana.MathExpression{
509+
Expression: "$B * 2",
510+
},
511+
},
512+
{
513+
RefID: "D",
514+
ResampleExpression: &grafana.ResampleExpression{
515+
Expression: "A",
516+
Window: "10s",
517+
DownSampler: expr.TypeResampleDownsamplerMean,
518+
UpSampler: expr.TypeResampleUpsamplerPad,
519+
},
520+
},
521+
{
522+
RefID: "E",
523+
ThresholdExpression: &grafana.ThresholdExpression{
524+
Expression: "D",
525+
ThresholdConditionsOptions: grafana.ThresholdConditionsOption{
526+
Params: []float64{2},
527+
Type: expr.ExprTypeThresholdConditionsEvaluatorTypeLt,
528+
},
529+
},
530+
},
531+
},
532+
})
533+
534+
rule, err := ruleBuilder.Build()
535+
require.NoError(t, err)
536+
537+
models := map[string]string{}
538+
for _, query := range rule.Data {
539+
require.NotNil(t, query.RefId)
540+
raw, errMarshal := json.Marshal(query.Model)
541+
require.NoError(t, errMarshal)
542+
models[*query.RefId] = string(raw)
543+
}
544+
545+
require.Contains(t, models["B"], `"type":"reduce"`)
546+
547+
require.Contains(t, models["C"], `"type":"math"`)
548+
require.Contains(t, models["C"], `"expression":"$B * 2"`)
549+
550+
require.Contains(t, models["D"], `"type":"resample"`)
551+
require.Contains(t, models["D"], `"downsampler":"mean"`)
552+
require.Contains(t, models["D"], `"upsampler":"pad"`)
553+
require.Contains(t, models["D"], `"expression":"A"`)
554+
require.Contains(t, models["D"], `"window":"10s"`)
555+
556+
require.Contains(t, models["E"], `"type":"threshold"`)
557+
})
558+
}
559+
484560
func TestBuilder_AddTimeSeriesPanelWithAlert(t *testing.T) {
485561
t.Run("AddPanel adds a panel to the dashboard", func(t *testing.T) {
486562
builder := grafana.NewBuilder(&grafana.BuilderOptions{

0 commit comments

Comments
 (0)