chore: add types for alert type, state, and rule data kind (#5804)

This commit is contained in:
Srikanth Chekuri 2024-08-30 10:34:11 +05:30 committed by GitHub
parent 44598e304d
commit dde4485839
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 71 additions and 27 deletions

View File

@ -805,7 +805,7 @@ func (aH *APIHandler) getRuleStateHistory(w http.ResponseWriter, r *http.Request
continue continue
} }
filterItems := []v3.FilterItem{} filterItems := []v3.FilterItem{}
if rule.AlertType == "LOGS_BASED_ALERT" || rule.AlertType == "TRACES_BASED_ALERT" { if rule.AlertType == rules.AlertTypeLogs || rule.AlertType == rules.AlertTypeTraces {
if rule.RuleCondition.CompositeQuery != nil { if rule.RuleCondition.CompositeQuery != nil {
if rule.RuleCondition.QueryType() == v3.QueryTypeBuilder { if rule.RuleCondition.QueryType() == v3.QueryTypeBuilder {
for _, query := range rule.RuleCondition.CompositeQuery.BuilderQueries { for _, query := range rule.RuleCondition.CompositeQuery.BuilderQueries {
@ -818,9 +818,9 @@ func (aH *APIHandler) getRuleStateHistory(w http.ResponseWriter, r *http.Request
} }
newFilters := common.PrepareFilters(lbls, filterItems) newFilters := common.PrepareFilters(lbls, filterItems)
ts := time.Unix(res.Items[idx].UnixMilli/1000, 0) ts := time.Unix(res.Items[idx].UnixMilli/1000, 0)
if rule.AlertType == "LOGS_BASED_ALERT" { if rule.AlertType == rules.AlertTypeLogs {
res.Items[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, newFilters) res.Items[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, newFilters)
} else if rule.AlertType == "TRACES_BASED_ALERT" { } else if rule.AlertType == rules.AlertTypeTraces {
res.Items[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, newFilters) res.Items[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, newFilters)
} }
} }
@ -854,9 +854,9 @@ func (aH *APIHandler) getRuleStateHistoryTopContributors(w http.ResponseWriter,
} }
ts := time.Unix(params.End/1000, 0) ts := time.Unix(params.End/1000, 0)
filters := common.PrepareFilters(lbls, nil) filters := common.PrepareFilters(lbls, nil)
if rule.AlertType == "LOGS_BASED_ALERT" { if rule.AlertType == rules.AlertTypeLogs {
res[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, filters) res[idx].RelatedLogsLink = common.PrepareLinksToLogs(ts, filters)
} else if rule.AlertType == "TRACES_BASED_ALERT" { } else if rule.AlertType == rules.AlertTypeTraces {
res[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, filters) res[idx].RelatedTracesLink = common.PrepareLinksToTraces(ts, filters)
} }
} }

View File

@ -61,6 +61,35 @@ func (s AlertState) String() string {
panic(errors.Errorf("unknown alert state: %d", s)) panic(errors.Errorf("unknown alert state: %d", s))
} }
func (s AlertState) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
func (s *AlertState) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case string:
switch value {
case "inactive":
*s = StateInactive
case "pending":
*s = StatePending
case "firing":
*s = StateFiring
case "disabled":
*s = StateDisabled
default:
return errors.New("invalid alert state")
}
return nil
default:
return errors.New("invalid alert state")
}
}
type Alert struct { type Alert struct {
State AlertState State AlertState

View File

@ -16,6 +16,22 @@ import (
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
type AlertType string
const (
AlertTypeMetric AlertType = "METRIC_BASED_ALERT"
AlertTypeTraces AlertType = "TRACES_BASED_ALERT"
AlertTypeLogs AlertType = "LOGS_BASED_ALERT"
AlertTypeExceptions AlertType = "EXCEPTIONS_BASED_ALERT"
)
type RuleDataKind string
const (
RuleDataKindJson RuleDataKind = "json"
RuleDataKindYaml RuleDataKind = "yaml"
)
// this file contains api request and responses to be // this file contains api request and responses to be
// served over http // served over http
@ -31,12 +47,12 @@ func newApiErrorBadData(err error) *model.ApiError {
// PostableRule is used to create alerting rule from HTTP api // PostableRule is used to create alerting rule from HTTP api
type PostableRule struct { type PostableRule struct {
AlertName string `yaml:"alert,omitempty" json:"alert,omitempty"` AlertName string `yaml:"alert,omitempty" json:"alert,omitempty"`
AlertType string `yaml:"alertType,omitempty" json:"alertType,omitempty"` AlertType AlertType `yaml:"alertType,omitempty" json:"alertType,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"` Description string `yaml:"description,omitempty" json:"description,omitempty"`
RuleType RuleType `yaml:"ruleType,omitempty" json:"ruleType,omitempty"` RuleType RuleType `yaml:"ruleType,omitempty" json:"ruleType,omitempty"`
EvalWindow Duration `yaml:"evalWindow,omitempty" json:"evalWindow,omitempty"` EvalWindow Duration `yaml:"evalWindow,omitempty" json:"evalWindow,omitempty"`
Frequency Duration `yaml:"frequency,omitempty" json:"frequency,omitempty"` Frequency Duration `yaml:"frequency,omitempty" json:"frequency,omitempty"`
RuleCondition *RuleCondition `yaml:"condition,omitempty" json:"condition,omitempty"` RuleCondition *RuleCondition `yaml:"condition,omitempty" json:"condition,omitempty"`
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"` Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
@ -234,8 +250,8 @@ type GettableRules struct {
// GettableRule has info for an alerting rules. // GettableRule has info for an alerting rules.
type GettableRule struct { type GettableRule struct {
Id string `json:"id"` Id string `json:"id"`
State string `json:"state"` State AlertState `json:"state"`
PostableRule PostableRule
CreatedAt *time.Time `json:"createAt"` CreatedAt *time.Time `json:"createAt"`
CreatedBy *string `json:"createBy"` CreatedBy *string `json:"createBy"`

View File

@ -325,9 +325,9 @@ func (r *ruleDB) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) {
continue continue
} }
alertNames = append(alertNames, rule.AlertName) alertNames = append(alertNames, rule.AlertName)
if rule.AlertType == "LOGS_BASED_ALERT" { if rule.AlertType == AlertTypeLogs {
alertsInfo.LogsBasedAlerts = alertsInfo.LogsBasedAlerts + 1 alertsInfo.LogsBasedAlerts = alertsInfo.LogsBasedAlerts + 1
} else if rule.AlertType == "METRIC_BASED_ALERT" { } else if rule.AlertType == AlertTypeMetric {
alertsInfo.MetricBasedAlerts = alertsInfo.MetricBasedAlerts + 1 alertsInfo.MetricBasedAlerts = alertsInfo.MetricBasedAlerts + 1
if rule.RuleCondition != nil && rule.RuleCondition.CompositeQuery != nil { if rule.RuleCondition != nil && rule.RuleCondition.CompositeQuery != nil {
if rule.RuleCondition.CompositeQuery.QueryType == v3.QueryTypeBuilder { if rule.RuleCondition.CompositeQuery.QueryType == v3.QueryTypeBuilder {
@ -343,7 +343,7 @@ func (r *ruleDB) GetAlertsInfo(ctx context.Context) (*model.AlertsInfo, error) {
} }
} }
} }
} else if rule.AlertType == "TRACES_BASED_ALERT" { } else if rule.AlertType == AlertTypeTraces {
alertsInfo.TracesBasedAlerts = alertsInfo.TracesBasedAlerts + 1 alertsInfo.TracesBasedAlerts = alertsInfo.TracesBasedAlerts + 1
} }
alertsInfo.TotalAlerts = alertsInfo.TotalAlerts + 1 alertsInfo.TotalAlerts = alertsInfo.TotalAlerts + 1

View File

@ -604,10 +604,10 @@ func (m *Manager) ListRuleStates(ctx context.Context) (*GettableRules, error) {
// fetch state of rule from memory // fetch state of rule from memory
if rm, ok := m.rules[ruleResponse.Id]; !ok { if rm, ok := m.rules[ruleResponse.Id]; !ok {
ruleResponse.State = StateDisabled.String() ruleResponse.State = StateDisabled
ruleResponse.Disabled = true ruleResponse.Disabled = true
} else { } else {
ruleResponse.State = rm.State().String() ruleResponse.State = rm.State()
} }
ruleResponse.CreatedAt = s.CreatedAt ruleResponse.CreatedAt = s.CreatedAt
ruleResponse.CreatedBy = s.CreatedBy ruleResponse.CreatedBy = s.CreatedBy
@ -631,10 +631,10 @@ func (m *Manager) GetRule(ctx context.Context, id string) (*GettableRule, error)
r.Id = fmt.Sprintf("%d", s.Id) r.Id = fmt.Sprintf("%d", s.Id)
// fetch state of rule from memory // fetch state of rule from memory
if rm, ok := m.rules[r.Id]; !ok { if rm, ok := m.rules[r.Id]; !ok {
r.State = StateDisabled.String() r.State = StateDisabled
r.Disabled = true r.Disabled = true
} else { } else {
r.State = rm.State().String() r.State = rm.State()
} }
r.CreatedAt = s.CreatedAt r.CreatedAt = s.CreatedAt
r.CreatedBy = s.CreatedBy r.CreatedBy = s.CreatedBy
@ -740,10 +740,10 @@ func (m *Manager) PatchRule(ctx context.Context, ruleStr string, ruleId string)
// fetch state of rule from memory // fetch state of rule from memory
if rm, ok := m.rules[ruleId]; !ok { if rm, ok := m.rules[ruleId]; !ok {
response.State = StateDisabled.String() response.State = StateDisabled
response.Disabled = true response.Disabled = true
} else { } else {
response.State = rm.State().String() response.State = rm.State()
} }
return &response, nil return &response, nil

View File

@ -91,8 +91,7 @@ type ThresholdRule struct {
lastTimestampWithDatapoints time.Time lastTimestampWithDatapoints time.Time
// Type of the rule // Type of the rule
// One of ["LOGS_BASED_ALERT", "TRACES_BASED_ALERT", "METRIC_BASED_ALERT", "EXCEPTIONS_BASED_ALERT"] typ AlertType
typ string
// querier is used for alerts created before the introduction of new metrics query builder // querier is used for alerts created before the introduction of new metrics query builder
querier interfaces.Querier querier interfaces.Querier
@ -975,12 +974,12 @@ func (r *ThresholdRule) Eval(ctx context.Context, ts time.Time, queriers *Querie
// Links with timestamps should go in annotations since labels // Links with timestamps should go in annotations since labels
// is used alert grouping, and we want to group alerts with the same // is used alert grouping, and we want to group alerts with the same
// label set, but different timestamps, together. // label set, but different timestamps, together.
if r.typ == "TRACES_BASED_ALERT" { if r.typ == AlertTypeTraces {
link := r.prepareLinksToTraces(ts, smpl.MetricOrig) link := r.prepareLinksToTraces(ts, smpl.MetricOrig)
if link != "" && r.hostFromSource() != "" { if link != "" && r.hostFromSource() != "" {
annotations = append(annotations, labels.Label{Name: "related_traces", Value: fmt.Sprintf("%s/traces-explorer?%s", r.hostFromSource(), link)}) annotations = append(annotations, labels.Label{Name: "related_traces", Value: fmt.Sprintf("%s/traces-explorer?%s", r.hostFromSource(), link)})
} }
} else if r.typ == "LOGS_BASED_ALERT" { } else if r.typ == AlertTypeLogs {
link := r.prepareLinksToLogs(ts, smpl.MetricOrig) link := r.prepareLinksToLogs(ts, smpl.MetricOrig)
if link != "" && r.hostFromSource() != "" { if link != "" && r.hostFromSource() != "" {
annotations = append(annotations, labels.Label{Name: "related_logs", Value: fmt.Sprintf("%s/logs/logs-explorer?%s", r.hostFromSource(), link)}) annotations = append(annotations, labels.Label{Name: "related_logs", Value: fmt.Sprintf("%s/logs/logs-explorer?%s", r.hostFromSource(), link)})

View File

@ -674,7 +674,7 @@ func TestNormalizeLabelName(t *testing.T) {
func TestPrepareLinksToLogs(t *testing.T) { func TestPrepareLinksToLogs(t *testing.T) {
postableRule := PostableRule{ postableRule := PostableRule{
AlertName: "Tricky Condition Tests", AlertName: "Tricky Condition Tests",
AlertType: "LOGS_BASED_ALERT", AlertType: AlertTypeLogs,
RuleType: RuleTypeThreshold, RuleType: RuleTypeThreshold,
EvalWindow: Duration(5 * time.Minute), EvalWindow: Duration(5 * time.Minute),
Frequency: Duration(1 * time.Minute), Frequency: Duration(1 * time.Minute),