Alerting: introduce AlertQuery in definitions package (#63825)

* copy AlertQuery from ngmodels to the definition package
* replaces usages of ngmodels.AlertQuery in API models
* create a converter between models of AlertQuery
---------

Co-authored-by: Alex Moreno <alexander.moreno@grafana.com>
This commit is contained in:
Yuri Tseretyan
2023-03-27 11:55:13 -04:00
committed by GitHub
co-authored by Alex Moreno
parent 36e8ca7f13
commit 52a0f59706
21 changed files with 279 additions and 182 deletions
@@ -6,8 +6,6 @@ import (
"time"
"github.com/prometheus/common/model"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// swagger:route Get /api/ruler/grafana/api/v1/rules ruler RouteGetGrafanaRulesConfig
@@ -370,7 +368,7 @@ const (
type PostableGrafanaRule struct {
Title string `json:"title" yaml:"title"`
Condition string `json:"condition" yaml:"condition"`
Data []models.AlertQuery `json:"data" yaml:"data"`
Data []AlertQuery `json:"data" yaml:"data"`
UID string `json:"uid" yaml:"uid"`
NoDataState NoDataState `json:"no_data_state" yaml:"no_data_state"`
ExecErrState ExecutionErrorState `json:"exec_err_state" yaml:"exec_err_state"`
@@ -383,7 +381,7 @@ type GettableGrafanaRule struct {
OrgID int64 `json:"orgId" yaml:"orgId"`
Title string `json:"title" yaml:"title"`
Condition string `json:"condition" yaml:"condition"`
Data []models.AlertQuery `json:"data" yaml:"data"`
Data []AlertQuery `json:"data" yaml:"data"`
Updated time.Time `json:"updated" yaml:"updated"`
IntervalSeconds int64 `json:"intervalSeconds" yaml:"intervalSeconds"`
Version int64 `json:"version" yaml:"version"`
@@ -396,3 +394,70 @@ type GettableGrafanaRule struct {
Provenance Provenance `json:"provenance,omitempty" yaml:"provenance,omitempty"`
IsPaused bool `json:"is_paused" yaml:"is_paused"`
}
// AlertQuery represents a single query associated with an alert definition.
type AlertQuery struct {
// RefID is the unique identifier of the query, set by the frontend call.
RefID string `json:"refId"`
// QueryType is an optional identifier for the type of query.
// It can be used to distinguish different types of queries.
QueryType string `json:"queryType"`
// RelativeTimeRange is the relative Start and End of the query as sent by the frontend.
RelativeTimeRange RelativeTimeRange `json:"relativeTimeRange"`
// Grafana data source unique identifier; it should be '__expr__' for a Server Side Expression operation.
DatasourceUID string `json:"datasourceUid"`
// JSON is the raw JSON query and includes the above properties as well as custom properties.
Model json.RawMessage `json:"model"`
}
// RelativeTimeRange is the per query start and end time
// for requests.
type RelativeTimeRange struct {
From Duration `json:"from" yaml:"from"`
To Duration `json:"to" yaml:"to"`
}
// Duration is a type used for marshalling durations.
type Duration time.Duration
func (d Duration) String() string {
return time.Duration(d).String()
}
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(time.Duration(d).Seconds())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case float64:
*d = Duration(time.Duration(value) * time.Second)
return nil
default:
return fmt.Errorf("invalid duration %v", v)
}
}
func (d Duration) MarshalYAML() (interface{}, error) {
return time.Duration(d).Seconds(), nil
}
func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
var v interface{}
if err := unmarshal(&v); err != nil {
return err
}
switch value := v.(type) {
case int:
*d = Duration(time.Duration(value) * time.Second)
return nil
default:
return fmt.Errorf("invalid duration %v", v)
}
}
@@ -4,15 +4,13 @@ import (
"encoding/json"
"fmt"
"time"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// EvalAlertConditionCommand is the command for evaluating a condition
type EvalAlertConditionCommand struct {
Condition string `json:"condition"`
Data []models.AlertQuery `json:"data"` // TODO yuri. Create API model for AlertQuery
Now time.Time `json:"now"`
Condition string `json:"condition"`
Data []AlertQuery `json:"data"`
Now time.Time `json:"now"`
}
func (cmd *EvalAlertConditionCommand) UnmarshalJSON(b []byte) error {
@@ -5,7 +5,6 @@ import (
"github.com/prometheus/common/model"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/provisioning/alerting/file"
)
@@ -119,7 +118,7 @@ type ProvisionedAlertRule struct {
Condition string `json:"condition"`
// required: true
// example: [{"refId":"A","queryType":"","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"__expr__","model":{"conditions":[{"evaluator":{"params":[0,0],"type":"gt"},"operator":{"type":"and"},"query":{"params":[]},"reducer":{"params":[],"type":"avg"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1 == 1","hide":false,"intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}]
Data []models.AlertQuery `json:"data"`
Data []AlertQuery `json:"data"`
// readonly: true
Updated time.Time `json:"updated,omitempty"`
// required: true
@@ -10,8 +10,6 @@ import (
"github.com/prometheus/alertmanager/config"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/promql"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// swagger:route Post /api/v1/rule/test/grafana testing RouteTestRuleGrafanaConfig
@@ -95,8 +93,8 @@ type EvalQueriesRequest struct {
// swagger:model
type EvalQueriesPayload struct {
Data []models.AlertQuery `json:"data"`
Now time.Time `json:"now"`
Data []AlertQuery `json:"data"`
Now time.Time `json:"now"`
}
func (p *TestRulePayload) UnmarshalJSON(b []byte) error {
@@ -187,9 +185,9 @@ type BacktestConfig struct {
To time.Time `json:"to"`
Interval model.Duration `json:"interval,omitempty"`
Condition string `json:"condition"`
Data []models.AlertQuery `json:"data"` // TODO yuri. Create API model for AlertQuery
For model.Duration `json:"for,omitempty"`
Condition string `json:"condition"`
Data []AlertQuery `json:"data"`
For model.Duration `json:"for,omitempty"`
Title string `json:"title"`
Labels map[string]string `json:"labels,omitempty"`
@@ -5,8 +5,6 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func TestRulePayloadMarshaling(t *testing.T) {
@@ -24,7 +22,7 @@ func TestRulePayloadMarshaling(t *testing.T) {
{
desc: "success grafana",
input: func() TestRulePayload {
data := models.AlertQuery{}
data := AlertQuery{}
// hack around that the struct embeds the json message inside of it as well
raw, _ := json.Marshal(data)
@@ -33,7 +31,7 @@ func TestRulePayloadMarshaling(t *testing.T) {
return TestRulePayload{
GrafanaManagedCondition: &EvalAlertConditionCommand{
Condition: "placeholder",
Data: []models.AlertQuery{data},
Data: []AlertQuery{data},
},
}
}(),