From c630dce3380b6fdef67d8bd060709f844a595f11 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Fri, 17 Jan 2020 15:01:41 -0500 Subject: [PATCH 01/29] add api to support prom rules and alerts to ruler Signed-off-by: Jacob Lisi --- go.mod | 1 + go.sum | 2 + pkg/ruler/api.go | 264 ++++++++ pkg/ruler/ruler.go | 150 ++++- pkg/ruler/ruler.pb.go | 657 ++++++++++++++++++++ pkg/ruler/ruler.proto | 22 + pkg/ruler/rules/rules.pb.go | 1146 ++++++++++++++++++++++++++++++++--- pkg/ruler/rules/rules.proto | 52 +- 8 files changed, 2176 insertions(+), 118 deletions(-) create mode 100644 pkg/ruler/api.go create mode 100644 pkg/ruler/ruler.pb.go create mode 100644 pkg/ruler/ruler.proto diff --git a/go.mod b/go.mod index e04127911a3..bc1ac886a60 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,7 @@ require ( google.golang.org/api v0.14.0 google.golang.org/grpc v1.25.1 gopkg.in/yaml.v2 v2.2.5 + grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 ) replace github.com/Azure/azure-sdk-for-go => github.com/Azure/azure-sdk-for-go v36.2.0+incompatible diff --git a/go.sum b/go.sum index f2feb819a1c..ac3c9b9330d 100644 --- a/go.sum +++ b/go.sum @@ -1052,6 +1052,8 @@ gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/x4yG7qPBrtNfLY= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go new file mode 100644 index 00000000000..24efeebaa8d --- /dev/null +++ b/pkg/ruler/api.go @@ -0,0 +1,264 @@ +package ruler + +import ( + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/prometheus/prometheus/pkg/labels" + + "github.com/cortexproject/cortex/pkg/ingester/client" + "github.com/cortexproject/cortex/pkg/util" + "github.com/go-kit/kit/log/level" + "github.com/gorilla/mux" + "github.com/weaveworks/common/user" +) + +// RegisterRoutes registers the configs API HTTP routes with the provided Router. +func (r *Ruler) RegisterRoutes(router *mux.Router) { + if r.store == nil { + level.Info(util.Logger).Log("msg", "ruler configured with store that does not support api") + return + } + for _, route := range []struct { + name, method, path string + handler http.HandlerFunc + }{ + {"get_rules", "GET", "/api/prom/api/v1/rules", r.rules}, + {"get_alerts", "GET", "/api/prom/api/v1/rules", r.alerts}, + } { + level.Debug(util.Logger).Log("msg", "ruler: registering route", "name", route.name, "method", route.method, "path", route.path) + router.Handle(route.path, route.handler).Methods(route.method).Name(route.name) + } +} + +// In order to reimplent the prometheus rules API, a large amount of code was copied over +// This is required because the prometheus api implementation does not pass a context to +// the rule retrieval function. +// https://github.com/prometheus/prometheus/blob/2aacd807b3ec6ddd90ae55f3a42f4cffed561ea9/web/api/v1/api.go#L108 +// https://github.com/prometheus/prometheus/pull/4999 + +type response struct { + Status string `json:"status"` + Data interface{} `json:"data,omitempty"` + ErrorType string `json:"errorType,omitempty"` + Error string `json:"error,omitempty"` +} + +// AlertDiscovery has info for all active alerts. +type AlertDiscovery struct { + Alerts []*Alert `json:"alerts"` +} + +// Alert has info for an alert. +type Alert struct { + Labels labels.Labels `json:"labels"` + Annotations labels.Labels `json:"annotations"` + State string `json:"state"` + ActiveAt *time.Time `json:"activeAt,omitempty"` + Value string `json:"value"` +} + +// RuleDiscovery has info for all rules +type RuleDiscovery struct { + RuleGroups []*RuleGroup `json:"groups"` +} + +// RuleGroup has info for rules which are part of a group +type RuleGroup struct { + Name string `json:"name"` + File string `json:"file"` + // In order to preserve rule ordering, while exposing type (alerting or recording) + // specific properties, both alerting and recording rules are exposed in the + // same array. + Rules []rule `json:"rules"` + Interval float64 `json:"interval"` +} + +type rule interface{} + +type alertingRule struct { + // State can be "pending", "firing", "inactive". + State string `json:"state"` + Name string `json:"name"` + Query string `json:"query"` + Duration float64 `json:"duration"` + Labels labels.Labels `json:"labels"` + Annotations labels.Labels `json:"annotations"` + Alerts []*Alert `json:"alerts"` + Health string `json:"health"` + LastError string `json:"lastError,omitempty"` + // Type of an alertingRule is always "alerting". + Type string `json:"type"` +} + +type recordingRule struct { + Name string `json:"name"` + Query string `json:"query"` + Labels labels.Labels `json:"labels,omitempty"` + Health string `json:"health"` + LastError string `json:"lastError,omitempty"` + // Type of a recordingRule is always "recording". + Type string `json:"type"` +} + +func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { + logger := util.WithContext(req.Context(), util.Logger) + userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) + if err != nil { + level.Error(logger).Log("msg", "error extracting org id from context", "err", err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + + w.Header().Set("Content-Type", "application/json") + rgs, err := r.GetRules(ctx, userID) + + if err != nil { + b, err := json.Marshal(&response{ + Status: "error", + ErrorType: "internal", + Error: err.Error(), + Data: nil, + }) + + if err != nil { + level.Error(logger).Log("msg", "error marshaling json response", "err", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusInternalServerError) + if n, err := w.Write(b); err != nil { + level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) + } + return + } + + groups := make([]*RuleGroup, len(rgs)) + + for _, g := range rgs { + grp := RuleGroup{ + Name: g.Name, + File: g.Namespace, + Interval: g.Interval.Seconds(), + Rules: make([]rule, len(g.Rules)), + } + + for i, rl := range g.Rules { + if g.Rules[i].Alert != "" { + alerts := make([]*Alert, len(rl.Alerts)) + for _, a := range rl.Alerts { + alerts = append(alerts, &Alert{ + Labels: client.FromLabelAdaptersToLabels(a.Labels), + Annotations: client.FromLabelAdaptersToLabels(a.Annotations), + State: a.GetState(), + ActiveAt: a.ActiveAt, + Value: fmt.Sprintf("%f", a.Value), + }) + } + grp.Rules[i] = alertingRule{ + State: rl.GetState(), + Name: rl.GetAlert(), + Query: rl.GetExpr(), + Duration: rl.For.Seconds(), + Labels: client.FromLabelAdaptersToLabels(rl.Labels), + Annotations: client.FromLabelAdaptersToLabels(rl.Annotations), + Alerts: alerts, + Health: rl.GetHealth(), + LastError: rl.GetLastError(), + Type: "alerting", + } + } else { + grp.Rules[i] = recordingRule{ + Name: rl.GetRecord(), + Query: rl.GetExpr(), + Labels: client.FromLabelAdaptersToLabels(rl.Labels), + Health: rl.GetHealth(), + LastError: rl.GetLastError(), + Type: "recording", + } + } + } + groups = append(groups, &grp) + } + + b, err := json.Marshal(&response{ + Status: "success", + Data: &RuleDiscovery{RuleGroups: groups}, + }) + if err != nil { + level.Error(logger).Log("msg", "error marshaling json response", "err", err) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + if n, err := w.Write(b); err != nil { + level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) + } +} + +func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { + logger := util.WithContext(req.Context(), util.Logger) + userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) + if err != nil { + level.Error(logger).Log("msg", "error extracting org id from context", "err", err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + + w.Header().Set("Content-Type", "application/json") + rgs, err := r.GetRules(ctx, userID) + + if err != nil { + b, err := json.Marshal(&response{ + Status: "error", + ErrorType: "internal", + Error: err.Error(), + Data: nil, + }) + + if err != nil { + level.Error(logger).Log("msg", "error marshaling json response", "err", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusInternalServerError) + if n, err := w.Write(b); err != nil { + level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) + } + return + } + + alerts := make([]*Alert, len(rgs)) + + for _, g := range rgs { + for _, rl := range g.Rules { + if rl.Alert != "" { + for _, a := range rl.Alerts { + alerts = append(alerts, &Alert{ + Labels: client.FromLabelAdaptersToLabels(a.Labels), + Annotations: client.FromLabelAdaptersToLabels(a.Annotations), + State: a.GetState(), + ActiveAt: a.ActiveAt, + Value: fmt.Sprintf("%f", a.Value), + }) + } + } + } + } + + b, err := json.Marshal(&response{ + Status: "success", + Data: &AlertDiscovery{Alerts: alerts}, + }) + if err != nil { + level.Error(logger).Log("msg", "error marshaling json response", "err", err) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + if n, err := w.Write(b); err != nil { + level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) + } +} diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index e956502b2ff..756907d779b 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -3,14 +3,23 @@ package ruler import ( native_ctx "context" "flag" + "fmt" "hash/fnv" "net/http" "net/url" "sync" "time" + "github.com/cortexproject/cortex/pkg/distributor" + "github.com/cortexproject/cortex/pkg/ingester/client" + "github.com/cortexproject/cortex/pkg/ring" + "github.com/cortexproject/cortex/pkg/ruler/rules" + store "github.com/cortexproject/cortex/pkg/ruler/rules" + "github.com/cortexproject/cortex/pkg/util" + "github.com/cortexproject/cortex/pkg/util/flagext" "github.com/go-kit/kit/log/level" ot "github.com/opentracing/opentracing-go" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/prometheus/config" @@ -19,16 +28,10 @@ import ( promRules "github.com/prometheus/prometheus/rules" promStorage "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/util/strutil" + "github.com/weaveworks/common/user" "golang.org/x/net/context" "golang.org/x/net/context/ctxhttp" - - "github.com/cortexproject/cortex/pkg/distributor" - "github.com/cortexproject/cortex/pkg/ring" - "github.com/cortexproject/cortex/pkg/ruler/rules" - store "github.com/cortexproject/cortex/pkg/ruler/rules" - "github.com/cortexproject/cortex/pkg/util" - "github.com/cortexproject/cortex/pkg/util/flagext" - "github.com/weaveworks/common/user" + "google.golang.org/grpc" ) var ( @@ -63,6 +66,8 @@ type Config struct { SearchPendingFor time.Duration Ring RingConfig FlushCheckPeriod time.Duration + + EnableAPI bool } // RegisterFlags adds the flags required to config this to the given FlagSet @@ -92,6 +97,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) { f.BoolVar(&cfg.EnableSharding, "ruler.enable-sharding", false, "Distribute rule evaluation using ring backend") f.DurationVar(&cfg.FlushCheckPeriod, "ruler.flush-period", 1*time.Minute, "Period with which to attempt to flush rule groups.") f.StringVar(&cfg.RulePath, "ruler.rule-path", "/rules", "file path to store temporary rule files for the prometheus rule managers") + f.BoolVar(&cfg.EnableAPI, "experimental.ruler.enable-api", false, "Enable the ruler api") } // Ruler evaluates rules. @@ -445,3 +451,131 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag } return promRules.NewManager(opts), nil } + +// GetRules retrieves the running rules from this ruler and all running rulers in the ring if +// sharding is enabled +func (r *Ruler) GetRules(ctx context.Context, userID string) ([]*rules.RuleGroupDesc, error) { + rgs, err := r.getRules(userID) + if err != nil { + return nil, err + } + + if r.cfg.EnableSharding { + rulers, err := r.ring.GetAll() + if err != nil { + return nil, err + } + + ctx, err = user.InjectIntoGRPCRequest(ctx) + if err != nil { + return nil, fmt.Errorf("unable to inject user ID into grpc request, %v", err) + } + + for _, rlr := range rulers.Ingesters { + // Don't retrieve rules using GRPC from the same ingester + if rlr.GetAddr() == r.lifecycler.Addr { + continue + } + conn, err := grpc.Dial(rlr.Addr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + cc := NewRulerClient(conn) + newGrps, err := cc.Rules(ctx, nil) + if err != nil { + return nil, fmt.Errorf("unable to retrieve rules from other rulers, %v", err) + } + rgs = append(rgs, newGrps.Groups...) + } + } + + return rgs, nil +} + +func (r *Ruler) getRules(userID string) ([]*rules.RuleGroupDesc, error) { + groupDescs := []*rules.RuleGroupDesc{} + + var groups []*promRules.Group + r.userManagerMtx.Lock() + mngr, exists := r.userManagers[userID] + if exists { + groups = mngr.RuleGroups() + } + r.userManagerMtx.Unlock() + + for _, group := range groups { + interval := group.Interval() + groupDesc := &rules.RuleGroupDesc{ + Name: group.Name(), + Namespace: group.File(), + Interval: &interval, + User: userID, + } + for _, r := range group.Rules() { + lastError := "" + if r.LastError() != nil { + lastError = r.LastError().Error() + } + + var ruleDesc *rules.RuleDesc + switch rule := r.(type) { + case *promRules.AlertingRule: + dur := rule.Duration() + rule.ActiveAlerts() + alerts := []*rules.Alert{} + for _, a := range rule.ActiveAlerts() { + alerts = append(alerts, &rules.Alert{ + State: a.State.String(), + Labels: client.FromLabelsToLabelAdapters(a.Labels), + Annotations: client.FromLabelsToLabelAdapters(a.Annotations), + Value: a.Value, + ActiveAt: &a.ActiveAt, + FiredAt: &a.FiredAt, + ResolvedAt: &a.ResolvedAt, + LastSentAt: &a.LastSentAt, + ValidUntil: &a.ValidUntil, + }) + } + ruleDesc = &rules.RuleDesc{ + State: rule.State().String(), + Alert: rule.Name(), + Alerts: alerts, + Expr: rule.Query().String(), + For: &dur, + Labels: client.FromLabelsToLabelAdapters(rule.Labels()), + Annotations: client.FromLabelsToLabelAdapters(rule.Annotations()), + Health: string(rule.Health()), + LastError: lastError, + } + case *promRules.RecordingRule: + ruleDesc = &rules.RuleDesc{ + Record: rule.Name(), + Expr: rule.Query().String(), + Labels: client.FromLabelsToLabelAdapters(rule.Labels()), + Health: string(rule.Health()), + LastError: lastError, + } + default: + return nil, errors.Errorf("failed to assert type of rule '%v'", rule.Name()) + } + groupDesc.Rules = append(groupDesc.Rules, ruleDesc) + } + groupDescs = append(groupDescs, groupDesc) + } + return groupDescs, nil +} + +// Rules implements the rules service +func (r *Ruler) Rules(ctx context.Context, in *RulesRequest) (*RulesResponse, error) { + userID, err := user.ExtractOrgID(ctx) + if err != nil { + return nil, fmt.Errorf("no user id found in context") + } + + groupDescs, err := r.getRules(userID) + if err != nil { + return nil, err + } + + return &RulesResponse{Groups: groupDescs}, nil +} diff --git a/pkg/ruler/ruler.pb.go b/pkg/ruler/ruler.pb.go new file mode 100644 index 00000000000..a70d058ece8 --- /dev/null +++ b/pkg/ruler/ruler.pb.go @@ -0,0 +1,657 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ruler.proto + +package ruler + +import ( + context "context" + fmt "fmt" + rules "github.com/cortexproject/cortex/pkg/ruler/rules" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + io "io" + math "math" + reflect "reflect" + strings "strings" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +type RulesRequest struct { +} + +func (m *RulesRequest) Reset() { *m = RulesRequest{} } +func (*RulesRequest) ProtoMessage() {} +func (*RulesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9ecbec0a4cfddea6, []int{0} +} +func (m *RulesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RulesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RulesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RulesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RulesRequest.Merge(m, src) +} +func (m *RulesRequest) XXX_Size() int { + return m.Size() +} +func (m *RulesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_RulesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_RulesRequest proto.InternalMessageInfo + +type RulesResponse struct { + Groups []*rules.RuleGroupDesc `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` +} + +func (m *RulesResponse) Reset() { *m = RulesResponse{} } +func (*RulesResponse) ProtoMessage() {} +func (*RulesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9ecbec0a4cfddea6, []int{1} +} +func (m *RulesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RulesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RulesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RulesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_RulesResponse.Merge(m, src) +} +func (m *RulesResponse) XXX_Size() int { + return m.Size() +} +func (m *RulesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_RulesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_RulesResponse proto.InternalMessageInfo + +func (m *RulesResponse) GetGroups() []*rules.RuleGroupDesc { + if m != nil { + return m.Groups + } + return nil +} + +func init() { + proto.RegisterType((*RulesRequest)(nil), "ruler.RulesRequest") + proto.RegisterType((*RulesResponse)(nil), "ruler.RulesResponse") +} + +func init() { proto.RegisterFile("ruler.proto", fileDescriptor_9ecbec0a4cfddea6) } + +var fileDescriptor_9ecbec0a4cfddea6 = []byte{ + // 251 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0x3d, 0x4e, 0xc4, 0x30, + 0x10, 0x85, 0x6d, 0xa1, 0xdd, 0xc2, 0x0b, 0x14, 0x61, 0x0b, 0x94, 0x62, 0x84, 0x52, 0x51, 0x40, + 0x22, 0x2d, 0xdb, 0xa1, 0x6d, 0x10, 0x12, 0x7d, 0x8e, 0x90, 0xc8, 0x98, 0xff, 0x31, 0xfe, 0x91, + 0x28, 0x39, 0x02, 0xc7, 0xe0, 0x28, 0x94, 0x29, 0xb7, 0x24, 0x4e, 0x43, 0xb9, 0x47, 0x40, 0x1e, + 0xa7, 0xc8, 0x36, 0xa3, 0xf9, 0xfc, 0xde, 0xf3, 0xe8, 0x89, 0x85, 0xf1, 0x2f, 0xd2, 0x94, 0xda, + 0xa0, 0xc3, 0x6c, 0x46, 0x90, 0x5f, 0xaa, 0x47, 0xf7, 0xe0, 0x9b, 0xb2, 0xc5, 0xd7, 0x4a, 0xa1, + 0xc2, 0x8a, 0xd4, 0xc6, 0xdf, 0x13, 0x11, 0xd0, 0x96, 0x52, 0xf9, 0xf5, 0xc4, 0xde, 0xa2, 0x71, + 0xf2, 0x43, 0x1b, 0x7c, 0x92, 0xad, 0x1b, 0xa9, 0xd2, 0xcf, 0xaa, 0xa2, 0x9f, 0x69, 0xda, 0x34, + 0x53, 0xb8, 0x38, 0x16, 0x87, 0x75, 0xc4, 0x5a, 0xbe, 0x7b, 0x69, 0x5d, 0xb1, 0x11, 0x47, 0x23, + 0x5b, 0x8d, 0x6f, 0x56, 0x66, 0x17, 0x62, 0xae, 0x0c, 0x7a, 0x6d, 0x4f, 0xf9, 0xd9, 0xc1, 0xf9, + 0x62, 0xb5, 0x2c, 0x53, 0x3c, 0xba, 0xee, 0xa2, 0x70, 0x2b, 0x6d, 0x5b, 0x8f, 0x9e, 0xd5, 0x46, + 0xcc, 0xa2, 0x60, 0xb2, 0x75, 0x5a, 0x6c, 0x76, 0x52, 0xa6, 0x86, 0xd3, 0x2b, 0xf9, 0x72, 0xff, + 0x31, 0x9d, 0x2a, 0xd8, 0xcd, 0xba, 0xeb, 0x81, 0x6d, 0x7b, 0x60, 0xbb, 0x1e, 0xf8, 0x67, 0x00, + 0xfe, 0x1d, 0x80, 0xff, 0x04, 0xe0, 0x5d, 0x00, 0xfe, 0x1b, 0x80, 0xff, 0x05, 0x60, 0xbb, 0x00, + 0xfc, 0x6b, 0x00, 0xd6, 0x0d, 0xc0, 0xb6, 0x03, 0xb0, 0x66, 0x4e, 0x55, 0xae, 0xfe, 0x03, 0x00, + 0x00, 0xff, 0xff, 0xec, 0x23, 0x45, 0x0d, 0x4c, 0x01, 0x00, 0x00, +} + +func (this *RulesRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RulesRequest) + if !ok { + that2, ok := that.(RulesRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *RulesResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RulesResponse) + if !ok { + that2, ok := that.(RulesResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Groups) != len(that1.Groups) { + return false + } + for i := range this.Groups { + if !this.Groups[i].Equal(that1.Groups[i]) { + return false + } + } + return true +} +func (this *RulesRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 4) + s = append(s, "&ruler.RulesRequest{") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *RulesResponse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&ruler.RulesResponse{") + if this.Groups != nil { + s = append(s, "Groups: "+fmt.Sprintf("%#v", this.Groups)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringRuler(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// RulerClient is the client API for Ruler service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type RulerClient interface { + Rules(ctx context.Context, in *RulesRequest, opts ...grpc.CallOption) (*RulesResponse, error) +} + +type rulerClient struct { + cc *grpc.ClientConn +} + +func NewRulerClient(cc *grpc.ClientConn) RulerClient { + return &rulerClient{cc} +} + +func (c *rulerClient) Rules(ctx context.Context, in *RulesRequest, opts ...grpc.CallOption) (*RulesResponse, error) { + out := new(RulesResponse) + err := c.cc.Invoke(ctx, "/ruler.Ruler/Rules", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RulerServer is the server API for Ruler service. +type RulerServer interface { + Rules(context.Context, *RulesRequest) (*RulesResponse, error) +} + +func RegisterRulerServer(s *grpc.Server, srv RulerServer) { + s.RegisterService(&_Ruler_serviceDesc, srv) +} + +func _Ruler_Rules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RulesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RulerServer).Rules(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ruler.Ruler/Rules", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RulerServer).Rules(ctx, req.(*RulesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Ruler_serviceDesc = grpc.ServiceDesc{ + ServiceName: "ruler.Ruler", + HandlerType: (*RulerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Rules", + Handler: _Ruler_Rules_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "ruler.proto", +} + +func (m *RulesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RulesRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *RulesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RulesResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Groups) > 0 { + for _, msg := range m.Groups { + dAtA[i] = 0xa + i++ + i = encodeVarintRuler(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func encodeVarintRuler(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *RulesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *RulesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovRuler(uint64(l)) + } + } + return n +} + +func sovRuler(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozRuler(x uint64) (n int) { + return sovRuler(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *RulesRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RulesRequest{`, + `}`, + }, "") + return s +} +func (this *RulesResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RulesResponse{`, + `Groups:` + strings.Replace(fmt.Sprintf("%v", this.Groups), "RuleGroupDesc", "rules.RuleGroupDesc", 1) + `,`, + `}`, + }, "") + return s +} +func valueToStringRuler(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *RulesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRuler + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RulesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RulesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipRuler(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRuler + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRuler + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RulesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRuler + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RulesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RulesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRuler + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRuler + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRuler + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, &rules.RuleGroupDesc{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRuler(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRuler + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRuler + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipRuler(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowRuler + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowRuler + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowRuler + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthRuler + } + iNdEx += length + if iNdEx < 0 { + return 0, ErrInvalidLengthRuler + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowRuler + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipRuler(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + if iNdEx < 0 { + return 0, ErrInvalidLengthRuler + } + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthRuler = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowRuler = fmt.Errorf("proto: integer overflow") +) diff --git a/pkg/ruler/ruler.proto b/pkg/ruler/ruler.proto new file mode 100644 index 00000000000..149924a2d7f --- /dev/null +++ b/pkg/ruler/ruler.proto @@ -0,0 +1,22 @@ +// Ruler Service Representation +// This service is used to retrieve the current state of rules running across +// all Rulers in a cluster. It allows cortex to fully serve the `/api/v1/{rules|alerts}` +// Prometheus API +syntax = "proto3"; +package ruler; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "github.com/cortexproject/cortex/pkg/ruler/rules/rules.proto"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; + +service Ruler { + rpc Rules(RulesRequest) returns (RulesResponse) {}; +} + +message RulesRequest {} + +message RulesResponse { + repeated rules.RuleGroupDesc groups = 1; +} diff --git a/pkg/ruler/rules/rules.pb.go b/pkg/ruler/rules/rules.pb.go index 9219afeb376..a21bf3abb79 100644 --- a/pkg/ruler/rules/rules.pb.go +++ b/pkg/ruler/rules/rules.pb.go @@ -4,6 +4,7 @@ package rules import ( + encoding_binary "encoding/binary" fmt "fmt" _ "github.com/cortexproject/cortex/pkg/ingester/client" github_com_cortexproject_cortex_pkg_ingester_client "github.com/cortexproject/cortex/pkg/ingester/client" @@ -11,6 +12,7 @@ import ( proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" _ "github.com/golang/protobuf/ptypes/duration" + _ "github.com/golang/protobuf/ptypes/timestamp" io "io" math "math" reflect "reflect" @@ -122,6 +124,10 @@ type RuleDesc struct { For *time.Duration `protobuf:"bytes,4,opt,name=for,proto3,stdduration" json:"for,omitempty"` Labels []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,5,rep,name=labels,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"labels"` Annotations []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,6,rep,name=annotations,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"annotations"` + State string `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` + Health string `protobuf:"bytes,8,opt,name=health,proto3" json:"health,omitempty"` + LastError string `protobuf:"bytes,9,opt,name=lastError,proto3" json:"lastError,omitempty"` + Alerts []*Alert `protobuf:"bytes,10,rep,name=alerts,proto3" json:"alerts,omitempty"` } func (m *RuleDesc) Reset() { *m = RuleDesc{} } @@ -184,43 +190,178 @@ func (m *RuleDesc) GetFor() *time.Duration { return nil } +func (m *RuleDesc) GetState() string { + if m != nil { + return m.State + } + return "" +} + +func (m *RuleDesc) GetHealth() string { + if m != nil { + return m.Health + } + return "" +} + +func (m *RuleDesc) GetLastError() string { + if m != nil { + return m.LastError + } + return "" +} + +func (m *RuleDesc) GetAlerts() []*Alert { + if m != nil { + return m.Alerts + } + return nil +} + +type Alert struct { + State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Labels []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,2,rep,name=labels,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"labels"` + Annotations []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,3,rep,name=annotations,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"annotations"` + Value float64 `protobuf:"fixed64,4,opt,name=value,proto3" json:"value,omitempty"` + ActiveAt *time.Time `protobuf:"bytes,5,opt,name=active_at,json=activeAt,proto3,stdtime" json:"active_at,omitempty"` + FiredAt *time.Time `protobuf:"bytes,6,opt,name=fired_at,json=firedAt,proto3,stdtime" json:"fired_at,omitempty"` + ResolvedAt *time.Time `protobuf:"bytes,7,opt,name=resolved_at,json=resolvedAt,proto3,stdtime" json:"resolved_at,omitempty"` + LastSentAt *time.Time `protobuf:"bytes,8,opt,name=last_sent_at,json=lastSentAt,proto3,stdtime" json:"last_sent_at,omitempty"` + ValidUntil *time.Time `protobuf:"bytes,9,opt,name=valid_until,json=validUntil,proto3,stdtime" json:"valid_until,omitempty"` +} + +func (m *Alert) Reset() { *m = Alert{} } +func (*Alert) ProtoMessage() {} +func (*Alert) Descriptor() ([]byte, []int) { + return fileDescriptor_8e722d3e922f0937, []int{2} +} +func (m *Alert) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Alert) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Alert.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalTo(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Alert) XXX_Merge(src proto.Message) { + xxx_messageInfo_Alert.Merge(m, src) +} +func (m *Alert) XXX_Size() int { + return m.Size() +} +func (m *Alert) XXX_DiscardUnknown() { + xxx_messageInfo_Alert.DiscardUnknown(m) +} + +var xxx_messageInfo_Alert proto.InternalMessageInfo + +func (m *Alert) GetState() string { + if m != nil { + return m.State + } + return "" +} + +func (m *Alert) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +func (m *Alert) GetActiveAt() *time.Time { + if m != nil { + return m.ActiveAt + } + return nil +} + +func (m *Alert) GetFiredAt() *time.Time { + if m != nil { + return m.FiredAt + } + return nil +} + +func (m *Alert) GetResolvedAt() *time.Time { + if m != nil { + return m.ResolvedAt + } + return nil +} + +func (m *Alert) GetLastSentAt() *time.Time { + if m != nil { + return m.LastSentAt + } + return nil +} + +func (m *Alert) GetValidUntil() *time.Time { + if m != nil { + return m.ValidUntil + } + return nil +} + func init() { proto.RegisterType((*RuleGroupDesc)(nil), "rules.RuleGroupDesc") proto.RegisterType((*RuleDesc)(nil), "rules.RuleDesc") + proto.RegisterType((*Alert)(nil), "rules.Alert") } func init() { proto.RegisterFile("rules.proto", fileDescriptor_8e722d3e922f0937) } var fileDescriptor_8e722d3e922f0937 = []byte{ - // 448 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x51, 0x41, 0x8b, 0xd4, 0x30, - 0x14, 0x6e, 0x76, 0x66, 0xea, 0x4c, 0x06, 0x11, 0x83, 0x48, 0x5c, 0x24, 0x53, 0x16, 0x84, 0x5e, - 0x6c, 0x71, 0x3d, 0xee, 0x45, 0x87, 0x05, 0x3d, 0x78, 0x90, 0x1e, 0xbd, 0xa5, 0xed, 0xdb, 0x5a, - 0xcd, 0x36, 0x25, 0x49, 0xc5, 0x8b, 0xe0, 0x4f, 0xf0, 0xe8, 0x4f, 0xf0, 0xa7, 0xec, 0x71, 0xc0, - 0xcb, 0xe2, 0x61, 0x75, 0x3a, 0x17, 0x8f, 0x0b, 0xfe, 0x01, 0x49, 0xd2, 0xba, 0x7b, 0x14, 0xc1, - 0x53, 0xde, 0x97, 0xef, 0xe5, 0xbd, 0xef, 0xfb, 0x82, 0x97, 0xaa, 0x13, 0xa0, 0x93, 0x56, 0x49, - 0x23, 0xc9, 0xcc, 0x81, 0xfd, 0x87, 0x55, 0x6d, 0x5e, 0x77, 0x79, 0x52, 0xc8, 0xd3, 0xb4, 0x92, - 0x95, 0x4c, 0x1d, 0x9b, 0x77, 0x27, 0x0e, 0x39, 0xe0, 0x2a, 0xff, 0x6a, 0x9f, 0x55, 0x52, 0x56, - 0x02, 0xae, 0xba, 0xca, 0x4e, 0x71, 0x53, 0xcb, 0x66, 0xe0, 0x9f, 0x5c, 0x1b, 0x57, 0x48, 0x65, - 0xe0, 0x7d, 0xab, 0xe4, 0x1b, 0x28, 0xcc, 0x80, 0xd2, 0xf6, 0x6d, 0x95, 0xd6, 0x4d, 0x05, 0xda, - 0x80, 0x4a, 0x0b, 0x51, 0x43, 0x33, 0x52, 0x7e, 0xc2, 0xc1, 0x57, 0x84, 0x6f, 0x66, 0x9d, 0x80, - 0x67, 0x4a, 0x76, 0xed, 0x31, 0xe8, 0x82, 0x10, 0x3c, 0x6d, 0xf8, 0x29, 0x50, 0x14, 0xa1, 0x78, - 0x91, 0xb9, 0x9a, 0xdc, 0xc7, 0x0b, 0x7b, 0xea, 0x96, 0x17, 0x40, 0xf7, 0x1c, 0x71, 0x75, 0x41, - 0x8e, 0xf0, 0xbc, 0x6e, 0x0c, 0xa8, 0x77, 0x5c, 0xd0, 0x49, 0x84, 0xe2, 0xe5, 0xe1, 0xbd, 0xc4, - 0x0b, 0x4f, 0x46, 0xe1, 0xc9, 0xf1, 0x20, 0x7c, 0x3d, 0xfd, 0xfc, 0x7d, 0x85, 0xb2, 0x3f, 0x0f, - 0xc8, 0x03, 0xec, 0xa3, 0xa1, 0xd3, 0x68, 0x12, 0x2f, 0x0f, 0x6f, 0x25, 0x3e, 0x35, 0xab, 0xc9, - 0xca, 0xc9, 0x3c, 0x4b, 0x28, 0xbe, 0x51, 0x82, 0x00, 0x03, 0x25, 0x9d, 0x45, 0x28, 0x9e, 0x67, - 0x23, 0xb4, 0x7a, 0x3b, 0x0d, 0x8a, 0x86, 0x5e, 0xaf, 0xad, 0x0f, 0x7e, 0xed, 0xe1, 0xf9, 0x38, - 0xc1, 0x36, 0xd8, 0x5c, 0x46, 0x43, 0xb6, 0x26, 0x77, 0x71, 0xa8, 0xa0, 0x90, 0xaa, 0x1c, 0xdc, - 0x0c, 0x88, 0xdc, 0xc1, 0x33, 0x2e, 0x40, 0x19, 0xe7, 0x63, 0x91, 0x79, 0x40, 0x1e, 0xe1, 0xc9, - 0x89, 0x54, 0x74, 0xfa, 0x77, 0xde, 0x6c, 0x2f, 0xd1, 0x38, 0x14, 0x3c, 0x07, 0xa1, 0xe9, 0xcc, - 0xf9, 0xba, 0x9d, 0x0c, 0xb1, 0xbf, 0xb0, 0xb7, 0x2f, 0x79, 0xad, 0xd6, 0xcf, 0xcf, 0x2e, 0x56, - 0xc1, 0xb7, 0x8b, 0xd5, 0xbf, 0x7c, 0xa2, 0x1f, 0xf3, 0xb4, 0xe4, 0xad, 0x01, 0x95, 0x0d, 0xab, - 0xc8, 0x07, 0xbc, 0xe4, 0x4d, 0x23, 0x8d, 0x53, 0xa3, 0x69, 0xf8, 0xff, 0x37, 0x5f, 0xdf, 0xb7, - 0x3e, 0xda, 0x6c, 0x59, 0x70, 0xbe, 0x65, 0xc1, 0xe5, 0x96, 0xa1, 0x8f, 0x3d, 0x43, 0x5f, 0x7a, - 0x86, 0xce, 0x7a, 0x86, 0x36, 0x3d, 0x43, 0x3f, 0x7a, 0x86, 0x7e, 0xf6, 0x2c, 0xb8, 0xec, 0x19, - 0xfa, 0xb4, 0x63, 0xc1, 0x66, 0xc7, 0x82, 0xf3, 0x1d, 0x0b, 0x5e, 0xf9, 0x0f, 0xce, 0x43, 0x17, - 0xe7, 0xe3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x67, 0x3a, 0xe5, 0x13, 0x36, 0x03, 0x00, 0x00, + // 645 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0x4f, 0x6b, 0x14, 0x31, + 0x14, 0xdf, 0x74, 0xff, 0x67, 0x2b, 0x62, 0x10, 0x89, 0x45, 0xb2, 0x4b, 0x51, 0xd8, 0x8b, 0xbb, + 0x58, 0x8f, 0x45, 0x70, 0x97, 0x8a, 0x1e, 0x3c, 0xc8, 0xa8, 0x17, 0x2f, 0x25, 0x3b, 0xf3, 0x3a, + 0x1d, 0xcd, 0x4e, 0x86, 0x24, 0xb3, 0x78, 0x11, 0xfc, 0x08, 0x3d, 0xfa, 0x11, 0xfc, 0x28, 0x3d, + 0x16, 0xbc, 0x14, 0x0f, 0xd5, 0x4e, 0x11, 0xbc, 0x08, 0xfd, 0x08, 0x92, 0x64, 0xa6, 0x5b, 0xf4, + 0xb2, 0x08, 0xea, 0x69, 0xf2, 0x7b, 0x2f, 0xbf, 0xf7, 0xe7, 0xf7, 0x5e, 0x06, 0xf7, 0x54, 0x2e, + 0x40, 0x8f, 0x32, 0x25, 0x8d, 0x24, 0x4d, 0x07, 0x36, 0xee, 0xc6, 0x89, 0xd9, 0xcf, 0x67, 0xa3, + 0x50, 0xce, 0xc7, 0xb1, 0x8c, 0xe5, 0xd8, 0x79, 0x67, 0xf9, 0x9e, 0x43, 0x0e, 0xb8, 0x93, 0x67, + 0x6d, 0xb0, 0x58, 0xca, 0x58, 0xc0, 0xf2, 0x56, 0x94, 0x2b, 0x6e, 0x12, 0x99, 0x96, 0xfe, 0xfe, + 0xaf, 0x7e, 0x93, 0xcc, 0x41, 0x1b, 0x3e, 0xcf, 0xca, 0x0b, 0x0f, 0x2f, 0xe5, 0x0b, 0xa5, 0x32, + 0xf0, 0x36, 0x53, 0xf2, 0x35, 0x84, 0xa6, 0x44, 0xe3, 0xec, 0x4d, 0x3c, 0x4e, 0xd2, 0x18, 0xb4, + 0x01, 0x35, 0x0e, 0x45, 0x02, 0x69, 0xe5, 0xf2, 0x11, 0x36, 0x3f, 0x21, 0x7c, 0x25, 0xc8, 0x05, + 0x3c, 0x56, 0x32, 0xcf, 0x76, 0x40, 0x87, 0x84, 0xe0, 0x46, 0xca, 0xe7, 0x40, 0xd1, 0x00, 0x0d, + 0xbb, 0x81, 0x3b, 0x93, 0x5b, 0xb8, 0x6b, 0xbf, 0x3a, 0xe3, 0x21, 0xd0, 0x35, 0xe7, 0x58, 0x1a, + 0xc8, 0x36, 0xee, 0x24, 0xa9, 0x01, 0xb5, 0xe0, 0x82, 0xd6, 0x07, 0x68, 0xd8, 0xdb, 0xba, 0x39, + 0xf2, 0x95, 0x8f, 0xaa, 0xca, 0x47, 0x3b, 0x65, 0x67, 0xd3, 0xc6, 0x87, 0x2f, 0x7d, 0x14, 0x5c, + 0x10, 0xc8, 0x1d, 0xec, 0xb5, 0xa3, 0x8d, 0x41, 0x7d, 0xd8, 0xdb, 0xba, 0x3a, 0xf2, 0xb2, 0xda, + 0x9a, 0x6c, 0x39, 0x81, 0xf7, 0x12, 0x8a, 0xdb, 0x11, 0x08, 0x30, 0x10, 0xd1, 0xe6, 0x00, 0x0d, + 0x3b, 0x41, 0x05, 0x6d, 0xbd, 0xb9, 0x06, 0x45, 0x5b, 0xbe, 0x5e, 0x7b, 0xde, 0xfc, 0x56, 0xc7, + 0x9d, 0x2a, 0x82, 0xbd, 0x60, 0x75, 0xa9, 0x1a, 0xb2, 0x67, 0x72, 0x03, 0xb7, 0x14, 0x84, 0x52, + 0x45, 0x65, 0x37, 0x25, 0x22, 0xd7, 0x71, 0x93, 0x0b, 0x50, 0xc6, 0xf5, 0xd1, 0x0d, 0x3c, 0x20, + 0xf7, 0x70, 0x7d, 0x4f, 0x2a, 0xda, 0x58, 0xad, 0x37, 0x7b, 0x97, 0x68, 0xdc, 0x12, 0x7c, 0x06, + 0x42, 0xd3, 0xa6, 0xeb, 0xeb, 0xda, 0xa8, 0x94, 0xfd, 0xa9, 0xb5, 0x3e, 0xe3, 0x89, 0x9a, 0x3e, + 0x39, 0x3c, 0xe9, 0xd7, 0x3e, 0x9f, 0xf4, 0xff, 0x64, 0x88, 0x3e, 0xcc, 0x24, 0xe2, 0x99, 0x01, + 0x15, 0x94, 0xa9, 0xc8, 0x3b, 0xdc, 0xe3, 0x69, 0x2a, 0x8d, 0xab, 0x46, 0xd3, 0xd6, 0xdf, 0xcf, + 0x7c, 0x39, 0x9f, 0x15, 0x4f, 0x1b, 0x6e, 0x80, 0xb6, 0xbd, 0x78, 0x0e, 0x58, 0xa9, 0xf7, 0x81, + 0x0b, 0xb3, 0x4f, 0x3b, 0x5e, 0x6a, 0x8f, 0xec, 0x4e, 0x09, 0xae, 0xcd, 0x23, 0xa5, 0xa4, 0xa2, + 0x5d, 0xbf, 0x53, 0x17, 0x06, 0x72, 0x1b, 0xb7, 0x9c, 0xf6, 0x9a, 0x62, 0xd7, 0xc5, 0x7a, 0xb9, + 0x17, 0x13, 0x6b, 0x0c, 0x4a, 0xdf, 0xe6, 0x8f, 0x06, 0x6e, 0x3a, 0xcb, 0x32, 0x37, 0xba, 0x9c, + 0x7b, 0x39, 0x85, 0xb5, 0xff, 0x36, 0x85, 0xfa, 0xbf, 0x9f, 0xc2, 0x82, 0x8b, 0x1c, 0xdc, 0xba, + 0xa2, 0xc0, 0x03, 0xf2, 0x00, 0x77, 0x79, 0x68, 0x92, 0x05, 0xec, 0x72, 0xe3, 0x5e, 0x50, 0x6f, + 0x6b, 0xe3, 0xb7, 0x45, 0x7e, 0x51, 0xfd, 0x5e, 0xa6, 0x8d, 0x03, 0xf7, 0x4a, 0x3d, 0x65, 0x62, + 0xec, 0x13, 0xdf, 0x4b, 0x14, 0x44, 0x96, 0xdd, 0x5a, 0x91, 0xdd, 0x76, 0x8c, 0x89, 0x21, 0x13, + 0xdc, 0x53, 0xa0, 0xa5, 0x58, 0x78, 0x7e, 0x7b, 0x45, 0x3e, 0xae, 0x48, 0x13, 0x43, 0xa6, 0x78, + 0xdd, 0xee, 0xc6, 0xae, 0x86, 0xd4, 0xd8, 0x18, 0x9d, 0x55, 0x63, 0x58, 0xd6, 0x73, 0x48, 0x8d, + 0x2f, 0x63, 0xc1, 0x45, 0x12, 0xed, 0xe6, 0xa9, 0x49, 0x84, 0x5b, 0xb9, 0x95, 0x42, 0x38, 0xd2, + 0x4b, 0xcb, 0x99, 0x6e, 0x1f, 0x9d, 0xb2, 0xda, 0xf1, 0x29, 0xab, 0x9d, 0x9f, 0x32, 0xf4, 0xbe, + 0x60, 0xe8, 0x63, 0xc1, 0xd0, 0x61, 0xc1, 0xd0, 0x51, 0xc1, 0xd0, 0xd7, 0x82, 0xa1, 0xef, 0x05, + 0xab, 0x9d, 0x17, 0x0c, 0x1d, 0x9c, 0xb1, 0xda, 0xd1, 0x19, 0xab, 0x1d, 0x9f, 0xb1, 0xda, 0x2b, + 0xff, 0x0b, 0x9b, 0xb5, 0x5c, 0x8a, 0xfb, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xf4, 0x48, + 0x2d, 0x39, 0x06, 0x00, 0x00, } func (this *RuleGroupDesc) Equal(that interface{}) bool { @@ -326,6 +467,101 @@ func (this *RuleDesc) Equal(that interface{}) bool { return false } } + if this.State != that1.State { + return false + } + if this.Health != that1.Health { + return false + } + if this.LastError != that1.LastError { + return false + } + if len(this.Alerts) != len(that1.Alerts) { + return false + } + for i := range this.Alerts { + if !this.Alerts[i].Equal(that1.Alerts[i]) { + return false + } + } + return true +} +func (this *Alert) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Alert) + if !ok { + that2, ok := that.(Alert) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.State != that1.State { + return false + } + if len(this.Labels) != len(that1.Labels) { + return false + } + for i := range this.Labels { + if !this.Labels[i].Equal(that1.Labels[i]) { + return false + } + } + if len(this.Annotations) != len(that1.Annotations) { + return false + } + for i := range this.Annotations { + if !this.Annotations[i].Equal(that1.Annotations[i]) { + return false + } + } + if this.Value != that1.Value { + return false + } + if that1.ActiveAt == nil { + if this.ActiveAt != nil { + return false + } + } else if !this.ActiveAt.Equal(*that1.ActiveAt) { + return false + } + if that1.FiredAt == nil { + if this.FiredAt != nil { + return false + } + } else if !this.FiredAt.Equal(*that1.FiredAt) { + return false + } + if that1.ResolvedAt == nil { + if this.ResolvedAt != nil { + return false + } + } else if !this.ResolvedAt.Equal(*that1.ResolvedAt) { + return false + } + if that1.LastSentAt == nil { + if this.LastSentAt != nil { + return false + } + } else if !this.LastSentAt.Equal(*that1.LastSentAt) { + return false + } + if that1.ValidUntil == nil { + if this.ValidUntil != nil { + return false + } + } else if !this.ValidUntil.Equal(*that1.ValidUntil) { + return false + } return true } func (this *RuleGroupDesc) GoString() string { @@ -349,7 +585,7 @@ func (this *RuleDesc) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 10) + s := make([]string, 0, 14) s = append(s, "&rules.RuleDesc{") s = append(s, "Expr: "+fmt.Sprintf("%#v", this.Expr)+",\n") s = append(s, "Record: "+fmt.Sprintf("%#v", this.Record)+",\n") @@ -357,6 +593,30 @@ func (this *RuleDesc) GoString() string { s = append(s, "For: "+fmt.Sprintf("%#v", this.For)+",\n") s = append(s, "Labels: "+fmt.Sprintf("%#v", this.Labels)+",\n") s = append(s, "Annotations: "+fmt.Sprintf("%#v", this.Annotations)+",\n") + s = append(s, "State: "+fmt.Sprintf("%#v", this.State)+",\n") + s = append(s, "Health: "+fmt.Sprintf("%#v", this.Health)+",\n") + s = append(s, "LastError: "+fmt.Sprintf("%#v", this.LastError)+",\n") + if this.Alerts != nil { + s = append(s, "Alerts: "+fmt.Sprintf("%#v", this.Alerts)+",\n") + } + s = append(s, "}") + return strings.Join(s, "") +} +func (this *Alert) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 13) + s = append(s, "&rules.Alert{") + s = append(s, "State: "+fmt.Sprintf("%#v", this.State)+",\n") + s = append(s, "Labels: "+fmt.Sprintf("%#v", this.Labels)+",\n") + s = append(s, "Annotations: "+fmt.Sprintf("%#v", this.Annotations)+",\n") + s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") + s = append(s, "ActiveAt: "+fmt.Sprintf("%#v", this.ActiveAt)+",\n") + s = append(s, "FiredAt: "+fmt.Sprintf("%#v", this.FiredAt)+",\n") + s = append(s, "ResolvedAt: "+fmt.Sprintf("%#v", this.ResolvedAt)+",\n") + s = append(s, "LastSentAt: "+fmt.Sprintf("%#v", this.LastSentAt)+",\n") + s = append(s, "ValidUntil: "+fmt.Sprintf("%#v", this.ValidUntil)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -503,6 +763,140 @@ func (m *RuleDesc) MarshalTo(dAtA []byte) (int, error) { i += n } } + if len(m.State) > 0 { + dAtA[i] = 0x3a + i++ + i = encodeVarintRules(dAtA, i, uint64(len(m.State))) + i += copy(dAtA[i:], m.State) + } + if len(m.Health) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintRules(dAtA, i, uint64(len(m.Health))) + i += copy(dAtA[i:], m.Health) + } + if len(m.LastError) > 0 { + dAtA[i] = 0x4a + i++ + i = encodeVarintRules(dAtA, i, uint64(len(m.LastError))) + i += copy(dAtA[i:], m.LastError) + } + if len(m.Alerts) > 0 { + for _, msg := range m.Alerts { + dAtA[i] = 0x52 + i++ + i = encodeVarintRules(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *Alert) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Alert) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.State) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintRules(dAtA, i, uint64(len(m.State))) + i += copy(dAtA[i:], m.State) + } + if len(m.Labels) > 0 { + for _, msg := range m.Labels { + dAtA[i] = 0x12 + i++ + i = encodeVarintRules(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Annotations) > 0 { + for _, msg := range m.Annotations { + dAtA[i] = 0x1a + i++ + i = encodeVarintRules(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.Value != 0 { + dAtA[i] = 0x21 + i++ + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) + i += 8 + } + if m.ActiveAt != nil { + dAtA[i] = 0x2a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ActiveAt))) + n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ActiveAt, dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 + } + if m.FiredAt != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.FiredAt))) + n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.FiredAt, dAtA[i:]) + if err != nil { + return 0, err + } + i += n4 + } + if m.ResolvedAt != nil { + dAtA[i] = 0x3a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ResolvedAt))) + n5, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ResolvedAt, dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + if m.LastSentAt != nil { + dAtA[i] = 0x42 + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastSentAt))) + n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.LastSentAt, dAtA[i:]) + if err != nil { + return 0, err + } + i += n6 + } + if m.ValidUntil != nil { + dAtA[i] = 0x4a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ValidUntil))) + n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ValidUntil, dAtA[i:]) + if err != nil { + return 0, err + } + i += n7 + } return i, nil } @@ -583,14 +977,80 @@ func (m *RuleDesc) Size() (n int) { n += 1 + l + sovRules(uint64(l)) } } + l = len(m.State) + if l > 0 { + n += 1 + l + sovRules(uint64(l)) + } + l = len(m.Health) + if l > 0 { + n += 1 + l + sovRules(uint64(l)) + } + l = len(m.LastError) + if l > 0 { + n += 1 + l + sovRules(uint64(l)) + } + if len(m.Alerts) > 0 { + for _, e := range m.Alerts { + l = e.Size() + n += 1 + l + sovRules(uint64(l)) + } + } return n } -func sovRules(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { +func (m *Alert) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.State) + if l > 0 { + n += 1 + l + sovRules(uint64(l)) + } + if len(m.Labels) > 0 { + for _, e := range m.Labels { + l = e.Size() + n += 1 + l + sovRules(uint64(l)) + } + } + if len(m.Annotations) > 0 { + for _, e := range m.Annotations { + l = e.Size() + n += 1 + l + sovRules(uint64(l)) + } + } + if m.Value != 0 { + n += 9 + } + if m.ActiveAt != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ActiveAt) + n += 1 + l + sovRules(uint64(l)) + } + if m.FiredAt != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.FiredAt) + n += 1 + l + sovRules(uint64(l)) + } + if m.ResolvedAt != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ResolvedAt) + n += 1 + l + sovRules(uint64(l)) + } + if m.LastSentAt != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastSentAt) + n += 1 + l + sovRules(uint64(l)) + } + if m.ValidUntil != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ValidUntil) + n += 1 + l + sovRules(uint64(l)) + } + return n +} + +func sovRules(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { break } } @@ -625,6 +1085,28 @@ func (this *RuleDesc) String() string { `For:` + strings.Replace(fmt.Sprintf("%v", this.For), "Duration", "duration.Duration", 1) + `,`, `Labels:` + fmt.Sprintf("%v", this.Labels) + `,`, `Annotations:` + fmt.Sprintf("%v", this.Annotations) + `,`, + `State:` + fmt.Sprintf("%v", this.State) + `,`, + `Health:` + fmt.Sprintf("%v", this.Health) + `,`, + `LastError:` + fmt.Sprintf("%v", this.LastError) + `,`, + `Alerts:` + strings.Replace(fmt.Sprintf("%v", this.Alerts), "Alert", "Alert", 1) + `,`, + `}`, + }, "") + return s +} +func (this *Alert) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&Alert{`, + `State:` + fmt.Sprintf("%v", this.State) + `,`, + `Labels:` + fmt.Sprintf("%v", this.Labels) + `,`, + `Annotations:` + fmt.Sprintf("%v", this.Annotations) + `,`, + `Value:` + fmt.Sprintf("%v", this.Value) + `,`, + `ActiveAt:` + strings.Replace(fmt.Sprintf("%v", this.ActiveAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, + `FiredAt:` + strings.Replace(fmt.Sprintf("%v", this.FiredAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, + `ResolvedAt:` + strings.Replace(fmt.Sprintf("%v", this.ResolvedAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, + `LastSentAt:` + strings.Replace(fmt.Sprintf("%v", this.LastSentAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, + `ValidUntil:` + strings.Replace(fmt.Sprintf("%v", this.ValidUntil), "Timestamp", "timestamp.Timestamp", 1) + `,`, `}`, }, "") return s @@ -668,7 +1150,310 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Namespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Interval", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Interval == nil { + m.Interval = new(time.Duration) + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.Interval, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Rules = append(m.Rules, &RuleDesc{}) + if err := m.Rules[len(m.Rules)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Deleted", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Deleted = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRules(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthRules + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthRules + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RuleDesc) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RuleDesc: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RuleDesc: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Expr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Record", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Record = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Alert", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -696,13 +1481,13 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Name = string(dAtA[iNdEx:postIndex]) + m.Alert = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field For", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowRules @@ -712,27 +1497,31 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthRules } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthRules } if postIndex > l { return io.ErrUnexpectedEOF } - m.Namespace = string(dAtA[iNdEx:postIndex]) + if m.For == nil { + m.For = new(time.Duration) + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.For, dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex - case 3: + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Interval", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -759,16 +1548,14 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Interval == nil { - m.Interval = new(time.Duration) - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.Interval, dAtA[iNdEx:postIndex]); err != nil { + m.Labels = append(m.Labels, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) + if err := m.Labels[len(m.Labels)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Rules", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -795,16 +1582,16 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Rules = append(m.Rules, &RuleDesc{}) - if err := m.Rules[len(m.Rules)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Annotations = append(m.Annotations, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) + if err := m.Annotations[len(m.Annotations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Deleted", wireType) + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) } - var v int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowRules @@ -814,15 +1601,27 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - v |= int(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } - m.Deleted = bool(v != 0) - case 6: + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.State = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Health", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -850,7 +1649,73 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.User = string(dAtA[iNdEx:postIndex]) + m.Health = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastError", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastError = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Alerts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Alerts = append(m.Alerts, &Alert{}) + if err := m.Alerts[len(m.Alerts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -876,7 +1741,7 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { } return nil } -func (m *RuleDesc) Unmarshal(dAtA []byte) error { +func (m *Alert) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -899,15 +1764,15 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RuleDesc: wiretype end group for non-group") + return fmt.Errorf("proto: Alert: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RuleDesc: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Alert: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Expr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -935,13 +1800,13 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Expr = string(dAtA[iNdEx:postIndex]) + m.State = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Record", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowRules @@ -951,29 +1816,31 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthRules } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthRules } if postIndex > l { return io.ErrUnexpectedEOF } - m.Record = string(dAtA[iNdEx:postIndex]) + m.Labels = append(m.Labels, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) + if err := m.Labels[len(m.Labels)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Alert", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowRules @@ -983,27 +1850,40 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthRules } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthRules } if postIndex > l { return io.ErrUnexpectedEOF } - m.Alert = string(dAtA[iNdEx:postIndex]) + m.Annotations = append(m.Annotations, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) + if err := m.Annotations[len(m.Annotations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 4: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.Value = float64(math.Float64frombits(v)) + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field For", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ActiveAt", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1030,16 +1910,16 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.For == nil { - m.For = new(time.Duration) + if m.ActiveAt == nil { + m.ActiveAt = new(time.Time) } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.For, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ActiveAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 5: + case 6: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field FiredAt", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1066,14 +1946,16 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Labels = append(m.Labels, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) - if err := m.Labels[len(m.Labels)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.FiredAt == nil { + m.FiredAt = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.FiredAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 6: + case 7: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ResolvedAt", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1100,8 +1982,82 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Annotations = append(m.Annotations, github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter{}) - if err := m.Annotations[len(m.Annotations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.ResolvedAt == nil { + m.ResolvedAt = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ResolvedAt, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastSentAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastSentAt == nil { + m.LastSentAt = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.LastSentAt, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidUntil", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRules + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRules + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRules + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ValidUntil == nil { + m.ValidUntil = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ValidUntil, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/pkg/ruler/rules/rules.proto b/pkg/ruler/rules/rules.proto index 0936db55fe3..b12bc9be00f 100644 --- a/pkg/ruler/rules/rules.proto +++ b/pkg/ruler/rules/rules.proto @@ -1,4 +1,3 @@ -// Rule Proto Representations syntax = "proto3"; @@ -8,6 +7,7 @@ option go_package = "rules"; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; import "github.com/cortexproject/cortex/pkg/ingester/client/cortex.proto"; option (gogoproto.marshaler_all) = true; @@ -17,7 +17,7 @@ option (gogoproto.unmarshaler_all) = true; message RuleGroupDesc { string name = 1; string namespace = 2; - google.protobuf.Duration interval = 3 [ (gogoproto.stdduration) = true ]; + google.protobuf.Duration interval = 3 [(gogoproto.stdduration) = true]; repeated RuleDesc rules = 4; bool deleted = 5; string user = 6; @@ -28,17 +28,39 @@ message RuleDesc { string expr = 1; string record = 2; string alert = 3; - google.protobuf.Duration for = 4 [(gogoproto.stdduration) = true]; - repeated cortex.LabelPair labels = 5 [ - (gogoproto.nullable) = false, - (gogoproto.customtype) = - "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" - ]; - ; - repeated cortex.LabelPair annotations = 6 [ - (gogoproto.nullable) = false, - (gogoproto.customtype) = - "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" - ]; - ; + google.protobuf.Duration for = 4 [(gogoproto.stdduration) = true]; + repeated cortex.LabelPair labels = 5 [ + (gogoproto.nullable) = false, + (gogoproto.customtype) = + "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" + ]; + repeated cortex.LabelPair annotations = 6 [ + (gogoproto.nullable) = false, + (gogoproto.customtype) = + "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" + ]; + string state = 7; + string health = 8; + string lastError = 9; + repeated Alert alerts = 10; +} + +message Alert { + string state = 1; + repeated cortex.LabelPair labels = 2 [ + (gogoproto.nullable) = false, + (gogoproto.customtype) = + "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" + ]; + repeated cortex.LabelPair annotations = 3 [ + (gogoproto.nullable) = false, + (gogoproto.customtype) = + "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" + ]; + double value = 4; + google.protobuf.Timestamp active_at = 5 [(gogoproto.stdtime) = true]; + google.protobuf.Timestamp fired_at = 6 [(gogoproto.stdtime) = true]; + google.protobuf.Timestamp resolved_at = 7 [(gogoproto.stdtime) = true]; + google.protobuf.Timestamp last_sent_at = 8 [(gogoproto.stdtime) = true]; + google.protobuf.Timestamp valid_until = 9 [(gogoproto.stdtime) = true]; } \ No newline at end of file From c7fc483d828debe8460603e4434d5aad0f90568a Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Fri, 17 Jan 2020 15:18:25 -0500 Subject: [PATCH 02/29] clean up deps Signed-off-by: Jacob Lisi --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index bc1ac886a60..e04127911a3 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,6 @@ require ( google.golang.org/api v0.14.0 google.golang.org/grpc v1.25.1 gopkg.in/yaml.v2 v2.2.5 - grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 ) replace github.com/Azure/azure-sdk-for-go => github.com/Azure/azure-sdk-for-go v36.2.0+incompatible diff --git a/go.sum b/go.sum index ac3c9b9330d..f2feb819a1c 100644 --- a/go.sum +++ b/go.sum @@ -1052,8 +1052,6 @@ gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/x4yG7qPBrtNfLY= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From ed010fe4b088ca2ce9b338559d3c6f7855e47423 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Fri, 17 Jan 2020 15:21:45 -0500 Subject: [PATCH 03/29] update changelog Signed-off-by: Jacob Lisi --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 423556e013a..b96b485627f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * `--querier.query-store-after` has been added in it's place. * [FEATURE] Added user sub rings to distribute users to a subset of ingesters. #1947 * `--experimental.distributor.user-subring-size` +* [FEATURE] Added flag `experimental.ruler.enable-api` to enable the ruler api which implements the Prometheus API `/api/v1/rules` and `/api/v1/alerts` endpoints. #1999 * [ENHANCEMENT] Experimental TSDB: Export TSDB Syncer metrics from Compactor component, they are prefixed with `cortex_compactor_`. #2023 * [ENHANCEMENT] Experimental TSDB: Added dedicated flag `-experimental.tsdb.bucket-store.tenant-sync-concurrency` to configure the maximum number of concurrent tenants for which blocks are synched. #2026 * [ENHANCEMENT] Experimental TSDB: Expose metrics for objstore operations (prefixed with `cortex__thanos_objstore_`, component being one of `ingester`, `querier` and `compactor`). #2027 From c5dfab9637af5ba576cb55d6959a75a7a4ad6ca6 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Fri, 17 Jan 2020 20:38:16 -0500 Subject: [PATCH 04/29] update documentation Signed-off-by: Jacob Lisi --- docs/configuration/config-file-reference.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index ba8d792c5c2..382b633d396 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -736,6 +736,10 @@ ring: # Period with which to attempt to flush rule groups. # CLI flag: -ruler.flush-period [flushcheckperiod: | default = 1m0s] + +# Enable the ruler api +# CLI flag: -experimental.ruler.enable-api +[enableapi: | default = false] ``` ## `alertmanager_config` From 142e5e1ddc8e9fba29242fe2e7e00f80fe31f82e Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 21 Jan 2020 12:36:05 -0500 Subject: [PATCH 05/29] register ruler routes in modules.go Signed-off-by: Jacob Lisi --- pkg/cortex/modules.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index f7405df8fb9..051756fc8a8 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -420,6 +420,10 @@ func (t *Cortex) initRuler(cfg *Config) (err error) { return } + if cfg.Ruler.EnableAPI { + t.ruler.RegisterRoutes(t.server.HTTP) + } + t.server.HTTP.Handle("/ruler_ring", t.ruler) return } From 43a45a9f5a2cf638dfb23f41b9e5734acb3942ba Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 21 Jan 2020 12:43:09 -0500 Subject: [PATCH 06/29] refactor to have proper struct tags and cleaner logic for rule retrieval Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 2 +- pkg/ruler/ruler.go | 69 +++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 24efeebaa8d..fafa0340ebd 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -33,7 +33,7 @@ func (r *Ruler) RegisterRoutes(router *mux.Router) { } } -// In order to reimplent the prometheus rules API, a large amount of code was copied over +// In order to reimplement the prometheus rules API, a large amount of code was copied over // This is required because the prometheus api implementation does not pass a context to // the rule retrieval function. // https://github.com/prometheus/prometheus/blob/2aacd807b3ec6ddd90ae55f3a42f4cffed561ea9/web/api/v1/api.go#L108 diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 756907d779b..36f3e7e5081 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -67,7 +67,7 @@ type Config struct { Ring RingConfig FlushCheckPeriod time.Duration - EnableAPI bool + EnableAPI bool `yaml:"enable_api"` } // RegisterFlags adds the flags required to config this to the given FlagSet @@ -455,44 +455,14 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag // GetRules retrieves the running rules from this ruler and all running rulers in the ring if // sharding is enabled func (r *Ruler) GetRules(ctx context.Context, userID string) ([]*rules.RuleGroupDesc, error) { - rgs, err := r.getRules(userID) - if err != nil { - return nil, err - } - if r.cfg.EnableSharding { - rulers, err := r.ring.GetAll() - if err != nil { - return nil, err - } - - ctx, err = user.InjectIntoGRPCRequest(ctx) - if err != nil { - return nil, fmt.Errorf("unable to inject user ID into grpc request, %v", err) - } - - for _, rlr := range rulers.Ingesters { - // Don't retrieve rules using GRPC from the same ingester - if rlr.GetAddr() == r.lifecycler.Addr { - continue - } - conn, err := grpc.Dial(rlr.Addr, grpc.WithInsecure()) - if err != nil { - return nil, err - } - cc := NewRulerClient(conn) - newGrps, err := cc.Rules(ctx, nil) - if err != nil { - return nil, fmt.Errorf("unable to retrieve rules from other rulers, %v", err) - } - rgs = append(rgs, newGrps.Groups...) - } + return r.getShardedRules(ctx, userID) } - return rgs, nil + return r.getLocalRules(userID) } -func (r *Ruler) getRules(userID string) ([]*rules.RuleGroupDesc, error) { +func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { groupDescs := []*rules.RuleGroupDesc{} var groups []*promRules.Group @@ -565,6 +535,35 @@ func (r *Ruler) getRules(userID string) ([]*rules.RuleGroupDesc, error) { return groupDescs, nil } +func (r *Ruler) getShardedRules(ctx context.Context, userID string) ([]*rules.RuleGroupDesc, error) { + rulers, err := r.ring.GetAll() + if err != nil { + return nil, err + } + + ctx, err = user.InjectIntoGRPCRequest(ctx) + if err != nil { + return nil, fmt.Errorf("unable to inject user ID into grpc request, %v", err) + } + + rgs := []*rules.RuleGroupDesc{} + + for _, rlr := range rulers.Ingesters { + conn, err := grpc.Dial(rlr.Addr, grpc.WithInsecure()) + if err != nil { + return nil, err + } + cc := NewRulerClient(conn) + newGrps, err := cc.Rules(ctx, nil) + if err != nil { + return nil, fmt.Errorf("unable to retrieve rules from other rulers, %v", err) + } + rgs = append(rgs, newGrps.Groups...) + } + + return rgs, nil +} + // Rules implements the rules service func (r *Ruler) Rules(ctx context.Context, in *RulesRequest) (*RulesResponse, error) { userID, err := user.ExtractOrgID(ctx) @@ -572,7 +571,7 @@ func (r *Ruler) Rules(ctx context.Context, in *RulesRequest) (*RulesResponse, er return nil, fmt.Errorf("no user id found in context") } - groupDescs, err := r.getRules(userID) + groupDescs, err := r.getLocalRules(userID) if err != nil { return nil, err } From 48fec7529ca50d90683f951fa7857be1fb9cc0e0 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 21 Jan 2020 19:28:36 -0500 Subject: [PATCH 07/29] add Rules test Signed-off-by: Jacob Lisi --- pkg/ruler/mock_store.go | 13 ++++++++++--- pkg/ruler/ruler.go | 10 +++++++++- pkg/ruler/ruler_test.go | 30 ++++++++++++++++++++++++++++++ pkg/ruler/rules/compat.go | 9 +++++++-- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/pkg/ruler/mock_store.go b/pkg/ruler/mock_store.go index 260d47b19ec..d4ffa326015 100644 --- a/pkg/ruler/mock_store.go +++ b/pkg/ruler/mock_store.go @@ -4,6 +4,7 @@ import ( "context" "strings" "sync" + "time" "github.com/cortexproject/cortex/pkg/ruler/rules" ) @@ -14,6 +15,7 @@ type mockRuleStore struct { } func newMockRuleStore() *mockRuleStore { + interval, _ := time.ParseDuration("1m") return &mockRuleStore{ rules: map[string]*rules.RuleGroupDesc{ "user1:group1": { @@ -22,9 +24,11 @@ func newMockRuleStore() *mockRuleStore { User: "user1", Rules: []*rules.RuleDesc{ { - Expr: "up", + Record: "UP_RULE", + Expr: "up", }, }, + Interval: &interval, }, "user2:group1": { Name: "group1", @@ -32,9 +36,12 @@ func newMockRuleStore() *mockRuleStore { User: "user2", Rules: []*rules.RuleDesc{ { - Expr: "up", + Record: "UP_RULE", + Expr: "up", + For: &interval, }, }, + Interval: &interval, }, }, } @@ -48,7 +55,7 @@ func (m *mockRuleStore) ListAllRuleGroups(ctx context.Context) (map[string]rules for id, rg := range m.rules { components := strings.Split(id, ":") - if len(components) != 3 { + if len(components) != 2 { continue } user := components[0] diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 36f3e7e5081..42692220adc 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -68,6 +68,9 @@ type Config struct { FlushCheckPeriod time.Duration EnableAPI bool `yaml:"enable_api"` + + // used to avoid duplicate registration in tests + registry prometheus.Registerer `yaml:"-"` } // RegisterFlags adds the flags required to config this to the given FlagSet @@ -435,9 +438,14 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag return nil, err } + reg := prometheus.DefaultRegisterer + if r.cfg.registry != nil { + reg = r.cfg.registry + } + // Wrap registerer with userID and cortex_ prefix - reg := prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, prometheus.DefaultRegisterer) reg = prometheus.WrapRegistererWithPrefix("cortex_", reg) + reg = prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, reg) opts := &promRules.ManagerOptions{ Appendable: tsdb, diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index 6ebb8434bc5..ffffc7890d9 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -1,8 +1,12 @@ package ruler import ( + "context" + "fmt" + "io/ioutil" "net/http" "net/http/httptest" + "os" "sync" "testing" "time" @@ -14,6 +18,7 @@ import ( "github.com/cortexproject/cortex/pkg/ring/kv/codec" "github.com/cortexproject/cortex/pkg/ring/kv/consul" "github.com/cortexproject/cortex/pkg/util/flagext" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/prometheus/notifier" "github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/promql" @@ -28,6 +33,7 @@ func defaultRulerConfig() Config { StoreConfig: RuleStoreConfig{ mock: newMockRuleStore(), }, + registry: prometheus.NewRegistry(), } flagext.DefaultValues(&cfg) flagext.DefaultValues(&cfg.Ring) @@ -73,6 +79,7 @@ func TestNotifierSendsUserIDHeader(t *testing.T) { cfg.AlertmanagerDiscovery = false r := newTestRuler(t, cfg) + defer r.Stop() n, err := r.getOrCreateNotifier("1") if err != nil { t.Fatal(err) @@ -90,3 +97,26 @@ func TestNotifierSendsUserIDHeader(t *testing.T) { wg.Wait() } + +func TestRuler_Rules(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "ruler-tests") + defer os.RemoveAll(dir) + + require.NoError(t, err) + + cfg := defaultRulerConfig() + cfg.RulePath = dir + + r := newTestRuler(t, cfg) + defer r.Stop() + + r.loadRules(context.Background()) + + ctx := user.InjectOrgID(context.Background(), "user1") + rls, err := r.Rules(ctx, &RulesRequest{}) + require.NoError(t, err) + require.Len(t, rls.Groups, 1) + for _, rule := range rls.GetGroups() { + fmt.Println(rule) + } +} diff --git a/pkg/ruler/rules/compat.go b/pkg/ruler/rules/compat.go index 2d9422ee20d..954193a2ac2 100644 --- a/pkg/ruler/rules/compat.go +++ b/pkg/ruler/rules/compat.go @@ -51,14 +51,19 @@ func FromProto(rg *RuleGroupDesc) rulefmt.RuleGroup { } for i, rl := range rg.GetRules() { - formattedRuleGroup.Rules[i] = rulefmt.Rule{ + newRule := rulefmt.Rule{ Record: rl.GetRecord(), Alert: rl.GetAlert(), Expr: rl.GetExpr(), - For: model.Duration(*rl.GetFor()), Labels: client.FromLabelAdaptersToLabels(rl.Labels).Map(), Annotations: client.FromLabelAdaptersToLabels(rl.Annotations).Map(), } + + if rl.GetFor() != nil { + newRule.For = model.Duration(*rl.GetFor()) + } + + formattedRuleGroup.Rules[i] = newRule } return formattedRuleGroup From 6f124cfea57a9f14866492851de1b4af49f08f62 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 21 Jan 2020 22:52:10 -0500 Subject: [PATCH 08/29] update docs Signed-off-by: Jacob Lisi --- docs/configuration/config-file-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index 382b633d396..0feead758c4 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -739,7 +739,7 @@ ring: # Enable the ruler api # CLI flag: -experimental.ruler.enable-api -[enableapi: | default = false] +[enable_api: | default = false] ``` ## `alertmanager_config` From 9f1423684f7be921a742728cd1f3d98108b06fb0 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 22 Jan 2020 14:30:33 -0500 Subject: [PATCH 09/29] explicitly pass registerer to the ruler Signed-off-by: Jacob Lisi --- pkg/cortex/modules.go | 2 +- pkg/ruler/ruler.go | 15 +++++---------- pkg/ruler/ruler_test.go | 3 +-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index 051756fc8a8..42fd718e1cd 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -415,7 +415,7 @@ func (t *Cortex) initRuler(cfg *Config) (err error) { cfg.Ruler.Ring.ListenPort = cfg.Server.GRPCListenPort queryable, engine := querier.New(cfg.Querier, t.distributor, t.store) - t.ruler, err = ruler.NewRuler(cfg.Ruler, engine, queryable, t.distributor) + t.ruler, err = ruler.NewRuler(cfg.Ruler, engine, queryable, t.distributor, prometheus.DefaultRegisterer) if err != nil { return } diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 42692220adc..b9c5f9a82dd 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -68,9 +68,6 @@ type Config struct { FlushCheckPeriod time.Duration EnableAPI bool `yaml:"enable_api"` - - // used to avoid duplicate registration in tests - registry prometheus.Registerer `yaml:"-"` } // RegisterFlags adds the flags required to config this to the given FlagSet @@ -126,10 +123,12 @@ type Ruler struct { done chan struct{} terminated chan struct{} + + registry prometheus.Registerer } // NewRuler creates a new ruler from a distributor and chunk store. -func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable, d *distributor.Distributor) (*Ruler, error) { +func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable, d *distributor.Distributor, reg prometheus.Registerer) (*Ruler, error) { ncfg, err := buildNotifierConfig(&cfg) if err != nil { return nil, err @@ -153,6 +152,7 @@ func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable userManagers: map[string]*promRules.Manager{}, done: make(chan struct{}), terminated: make(chan struct{}), + registry: reg, } // If sharding is enabled, create/join a ring to distribute tokens to @@ -438,13 +438,8 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag return nil, err } - reg := prometheus.DefaultRegisterer - if r.cfg.registry != nil { - reg = r.cfg.registry - } - // Wrap registerer with userID and cortex_ prefix - reg = prometheus.WrapRegistererWithPrefix("cortex_", reg) + reg := prometheus.WrapRegistererWithPrefix("cortex_", r.registry) reg = prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, reg) opts := &promRules.ManagerOptions{ diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index ffffc7890d9..5125dffee91 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -33,7 +33,6 @@ func defaultRulerConfig() Config { StoreConfig: RuleStoreConfig{ mock: newMockRuleStore(), }, - registry: prometheus.NewRegistry(), } flagext.DefaultValues(&cfg) flagext.DefaultValues(&cfg.Ring) @@ -55,7 +54,7 @@ func newTestRuler(t *testing.T, cfg Config) *Ruler { Timeout: 2 * time.Minute, }) queryable := querier.NewQueryable(nil, nil, nil, querier.Config{}) - ruler, err := NewRuler(cfg, engine, queryable, nil) + ruler, err := NewRuler(cfg, engine, queryable, nil, prometheus.NewRegistry()) if err != nil { t.Fatal(err) } From 3073c816be47053191b5a3d484cdd46df7b73b2a Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 22 Jan 2020 14:31:47 -0500 Subject: [PATCH 10/29] create respondError function Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 87 ++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index fafa0340ebd..9f311490919 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -6,13 +6,14 @@ import ( "net/http" "time" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/gorilla/mux" "github.com/prometheus/prometheus/pkg/labels" + "github.com/weaveworks/common/user" "github.com/cortexproject/cortex/pkg/ingester/client" "github.com/cortexproject/cortex/pkg/util" - "github.com/go-kit/kit/log/level" - "github.com/gorilla/mux" - "github.com/weaveworks/common/user" ) // RegisterRoutes registers the configs API HTTP routes with the provided Router. @@ -33,6 +34,19 @@ func (r *Ruler) RegisterRoutes(router *mux.Router) { } } +type errorType string + +const ( + errorNone errorType = "" + errorTimeout errorType = "timeout" + errorCanceled errorType = "canceled" + errorExec errorType = "execution" + errorBadData errorType = "bad_data" + errorInternal errorType = "internal" + errorUnavailable errorType = "unavailable" + errorNotFound errorType = "not_found" +) + // In order to reimplement the prometheus rules API, a large amount of code was copied over // This is required because the prometheus api implementation does not pass a context to // the rule retrieval function. @@ -42,7 +56,7 @@ func (r *Ruler) RegisterRoutes(router *mux.Router) { type response struct { Status string `json:"status"` Data interface{} `json:"data,omitempty"` - ErrorType string `json:"errorType,omitempty"` + ErrorType errorType `json:"errorType,omitempty"` Error string `json:"error,omitempty"` } @@ -103,12 +117,33 @@ type recordingRule struct { Type string `json:"type"` } +func respondError(logger log.Logger, w http.ResponseWriter, msg string, errType errorType) { + b, err := json.Marshal(&response{ + Status: "error", + ErrorType: errType, + Error: msg, + Data: nil, + }) + + if err != nil { + level.Error(logger).Log("msg", "error marshaling json response", "err", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusInternalServerError) + if n, err := w.Write(b); err != nil { + level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) + } + return +} + func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { logger := util.WithContext(req.Context(), util.Logger) userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - http.Error(w, err.Error(), http.StatusUnauthorized) + respondError(logger, w, "no valid org id found", errorInternal) return } @@ -116,23 +151,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - b, err := json.Marshal(&response{ - Status: "error", - ErrorType: "internal", - Error: err.Error(), - Data: nil, - }) - - if err != nil { - level.Error(logger).Log("msg", "error marshaling json response", "err", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.WriteHeader(http.StatusInternalServerError) - if n, err := w.Write(b); err != nil { - level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) - } + respondError(logger, w, err.Error(), errorInternal) return } @@ -190,6 +209,8 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) + respondError(logger, w, "unable to marshal the requested data", errorBadData) + return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) @@ -203,7 +224,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - http.Error(w, err.Error(), http.StatusUnauthorized) + respondError(logger, w, "no valid org id found", errorInternal) return } @@ -211,23 +232,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - b, err := json.Marshal(&response{ - Status: "error", - ErrorType: "internal", - Error: err.Error(), - Data: nil, - }) - - if err != nil { - level.Error(logger).Log("msg", "error marshaling json response", "err", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.WriteHeader(http.StatusInternalServerError) - if n, err := w.Write(b); err != nil { - level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) - } + respondError(logger, w, err.Error(), "internal") return } @@ -255,6 +260,8 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) + respondError(logger, w, "unable to marshal the requested data", errorBadData) + return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) From 79222b22967f5a59627cc6f35bda97a19a8af497 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 22 Jan 2020 14:41:33 -0500 Subject: [PATCH 11/29] remove unused return and err vars Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 9f311490919..259d4d66eea 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -37,14 +37,8 @@ func (r *Ruler) RegisterRoutes(router *mux.Router) { type errorType string const ( - errorNone errorType = "" - errorTimeout errorType = "timeout" - errorCanceled errorType = "canceled" - errorExec errorType = "execution" - errorBadData errorType = "bad_data" - errorInternal errorType = "internal" - errorUnavailable errorType = "unavailable" - errorNotFound errorType = "not_found" + errorBadData errorType = "bad_data" + errorInternal errorType = "internal" ) // In order to reimplement the prometheus rules API, a large amount of code was copied over @@ -135,7 +129,6 @@ func respondError(logger log.Logger, w http.ResponseWriter, msg string, errType if n, err := w.Write(b); err != nil { level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err) } - return } func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { From 912599cc4899999c61d11a9931cc8675d6a641de Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 22 Jan 2020 15:13:37 -0500 Subject: [PATCH 12/29] reorder registry wrapping Signed-off-by: Jacob Lisi --- pkg/ruler/ruler.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index b9c5f9a82dd..b22a76092f0 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -439,8 +439,8 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag } // Wrap registerer with userID and cortex_ prefix - reg := prometheus.WrapRegistererWithPrefix("cortex_", r.registry) - reg = prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, reg) + reg := prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, r.registry) + reg = prometheus.WrapRegistererWithPrefix("cortex_", reg) opts := &promRules.ManagerOptions{ Appendable: tsdb, From f5732e15ec63dbe8efc575238bf6cc7aaef00bec Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Fri, 24 Jan 2020 16:56:20 -0500 Subject: [PATCH 13/29] refactor based on pr suggestions Signed-off-by: Jacob Lisi --- pkg/cortex/modules.go | 7 +-- pkg/ruler/api.go | 10 ++-- pkg/ruler/mapper.go | 16 +++--- pkg/ruler/mock_store.go | 1 - pkg/ruler/ruler.go | 106 +++++++++++++++++++++------------------- pkg/ruler/ruler_test.go | 19 ++++--- 6 files changed, 85 insertions(+), 74 deletions(-) diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index 42fd718e1cd..1a182387e04 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -415,13 +415,14 @@ func (t *Cortex) initRuler(cfg *Config) (err error) { cfg.Ruler.Ring.ListenPort = cfg.Server.GRPCListenPort queryable, engine := querier.New(cfg.Querier, t.distributor, t.store) - t.ruler, err = ruler.NewRuler(cfg.Ruler, engine, queryable, t.distributor, prometheus.DefaultRegisterer) + t.ruler, err = ruler.NewRuler(cfg.Ruler, engine, queryable, t.distributor, prometheus.DefaultRegisterer, util.Logger) if err != nil { return } if cfg.Ruler.EnableAPI { - t.ruler.RegisterRoutes(t.server.HTTP) + subrouter := t.server.HTTP.PathPrefix(cfg.HTTPPrefix).Subrouter() + t.ruler.RegisterRoutes(subrouter) } t.server.HTTP.Handle("/ruler_ring", t.ruler) @@ -460,7 +461,7 @@ func (t *Cortex) initAlertmanager(cfg *Config) (err error) { // TODO this clashed with the queirer and the distributor, so we cannot // run them in the same process. - t.server.HTTP.PathPrefix("/api/prom").Handler(middleware.AuthenticateUser.Wrap(t.alertmanager)) + t.server.HTTP.PathPrefix(cfg.HTTPPrefix).Handler(middleware.AuthenticateUser.Wrap(t.alertmanager)) return } diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 259d4d66eea..93539f50c8c 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -18,16 +18,12 @@ import ( // RegisterRoutes registers the configs API HTTP routes with the provided Router. func (r *Ruler) RegisterRoutes(router *mux.Router) { - if r.store == nil { - level.Info(util.Logger).Log("msg", "ruler configured with store that does not support api") - return - } for _, route := range []struct { name, method, path string handler http.HandlerFunc }{ {"get_rules", "GET", "/api/prom/api/v1/rules", r.rules}, - {"get_alerts", "GET", "/api/prom/api/v1/rules", r.alerts}, + {"get_alerts", "GET", "/api/prom/api/v1/alerts", r.alerts}, } { level.Debug(util.Logger).Log("msg", "ruler: registering route", "name", route.name, "method", route.method, "path", route.path) router.Handle(route.path, route.handler).Methods(route.method).Name(route.name) @@ -148,7 +144,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { return } - groups := make([]*RuleGroup, len(rgs)) + groups := make([]*RuleGroup, 0, len(rgs)) for _, g := range rgs { grp := RuleGroup{ @@ -229,7 +225,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { return } - alerts := make([]*Alert, len(rgs)) + alerts := make([]*Alert, 0, len(rgs)) for _, g := range rgs { for _, rl := range g.Rules { diff --git a/pkg/ruler/mapper.go b/pkg/ruler/mapper.go index 3326d2180c1..36d1f60f4b3 100644 --- a/pkg/ruler/mapper.go +++ b/pkg/ruler/mapper.go @@ -4,7 +4,7 @@ import ( "crypto/md5" "sort" - "github.com/cortexproject/cortex/pkg/util" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/prometheus/prometheus/pkg/rulefmt" "github.com/spf13/afero" @@ -16,13 +16,15 @@ import ( type mapper struct { Path string // Path specifies the directory in which rule files will be mapped. - FS afero.Fs + FS afero.Fs + logger log.Logger } -func newMapper(path string) *mapper { +func newMapper(path string, logger log.Logger) *mapper { return &mapper{ - Path: path, - FS: afero.NewOsFs(), + Path: path, + FS: afero.NewOsFs(), + logger: logger, } } @@ -62,7 +64,7 @@ func (m *mapper) MapRules(user string, ruleConfigs map[string][]rulefmt.RuleGrou if ruleGroups == nil { err = m.FS.Remove(fullFileName) if err != nil { - level.Warn(util.Logger).Log("msg", "unable to remove rule file on disk", "file", fullFileName, "err", err) + level.Warn(m.logger).Log("msg", "unable to remove rule file on disk", "file", fullFileName, "err", err) } anyUpdated = true } @@ -98,7 +100,7 @@ func (m *mapper) writeRuleGroupsIfNewer(groups []rulefmt.RuleGroup, filename str } } - level.Info(util.Logger).Log("msg", "updating rule file", "file", filename) + level.Info(m.logger).Log("msg", "updating rule file", "file", filename) err = afero.WriteFile(m.FS, filename, d, 0777) if err != nil { return false, err diff --git a/pkg/ruler/mock_store.go b/pkg/ruler/mock_store.go index d4ffa326015..432adef7572 100644 --- a/pkg/ruler/mock_store.go +++ b/pkg/ruler/mock_store.go @@ -38,7 +38,6 @@ func newMockRuleStore() *mockRuleStore { { Record: "UP_RULE", Expr: "up", - For: &interval, }, }, Interval: &interval, diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index b22a76092f0..ea98c844628 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -17,6 +17,7 @@ import ( store "github.com/cortexproject/cortex/pkg/ruler/rules" "github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util/flagext" + "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" ot "github.com/opentracing/opentracing-go" "github.com/pkg/errors" @@ -125,10 +126,11 @@ type Ruler struct { terminated chan struct{} registry prometheus.Registerer + logger log.Logger } // NewRuler creates a new ruler from a distributor and chunk store. -func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable, d *distributor.Distributor, reg prometheus.Registerer) (*Ruler, error) { +func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable, d *distributor.Distributor, reg prometheus.Registerer, logger log.Logger) (*Ruler, error) { ncfg, err := buildNotifierConfig(&cfg) if err != nil { return nil, err @@ -148,11 +150,12 @@ func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable notifiers: map[string]*rulerNotifier{}, store: ruleStore, pusher: d, - mapper: newMapper(cfg.RulePath), + mapper: newMapper(cfg.RulePath, logger), userManagers: map[string]*promRules.Manager{}, done: make(chan struct{}), terminated: make(chan struct{}), registry: reg, + logger: logger, } // If sharding is enabled, create/join a ring to distribute tokens to @@ -173,7 +176,7 @@ func NewRuler(cfg Config, engine *promql.Engine, queryable promStorage.Queryable } go ruler.run() - level.Info(util.Logger).Log("msg", "ruler up and running") + level.Info(logger).Log("msg", "ruler up and running") return ruler, nil } @@ -191,27 +194,27 @@ func (r *Ruler) Stop() { r.notifiersMtx.Unlock() if r.cfg.EnableSharding { - level.Info(util.Logger).Log("msg", "attempting shutdown lifecycle") + level.Info(r.logger).Log("msg", "attempting shutdown lifecycle") r.lifecycler.Shutdown() - level.Info(util.Logger).Log("msg", "shutting down the ring") + level.Info(r.logger).Log("msg", "shutting down the ring") r.ring.Stop() } - level.Info(util.Logger).Log("msg", "stopping user managers") + level.Info(r.logger).Log("msg", "stopping user managers") wg := sync.WaitGroup{} r.userManagerMtx.Lock() for user, manager := range r.userManagers { - level.Debug(util.Logger).Log("msg", "shutting down user manager", "user", user) + level.Debug(r.logger).Log("msg", "shutting down user manager", "user", user) wg.Add(1) go func(manager *promRules.Manager, user string) { manager.Stop() wg.Done() - level.Debug(util.Logger).Log("msg", "user manager shut down", "user", user) + level.Debug(r.logger).Log("msg", "user manager shut down", "user", user) }(manager, user) } wg.Wait() r.userManagerMtx.Unlock() - level.Info(util.Logger).Log("msg", "all user managers stopped") + level.Info(r.logger).Log("msg", "all user managers stopped") } // sendAlerts implements a rules.NotifyFunc for a Notifier. @@ -287,15 +290,15 @@ func (r *Ruler) getOrCreateNotifier(userID string) (*notifier.Manager, error) { func (r *Ruler) ownsRule(hash uint32) (bool, error) { rlrs, err := r.ring.Get(hash, ring.Read, []ring.IngesterDesc{}) if err != nil { - level.Warn(util.Logger).Log("msg", "error reading ring to verify rule group ownership", "err", err) + level.Warn(r.logger).Log("msg", "error reading ring to verify rule group ownership", "err", err) ringCheckErrors.Inc() return false, err } if rlrs.Ingesters[0].Addr == r.lifecycler.Addr { - level.Debug(util.Logger).Log("msg", "rule group owned", "owner_addr", rlrs.Ingesters[0].Addr, "addr", r.lifecycler.Addr) + level.Debug(r.logger).Log("msg", "rule group owned", "owner_addr", rlrs.Ingesters[0].Addr, "addr", r.lifecycler.Addr) return true, nil } - level.Debug(util.Logger).Log("msg", "rule group not owned, address does not match", "owner_addr", rlrs.Ingesters[0].Addr, "addr", r.lifecycler.Addr) + level.Debug(r.logger).Log("msg", "rule group not owned, address does not match", "owner_addr", rlrs.Ingesters[0].Addr, "addr", r.lifecycler.Addr) return false, nil } @@ -318,7 +321,7 @@ func (r *Ruler) ServeHTTP(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) _, err := w.Write([]byte(unshardedPage)) if err != nil { - level.Error(util.Logger).Log("msg", "unable to serve status page", "err", err) + level.Error(r.logger).Log("msg", "unable to serve status page", "err", err) } } } @@ -345,7 +348,7 @@ func (r *Ruler) loadRules(ctx context.Context) { configs, err := r.store.ListAllRuleGroups(ctx) if err != nil { - level.Error(util.Logger).Log("msg", "unable to poll for rules", "err", err) + level.Error(r.logger).Log("msg", "unable to poll for rules", "err", err) return } @@ -362,13 +365,13 @@ func (r *Ruler) loadRules(ctx context.Context) { ringHasher.Reset() _, err = ringHasher.Write([]byte(id)) if err != nil { - level.Error(util.Logger).Log("msg", "failed to create group for user", "user", user, "namespace", g.Namespace, "group", g.Name, "err", err) + level.Error(r.logger).Log("msg", "failed to create group for user", "user", user, "namespace", g.Namespace, "group", g.Name, "err", err) continue } hash := ringHasher.Sum32() owned, err := r.ownsRule(hash) if err != nil { - level.Error(util.Logger).Log("msg", "unable to verify rule group ownership ownership, will retry on the next poll", "err", err) + level.Error(r.logger).Log("msg", "unable to verify rule group ownership ownership, will retry on the next poll", "err", err) return } if owned { @@ -379,36 +382,7 @@ func (r *Ruler) loadRules(ctx context.Context) { filteredGroups = cfg } - // Map the files to disk and return the file names to be passed to the users manager - update, files, err := r.mapper.MapRules(user, filteredGroups.Formatted()) - if err != nil { - level.Error(util.Logger).Log("msg", "unable to map rule files", "user", user, "err", err) - continue - } - - if update { - configUpdatesTotal.WithLabelValues(user).Inc() - r.userManagerMtx.Lock() - manager, exists := r.userManagers[user] - r.userManagerMtx.Unlock() - if !exists { - manager, err = r.newManager(ctx, user) - if err != nil { - level.Error(util.Logger).Log("msg", "unable to create rule manager", "user", user, "err", err) - continue - } - manager.Run() - - r.userManagerMtx.Lock() - r.userManagers[user] = manager - r.userManagerMtx.Unlock() - } - err = manager.Update(r.cfg.EvaluationInterval, files, nil) - if err != nil { - level.Error(util.Logger).Log("msg", "unable to create rule manager", "user", user, "err", err) - continue - } - } + r.syncManager(ctx, user, filteredGroups) } // Check for deleted users and remove them @@ -418,12 +392,46 @@ func (r *Ruler) loadRules(ctx context.Context) { if _, exists := configs[user]; !exists { go mngr.Stop() delete(r.userManagers, user) - level.Info(util.Logger).Log("msg", "deleting rule manager", "user", user) + level.Info(r.logger).Log("msg", "deleting rule manager", "user", user) } } } +// syncManager maps the rule files to disk, detects any changes and will create/update the +// the users Prometheus Rules Manager +func (r *Ruler) syncManager(ctx native_ctx.Context, user string, groups store.RuleGroupList) { + r.userManagerMtx.Lock() + defer r.userManagerMtx.Unlock() + + // Map the files to disk and return the file names to be passed to the users manager + update, files, err := r.mapper.MapRules(user, groups.Formatted()) + if err != nil { + level.Error(r.logger).Log("msg", "unable to map rule files", "user", user, "err", err) + return + } + + if update { + level.Info(r.logger).Log("msg", "updating rules", "user", "user") + configUpdatesTotal.WithLabelValues(user).Inc() + manager, exists := r.userManagers[user] + if !exists { + manager, err = r.newManager(ctx, user) + if err != nil { + level.Error(r.logger).Log("msg", "unable to create rule manager", "user", user, "err", err) + return + } + manager.Run() + r.userManagers[user] = manager + } + err = manager.Update(r.cfg.EvaluationInterval, files, nil) + if err != nil { + level.Error(r.logger).Log("msg", "unable to update rule manager", "user", user, "err", err) + return + } + } +} + // newManager creates a prometheus rule manager wrapped with a user id // configured storage, appendable, notifier, and instrumentation func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manager, error) { @@ -441,7 +449,7 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag // Wrap registerer with userID and cortex_ prefix reg := prometheus.WrapRegistererWith(prometheus.Labels{"user": userID}, r.registry) reg = prometheus.WrapRegistererWithPrefix("cortex_", reg) - + logger := log.With(r.logger, "user", userID) opts := &promRules.ManagerOptions{ Appendable: tsdb, TSDB: tsdb, @@ -449,7 +457,7 @@ func (r *Ruler) newManager(ctx context.Context, userID string) (*promRules.Manag Context: user.InjectOrgID(ctx, userID), ExternalURL: r.alertURL, NotifyFunc: sendAlerts(notifier, r.alertURL.String()), - Logger: util.Logger, + Logger: logger, Registerer: reg, } return promRules.NewManager(opts), nil diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index 5125dffee91..fcf73dac1eb 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -2,7 +2,7 @@ package ruler import ( "context" - "fmt" + "errors" "io/ioutil" "net/http" "net/http/httptest" @@ -11,9 +11,10 @@ import ( "testing" "time" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/stretchr/testify/require" - "github.com/cortexproject/cortex/pkg/querier" "github.com/cortexproject/cortex/pkg/ring" "github.com/cortexproject/cortex/pkg/ring/kv/codec" "github.com/cortexproject/cortex/pkg/ring/kv/consul" @@ -22,6 +23,7 @@ import ( "github.com/prometheus/prometheus/notifier" "github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/promql" + "github.com/prometheus/prometheus/storage" "github.com/stretchr/testify/assert" "github.com/weaveworks/common/user" ) @@ -53,8 +55,14 @@ func newTestRuler(t *testing.T, cfg Config) *Ruler { MaxConcurrent: 20, Timeout: 2 * time.Minute, }) - queryable := querier.NewQueryable(nil, nil, nil, querier.Config{}) - ruler, err := NewRuler(cfg, engine, queryable, nil, prometheus.NewRegistry()) + + noopQueryable := storage.QueryableFunc(func(ctx context.Context, mint, maxt int64) (storage.Querier, error) { + return nil, errors.New("not implemented") + }) + + l := log.NewLogfmtLogger(os.Stdout) + l = level.NewFilter(l, level.AllowInfo()) + ruler, err := NewRuler(cfg, engine, noopQueryable, nil, prometheus.NewRegistry(), l) if err != nil { t.Fatal(err) } @@ -115,7 +123,4 @@ func TestRuler_Rules(t *testing.T) { rls, err := r.Rules(ctx, &RulesRequest{}) require.NoError(t, err) require.Len(t, rls.Groups, 1) - for _, rule := range rls.GetGroups() { - fmt.Println(rule) - } } From 4c6ec75a47ac73e76739d1a84781711877faaf70 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 15:14:45 -0500 Subject: [PATCH 14/29] improve ruler tests for loading rules Signed-off-by: Jacob Lisi --- pkg/ruler/ruler.go | 6 ++- pkg/ruler/ruler_test.go | 24 +++++++++ .../{mock_store.go => store_mock_test.go} | 53 ++++++++----------- 3 files changed, 51 insertions(+), 32 deletions(-) rename pkg/ruler/{mock_store.go => store_mock_test.go} (54%) diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index ea98c844628..647eb8d2400 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -7,6 +7,8 @@ import ( "hash/fnv" "net/http" "net/url" + "path/filepath" + "strings" "sync" "time" @@ -484,11 +486,13 @@ func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { } r.userManagerMtx.Unlock() + prefix := filepath.Join(r.cfg.RulePath, userID) + "/" + for _, group := range groups { interval := group.Interval() groupDesc := &rules.RuleGroupDesc{ Name: group.Name(), - Namespace: group.File(), + Namespace: strings.TrimPrefix(group.File(), prefix), Interval: &interval, User: userID, } diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index fcf73dac1eb..879e215ad62 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -18,6 +18,7 @@ import ( "github.com/cortexproject/cortex/pkg/ring" "github.com/cortexproject/cortex/pkg/ring/kv/codec" "github.com/cortexproject/cortex/pkg/ring/kv/consul" + "github.com/cortexproject/cortex/pkg/ruler/rules" "github.com/cortexproject/cortex/pkg/util/flagext" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/prometheus/notifier" @@ -119,8 +120,31 @@ func TestRuler_Rules(t *testing.T) { r.loadRules(context.Background()) + // test user1 ctx := user.InjectOrgID(context.Background(), "user1") rls, err := r.Rules(ctx, &RulesRequest{}) require.NoError(t, err) require.Len(t, rls.Groups, 1) + rg := rls.Groups[0] + expectedRg := mockRules["user1"][0] + compareRuleGroupDescs(t, rg, expectedRg) + + // test user2 + ctx = user.InjectOrgID(context.Background(), "user2") + rls, err = r.Rules(ctx, &RulesRequest{}) + require.NoError(t, err) + require.Len(t, rls.Groups, 1) + rg = rls.Groups[0] + expectedRg = mockRules["user2"][0] + compareRuleGroupDescs(t, rg, expectedRg) +} + +func compareRuleGroupDescs(t *testing.T, expected, got *rules.RuleGroupDesc) { + require.Equal(t, expected.Name, got.Name) + require.Equal(t, expected.Namespace, got.Namespace) + require.Len(t, got.Rules, len(expected.Rules)) + for i := range got.Rules { + require.Equal(t, expected.Rules[i].Record, got.Rules[i].Record) + require.Equal(t, expected.Rules[i].Alert, got.Rules[i].Alert) + } } diff --git a/pkg/ruler/mock_store.go b/pkg/ruler/store_mock_test.go similarity index 54% rename from pkg/ruler/mock_store.go rename to pkg/ruler/store_mock_test.go index 432adef7572..02929ed0709 100644 --- a/pkg/ruler/mock_store.go +++ b/pkg/ruler/store_mock_test.go @@ -2,40 +2,43 @@ package ruler import ( "context" - "strings" - "sync" "time" "github.com/cortexproject/cortex/pkg/ruler/rules" ) type mockRuleStore struct { - sync.Mutex - rules map[string]*rules.RuleGroupDesc + rules map[string]rules.RuleGroupList } -func newMockRuleStore() *mockRuleStore { - interval, _ := time.ParseDuration("1m") - return &mockRuleStore{ - rules: map[string]*rules.RuleGroupDesc{ - "user1:group1": { +var ( + interval, _ = time.ParseDuration("1m") + mockRules = map[string]rules.RuleGroupList{ + "user1": rules.RuleGroupList{ + &rules.RuleGroupDesc{ Name: "group1", Namespace: "namespace1", User: "user1", Rules: []*rules.RuleDesc{ - { + &rules.RuleDesc{ Record: "UP_RULE", Expr: "up", }, + &rules.RuleDesc{ + Alert: "UP_ALERT", + Expr: "up < 1", + }, }, Interval: &interval, }, - "user2:group1": { + }, + "user2": rules.RuleGroupList{ + &rules.RuleGroupDesc{ Name: "group1", Namespace: "namespace1", User: "user2", Rules: []*rules.RuleDesc{ - { + &rules.RuleDesc{ Record: "UP_RULE", Expr: "up", }, @@ -44,26 +47,14 @@ func newMockRuleStore() *mockRuleStore { }, }, } -} - -func (m *mockRuleStore) ListAllRuleGroups(ctx context.Context) (map[string]rules.RuleGroupList, error) { - m.Lock() - defer m.Unlock() - - userGroupMap := map[string]rules.RuleGroupList{} - - for id, rg := range m.rules { - components := strings.Split(id, ":") - if len(components) != 2 { - continue - } - user := components[0] +) - if _, exists := userGroupMap[user]; !exists { - userGroupMap[user] = rules.RuleGroupList{} - } - userGroupMap[user] = append(userGroupMap[user], rg) +func newMockRuleStore() *mockRuleStore { + return &mockRuleStore{ + rules: mockRules, } +} - return userGroupMap, nil +func (m *mockRuleStore) ListAllRuleGroups(ctx context.Context) (map[string]rules.RuleGroupList, error) { + return m.rules, nil } From 60e8d844bf0dc7fe8348b1c5b5cd70f88915fd6e Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 15:21:57 -0500 Subject: [PATCH 15/29] add logger to mapper tests Signed-off-by: Jacob Lisi --- pkg/ruler/mapper_test.go | 21 +++++++++++++++------ pkg/ruler/storage.go | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pkg/ruler/mapper_test.go b/pkg/ruler/mapper_test.go index 3a1efc790a2..9c3a19cd6fc 100644 --- a/pkg/ruler/mapper_test.go +++ b/pkg/ruler/mapper_test.go @@ -1,12 +1,14 @@ package ruler import ( + "os" "testing" - "github.com/stretchr/testify/require" - + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/prometheus/prometheus/pkg/rulefmt" "github.com/spf13/afero" + "github.com/stretchr/testify/require" ) var ( @@ -92,9 +94,12 @@ var ( ) func Test_mapper_MapRules(t *testing.T) { + l := log.NewLogfmtLogger(os.Stdout) + l = level.NewFilter(l, level.AllowInfo()) m := &mapper{ - Path: "/rules", - FS: afero.NewMemMapFs(), + Path: "/rules", + FS: afero.NewMemMapFs(), + logger: l, } t.Run("basic rulegroup", func(t *testing.T) { @@ -238,9 +243,13 @@ var ( ) func Test_mapper_MapRulesMultipleFiles(t *testing.T) { + l := log.NewLogfmtLogger(os.Stdout) + l = level.NewFilter(l, level.AllowInfo()) + m := &mapper{ - Path: "/rules", - FS: afero.NewMemMapFs(), + Path: "/rules", + FS: afero.NewMemMapFs(), + logger: l, } t.Run("basic rulegroup", func(t *testing.T) { diff --git a/pkg/ruler/storage.go b/pkg/ruler/storage.go index 81ed2c75b5f..536a9989342 100644 --- a/pkg/ruler/storage.go +++ b/pkg/ruler/storage.go @@ -13,7 +13,7 @@ type RuleStoreConfig struct { Type string `yaml:"type"` ConfigDB client.Config - mock *mockRuleStore + mock rules.RuleStore } // RegisterFlags registers flags. From 80b28b29a52d13611ab30630ceda7d487973e59b Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:13:50 -0500 Subject: [PATCH 16/29] add tests for ruler api calls Signed-off-by: Jacob Lisi --- pkg/ruler/api_test.go | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 pkg/ruler/api_test.go diff --git a/pkg/ruler/api_test.go b/pkg/ruler/api_test.go new file mode 100644 index 00000000000..bdb82361635 --- /dev/null +++ b/pkg/ruler/api_test.go @@ -0,0 +1,101 @@ +package ruler + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/weaveworks/common/user" +) + +func TestRuler_rules(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "ruler-tests") + defer os.RemoveAll(dir) + + require.NoError(t, err) + cfg := defaultRulerConfig() + cfg.RulePath = dir + + r := newTestRuler(t, cfg) + defer r.Stop() + + req := httptest.NewRequest("GET", "https://localhost:8080/api/prom/api/v1/rules", nil) + req.Header.Add(user.OrgIDHeaderName, "user1") + w := httptest.NewRecorder() + r.rules(w, req) + + resp := w.Result() + body, _ := ioutil.ReadAll(resp.Body) + responseJSON := response{} + json.Unmarshal(body, &responseJSON) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, responseJSON.Status, "success") + + expectedResponse, _ := json.Marshal(response{ + Status: "success", + Data: &RuleDiscovery{ + RuleGroups: []*RuleGroup{ + &RuleGroup{ + Name: "group1", + File: "namespace1", + Rules: []rule{ + &recordingRule{ + Name: "UP_RULE", + Query: "up", + Health: "unknown", + Type: "recording", + }, + &alertingRule{ + Name: "UP_ALERT", + Query: "up < 1", + State: "inactive", + Health: "unknown", + Type: "alerting", + Alerts: []*Alert{}, + }, + }, + Interval: 60, + }, + }, + }, + }) + + require.Equal(t, string(expectedResponse), string(body)) +} + +func TestRuler_alerts(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "ruler-tests") + defer os.RemoveAll(dir) + + require.NoError(t, err) + cfg := defaultRulerConfig() + cfg.RulePath = dir + + r := newTestRuler(t, cfg) + defer r.Stop() + + req := httptest.NewRequest("GET", "https://localhost:8080/api/prom/api/v1/alerts", nil) + req.Header.Add(user.OrgIDHeaderName, "user1") + w := httptest.NewRecorder() + r.alerts(w, req) + + resp := w.Result() + body, _ := ioutil.ReadAll(resp.Body) + responseJSON := response{} + json.Unmarshal(body, &responseJSON) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, responseJSON.Status, "success") + + expectedResponse, _ := json.Marshal(response{ + Status: "success", + Data: &AlertDiscovery{ + Alerts: []*Alert{}, + }, + }) + + require.Equal(t, string(expectedResponse), string(body)) +} From 79e09255f4f22c97bc37854d62583857113a0313 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:24:21 -0500 Subject: [PATCH 17/29] ensure all test rulers load rules before returning Signed-off-by: Jacob Lisi --- pkg/ruler/api_test.go | 17 +++++++++++++---- pkg/ruler/ruler_test.go | 6 ++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/ruler/api_test.go b/pkg/ruler/api_test.go index bdb82361635..d676849aee7 100644 --- a/pkg/ruler/api_test.go +++ b/pkg/ruler/api_test.go @@ -15,8 +15,8 @@ import ( func TestRuler_rules(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "ruler-tests") defer os.RemoveAll(dir) - require.NoError(t, err) + cfg := defaultRulerConfig() cfg.RulePath = dir @@ -30,11 +30,15 @@ func TestRuler_rules(t *testing.T) { resp := w.Result() body, _ := ioutil.ReadAll(resp.Body) + + // Check status code and status response responseJSON := response{} - json.Unmarshal(body, &responseJSON) + err = json.Unmarshal(body, &responseJSON) + require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) require.Equal(t, responseJSON.Status, "success") + // Testing the running rules for user1 in the mock store expectedResponse, _ := json.Marshal(response{ Status: "success", Data: &RuleDiscovery{ @@ -70,8 +74,8 @@ func TestRuler_rules(t *testing.T) { func TestRuler_alerts(t *testing.T) { dir, err := ioutil.TempDir("/tmp", "ruler-tests") defer os.RemoveAll(dir) - require.NoError(t, err) + cfg := defaultRulerConfig() cfg.RulePath = dir @@ -85,11 +89,16 @@ func TestRuler_alerts(t *testing.T) { resp := w.Result() body, _ := ioutil.ReadAll(resp.Body) + + // Check status code and status response responseJSON := response{} - json.Unmarshal(body, &responseJSON) + err = json.Unmarshal(body, &responseJSON) + require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) require.Equal(t, responseJSON.Status, "success") + // Currently there is not an easy way to mock firing alerts. The empty + // response case is tested instead. expectedResponse, _ := json.Marshal(response{ Status: "success", Data: &AlertDiscovery{ diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index 879e215ad62..f213b6492c4 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -67,6 +67,10 @@ func newTestRuler(t *testing.T, cfg Config) *Ruler { if err != nil { t.Fatal(err) } + + // Ensure all rules are loaded before usage + ruler.loadRules(context.Background()) + return ruler } @@ -118,8 +122,6 @@ func TestRuler_Rules(t *testing.T) { r := newTestRuler(t, cfg) defer r.Stop() - r.loadRules(context.Background()) - // test user1 ctx := user.InjectOrgID(context.Background(), "user1") rls, err := r.Rules(ctx, &RulesRequest{}) From 3eb742586b39b6841654afb40e70baec08556fc5 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:24:53 -0500 Subject: [PATCH 18/29] format api_test file Signed-off-by: Jacob Lisi --- pkg/ruler/api_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ruler/api_test.go b/pkg/ruler/api_test.go index d676849aee7..e2448e5d12c 100644 --- a/pkg/ruler/api_test.go +++ b/pkg/ruler/api_test.go @@ -43,7 +43,7 @@ func TestRuler_rules(t *testing.T) { Status: "success", Data: &RuleDiscovery{ RuleGroups: []*RuleGroup{ - &RuleGroup{ + { Name: "group1", File: "namespace1", Rules: []rule{ From 43baec12a97fd081542b1d7d2203049acd3e4910 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:28:59 -0500 Subject: [PATCH 19/29] go format Signed-off-by: Jacob Lisi --- pkg/ruler/store_mock_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/ruler/store_mock_test.go b/pkg/ruler/store_mock_test.go index 02929ed0709..3b0dae8893e 100644 --- a/pkg/ruler/store_mock_test.go +++ b/pkg/ruler/store_mock_test.go @@ -14,17 +14,17 @@ type mockRuleStore struct { var ( interval, _ = time.ParseDuration("1m") mockRules = map[string]rules.RuleGroupList{ - "user1": rules.RuleGroupList{ + "user1": { &rules.RuleGroupDesc{ Name: "group1", Namespace: "namespace1", User: "user1", Rules: []*rules.RuleDesc{ - &rules.RuleDesc{ + { Record: "UP_RULE", Expr: "up", }, - &rules.RuleDesc{ + { Alert: "UP_ALERT", Expr: "up < 1", }, @@ -32,13 +32,13 @@ var ( Interval: &interval, }, }, - "user2": rules.RuleGroupList{ + "user2": { &rules.RuleGroupDesc{ Name: "group1", Namespace: "namespace1", User: "user2", Rules: []*rules.RuleDesc{ - &rules.RuleDesc{ + { Record: "UP_RULE", Expr: "up", }, From 31b624c399eb1eca0705f5edb9f094fa8a3bcf3e Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:30:08 -0500 Subject: [PATCH 20/29] clean mapper_test file Signed-off-by: Jacob Lisi --- pkg/ruler/mapper_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/ruler/mapper_test.go b/pkg/ruler/mapper_test.go index 9c3a19cd6fc..31a972e969c 100644 --- a/pkg/ruler/mapper_test.go +++ b/pkg/ruler/mapper_test.go @@ -245,7 +245,6 @@ var ( func Test_mapper_MapRulesMultipleFiles(t *testing.T) { l := log.NewLogfmtLogger(os.Stdout) l = level.NewFilter(l, level.AllowInfo()) - m := &mapper{ Path: "/rules", FS: afero.NewMemMapFs(), From 17549495f985ee3b3bf0c83eb1c2d528a22797b9 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:34:26 -0500 Subject: [PATCH 21/29] add api documentation Signed-off-by: Jacob Lisi --- docs/apis.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/apis.md b/docs/apis.md index 476fd70ddc4..59fb6305751 100644 --- a/docs/apis.md +++ b/docs/apis.md @@ -17,6 +17,9 @@ APIs. The encoding is Protobuf over http. Read is on `/api/prom/read` and write is on `/api/prom/push`. +## Alerts & Rules API + +Cortex supports the Prometheus' [alerts](https://prometheus.io/docs/prometheus/latest/querying/api/#alerts) and [rules](https://prometheus.io/docs/prometheus/latest/querying/api/#rules) api endpoints. This is supported in the Ruler service and can be enabled using the `experimental.ruler.enable-api` flag. ## Configs API From c1683c36d6687b0ac54030d3e640a5752312ee2e Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Tue, 28 Jan 2020 16:36:37 -0500 Subject: [PATCH 22/29] fix alert array instantiation Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 93539f50c8c..f1adbc2cbe8 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -156,7 +156,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { for i, rl := range g.Rules { if g.Rules[i].Alert != "" { - alerts := make([]*Alert, len(rl.Alerts)) + alerts := make([]*Alert, 0, len(rl.Alerts)) for _, a := range rl.Alerts { alerts = append(alerts, &Alert{ Labels: client.FromLabelAdaptersToLabels(a.Labels), @@ -225,7 +225,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { return } - alerts := make([]*Alert, 0, len(rgs)) + alerts := []*Alert{} for _, g := range rgs { for _, rl := range g.Rules { From 1d34e66db402492227acdcc4923698d813241ed7 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 29 Jan 2020 16:41:47 -0500 Subject: [PATCH 23/29] refactor according to changes and comments on PR Signed-off-by: Jacob Lisi --- docs/apis.md | 4 ++++ pkg/cortex/modules.go | 4 ++-- pkg/ruler/api.go | 46 ++++++++++++++++++------------------------- pkg/ruler/ruler.go | 17 ++++++++-------- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/docs/apis.md b/docs/apis.md index 59fb6305751..ba38f8b0e7c 100644 --- a/docs/apis.md +++ b/docs/apis.md @@ -21,6 +21,10 @@ Read is on `/api/prom/read` and write is on `/api/prom/push`. Cortex supports the Prometheus' [alerts](https://prometheus.io/docs/prometheus/latest/querying/api/#alerts) and [rules](https://prometheus.io/docs/prometheus/latest/querying/api/#rules) api endpoints. This is supported in the Ruler service and can be enabled using the `experimental.ruler.enable-api` flag. +`GET /api/prom/api/v1/rules` - List of alerting and recording rules that are currently loaded + +`GET /api/prom/api/v1/alerts` - List of all active alerts + ## Configs API The configs service provides an API-driven multi-tenant approach to handling various configuration files for prometheus. The service hosts an API where users can read and write Prometheus rule files, Alertmanager configuration files, and Alertmanager templates to a database. diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index 1a182387e04..dd91a6c32b6 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -417,7 +417,7 @@ func (t *Cortex) initRuler(cfg *Config) (err error) { t.ruler, err = ruler.NewRuler(cfg.Ruler, engine, queryable, t.distributor, prometheus.DefaultRegisterer, util.Logger) if err != nil { - return + return err } if cfg.Ruler.EnableAPI { @@ -461,7 +461,7 @@ func (t *Cortex) initAlertmanager(cfg *Config) (err error) { // TODO this clashed with the queirer and the distributor, so we cannot // run them in the same process. - t.server.HTTP.PathPrefix(cfg.HTTPPrefix).Handler(middleware.AuthenticateUser.Wrap(t.alertmanager)) + t.server.HTTP.PathPrefix("/api/prom").Handler(middleware.AuthenticateUser.Wrap(t.alertmanager)) return } diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index f1adbc2cbe8..93de5074886 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -9,6 +9,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/gorilla/mux" + v1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/prometheus/pkg/labels" "github.com/weaveworks/common/user" @@ -16,27 +17,20 @@ import ( "github.com/cortexproject/cortex/pkg/util" ) -// RegisterRoutes registers the configs API HTTP routes with the provided Router. +// RegisterRoutes registers the ruler API HTTP routes with the provided Router. func (r *Ruler) RegisterRoutes(router *mux.Router) { for _, route := range []struct { name, method, path string handler http.HandlerFunc }{ - {"get_rules", "GET", "/api/prom/api/v1/rules", r.rules}, - {"get_alerts", "GET", "/api/prom/api/v1/alerts", r.alerts}, + {"get_rules", "GET", "/api/v1/rules", r.rules}, + {"get_alerts", "GET", "/api/v1/alerts", r.alerts}, } { level.Debug(util.Logger).Log("msg", "ruler: registering route", "name", route.name, "method", route.method, "path", route.path) router.Handle(route.path, route.handler).Methods(route.method).Name(route.name) } } -type errorType string - -const ( - errorBadData errorType = "bad_data" - errorInternal errorType = "internal" -) - // In order to reimplement the prometheus rules API, a large amount of code was copied over // This is required because the prometheus api implementation does not pass a context to // the rule retrieval function. @@ -44,10 +38,10 @@ const ( // https://github.com/prometheus/prometheus/pull/4999 type response struct { - Status string `json:"status"` - Data interface{} `json:"data,omitempty"` - ErrorType errorType `json:"errorType,omitempty"` - Error string `json:"error,omitempty"` + Status string `json:"status"` + Data interface{} `json:"data,omitempty"` + ErrorType v1.ErrorType `json:"errorType,omitempty"` + Error string `json:"error,omitempty"` } // AlertDiscovery has info for all active alerts. @@ -93,8 +87,7 @@ type alertingRule struct { Alerts []*Alert `json:"alerts"` Health string `json:"health"` LastError string `json:"lastError,omitempty"` - // Type of an alertingRule is always "alerting". - Type string `json:"type"` + Type v1.RuleType `json:"type"` } type recordingRule struct { @@ -103,11 +96,10 @@ type recordingRule struct { Labels labels.Labels `json:"labels,omitempty"` Health string `json:"health"` LastError string `json:"lastError,omitempty"` - // Type of a recordingRule is always "recording". - Type string `json:"type"` + Type v1.RuleType `json:"type"` } -func respondError(logger log.Logger, w http.ResponseWriter, msg string, errType errorType) { +func respondError(logger log.Logger, w http.ResponseWriter, msg string, errType v1.ErrorType) { b, err := json.Marshal(&response{ Status: "error", ErrorType: errType, @@ -132,7 +124,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - respondError(logger, w, "no valid org id found", errorInternal) + respondError(logger, w, "no valid org id found", v1.ErrServer) return } @@ -140,7 +132,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - respondError(logger, w, err.Error(), errorInternal) + respondError(logger, w, err.Error(), v1.ErrServer) return } @@ -176,7 +168,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { Alerts: alerts, Health: rl.GetHealth(), LastError: rl.GetLastError(), - Type: "alerting", + Type: v1.RuleTypeAlerting, } } else { grp.Rules[i] = recordingRule{ @@ -185,7 +177,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { Labels: client.FromLabelAdaptersToLabels(rl.Labels), Health: rl.GetHealth(), LastError: rl.GetLastError(), - Type: "recording", + Type: v1.RuleTypeRecording, } } } @@ -198,7 +190,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) - respondError(logger, w, "unable to marshal the requested data", errorBadData) + respondError(logger, w, "unable to marshal the requested data", v1.ErrServer) return } w.Header().Set("Content-Type", "application/json") @@ -213,7 +205,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - respondError(logger, w, "no valid org id found", errorInternal) + respondError(logger, w, "no valid org id found", v1.ErrServer) return } @@ -221,7 +213,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - respondError(logger, w, err.Error(), "internal") + respondError(logger, w, err.Error(), v1.ErrServer) return } @@ -249,7 +241,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) - respondError(logger, w, "unable to marshal the requested data", errorBadData) + respondError(logger, w, "unable to marshal the requested data", v1.ErrServer) return } w.Header().Set("Content-Type", "application/json") diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 647eb8d2400..b4e0b024e8b 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -401,12 +401,15 @@ func (r *Ruler) loadRules(ctx context.Context) { } // syncManager maps the rule files to disk, detects any changes and will create/update the -// the users Prometheus Rules Manager +// the users Prometheus Rules Manager. func (r *Ruler) syncManager(ctx native_ctx.Context, user string, groups store.RuleGroupList) { + // A lock is taken to ensure if syncManager is called concurrently, that each call + // returns after the call map files and check for updates r.userManagerMtx.Lock() defer r.userManagerMtx.Unlock() - // Map the files to disk and return the file names to be passed to the users manager + // Map the files to disk and return the file names to be passed to the users manager if they + // have been updated update, files, err := r.mapper.MapRules(user, groups.Formatted()) if err != nil { level.Error(r.logger).Log("msg", "unable to map rule files", "user", user, "err", err) @@ -414,7 +417,7 @@ func (r *Ruler) syncManager(ctx native_ctx.Context, user string, groups store.Ru } if update { - level.Info(r.logger).Log("msg", "updating rules", "user", "user") + level.Debug(r.logger).Log("msg", "updating rules", "user", "user") configUpdatesTotal.WithLabelValues(user).Inc() manager, exists := r.userManagers[user] if !exists { @@ -428,7 +431,7 @@ func (r *Ruler) syncManager(ctx native_ctx.Context, user string, groups store.Ru } err = manager.Update(r.cfg.EvaluationInterval, files, nil) if err != nil { - level.Error(r.logger).Log("msg", "unable to update rule manager", "user", user, "err", err) + level.Error(r.logger).Log("dsg", "unable to update rule manager", "user", user, "err", err) return } } @@ -476,16 +479,14 @@ func (r *Ruler) GetRules(ctx context.Context, userID string) ([]*rules.RuleGroup } func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { - groupDescs := []*rules.RuleGroupDesc{} - var groups []*promRules.Group r.userManagerMtx.Lock() - mngr, exists := r.userManagers[userID] - if exists { + if mngr, exists := r.userManagers[userID]; exists { groups = mngr.RuleGroups() } r.userManagerMtx.Unlock() + groupDescs := make([]*rules.RuleGroupDesc, 0, len(groups)) prefix := filepath.Join(r.cfg.RulePath, userID) + "/" for _, group := range groups { From b00ec4b48186e6e4e964bf50f408e63e68f1b111 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 29 Jan 2020 16:51:56 -0500 Subject: [PATCH 24/29] make all time related fields nonnullable for rules protos Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 4 +- pkg/ruler/ruler.go | 19 +- pkg/ruler/rules/compat.go | 11 +- pkg/ruler/rules/rules.pb.go | 451 ++++++++++++++--------------------- pkg/ruler/rules/rules.proto | 24 +- pkg/ruler/store_mock_test.go | 4 +- 6 files changed, 217 insertions(+), 296 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 93de5074886..60a5bc29a70 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -154,7 +154,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { Labels: client.FromLabelAdaptersToLabels(a.Labels), Annotations: client.FromLabelAdaptersToLabels(a.Annotations), State: a.GetState(), - ActiveAt: a.ActiveAt, + ActiveAt: &a.ActiveAt, Value: fmt.Sprintf("%f", a.Value), }) } @@ -227,7 +227,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { Labels: client.FromLabelAdaptersToLabels(a.Labels), Annotations: client.FromLabelAdaptersToLabels(a.Annotations), State: a.GetState(), - ActiveAt: a.ActiveAt, + ActiveAt: &a.ActiveAt, Value: fmt.Sprintf("%f", a.Value), }) } diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index b4e0b024e8b..42471aed96b 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -494,7 +494,7 @@ func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { groupDesc := &rules.RuleGroupDesc{ Name: group.Name(), Namespace: strings.TrimPrefix(group.File(), prefix), - Interval: &interval, + Interval: interval, User: userID, } for _, r := range group.Rules() { @@ -506,20 +506,19 @@ func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { var ruleDesc *rules.RuleDesc switch rule := r.(type) { case *promRules.AlertingRule: - dur := rule.Duration() rule.ActiveAlerts() - alerts := []*rules.Alert{} + alerts := []*rules.AlertDesc{} for _, a := range rule.ActiveAlerts() { - alerts = append(alerts, &rules.Alert{ + alerts = append(alerts, &rules.AlertDesc{ State: a.State.String(), Labels: client.FromLabelsToLabelAdapters(a.Labels), Annotations: client.FromLabelsToLabelAdapters(a.Annotations), Value: a.Value, - ActiveAt: &a.ActiveAt, - FiredAt: &a.FiredAt, - ResolvedAt: &a.ResolvedAt, - LastSentAt: &a.LastSentAt, - ValidUntil: &a.ValidUntil, + ActiveAt: a.ActiveAt, + FiredAt: a.FiredAt, + ResolvedAt: a.ResolvedAt, + LastSentAt: a.LastSentAt, + ValidUntil: a.ValidUntil, }) } ruleDesc = &rules.RuleDesc{ @@ -527,7 +526,7 @@ func (r *Ruler) getLocalRules(userID string) ([]*rules.RuleGroupDesc, error) { Alert: rule.Name(), Alerts: alerts, Expr: rule.Query().String(), - For: &dur, + For: rule.Duration(), Labels: client.FromLabelsToLabelAdapters(rule.Labels()), Annotations: client.FromLabelsToLabelAdapters(rule.Annotations()), Health: string(rule.Health()), diff --git a/pkg/ruler/rules/compat.go b/pkg/ruler/rules/compat.go index 954193a2ac2..4561ccedf3d 100644 --- a/pkg/ruler/rules/compat.go +++ b/pkg/ruler/rules/compat.go @@ -16,7 +16,7 @@ func ToProto(user string, namespace string, rl rulefmt.RuleGroup) *RuleGroupDesc rg := RuleGroupDesc{ Name: rl.Name, Namespace: namespace, - Interval: &dur, + Interval: dur, Rules: formattedRuleToProto(rl.Rules), User: user, } @@ -33,7 +33,7 @@ func formattedRuleToProto(rls []rulefmt.Rule) []*RuleDesc { Record: rls[i].Record, Alert: rls[i].Alert, - For: &f, + For: f, Labels: client.FromLabelsToLabelAdapters(labels.FromMap(rls[i].Labels)), Annotations: client.FromLabelsToLabelAdapters(labels.FromMap(rls[i].Annotations)), } @@ -46,7 +46,7 @@ func formattedRuleToProto(rls []rulefmt.Rule) []*RuleDesc { func FromProto(rg *RuleGroupDesc) rulefmt.RuleGroup { formattedRuleGroup := rulefmt.RuleGroup{ Name: rg.GetName(), - Interval: model.Duration(*rg.Interval), + Interval: model.Duration(rg.Interval), Rules: make([]rulefmt.Rule, len(rg.GetRules())), } @@ -57,10 +57,7 @@ func FromProto(rg *RuleGroupDesc) rulefmt.RuleGroup { Expr: rl.GetExpr(), Labels: client.FromLabelAdaptersToLabels(rl.Labels).Map(), Annotations: client.FromLabelAdaptersToLabels(rl.Annotations).Map(), - } - - if rl.GetFor() != nil { - newRule.For = model.Duration(*rl.GetFor()) + For: model.Duration(rl.GetFor()), } formattedRuleGroup.Rules[i] = newRule diff --git a/pkg/ruler/rules/rules.pb.go b/pkg/ruler/rules/rules.pb.go index a21bf3abb79..b0535365200 100644 --- a/pkg/ruler/rules/rules.pb.go +++ b/pkg/ruler/rules/rules.pb.go @@ -34,12 +34,12 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package // RuleGroupDesc is a proto representation of a cortex rule group type RuleGroupDesc struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` - Interval *time.Duration `protobuf:"bytes,3,opt,name=interval,proto3,stdduration" json:"interval,omitempty"` - Rules []*RuleDesc `protobuf:"bytes,4,rep,name=rules,proto3" json:"rules,omitempty"` - Deleted bool `protobuf:"varint,5,opt,name=deleted,proto3" json:"deleted,omitempty"` - User string `protobuf:"bytes,6,opt,name=user,proto3" json:"user,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + Interval time.Duration `protobuf:"bytes,3,opt,name=interval,proto3,stdduration" json:"interval"` + Rules []*RuleDesc `protobuf:"bytes,4,rep,name=rules,proto3" json:"rules,omitempty"` + Deleted bool `protobuf:"varint,5,opt,name=deleted,proto3" json:"deleted,omitempty"` + User string `protobuf:"bytes,6,opt,name=user,proto3" json:"user,omitempty"` } func (m *RuleGroupDesc) Reset() { *m = RuleGroupDesc{} } @@ -88,11 +88,11 @@ func (m *RuleGroupDesc) GetNamespace() string { return "" } -func (m *RuleGroupDesc) GetInterval() *time.Duration { +func (m *RuleGroupDesc) GetInterval() time.Duration { if m != nil { return m.Interval } - return nil + return 0 } func (m *RuleGroupDesc) GetRules() []*RuleDesc { @@ -121,13 +121,13 @@ type RuleDesc struct { Expr string `protobuf:"bytes,1,opt,name=expr,proto3" json:"expr,omitempty"` Record string `protobuf:"bytes,2,opt,name=record,proto3" json:"record,omitempty"` Alert string `protobuf:"bytes,3,opt,name=alert,proto3" json:"alert,omitempty"` - For *time.Duration `protobuf:"bytes,4,opt,name=for,proto3,stdduration" json:"for,omitempty"` + For time.Duration `protobuf:"bytes,4,opt,name=for,proto3,stdduration" json:"for"` Labels []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,5,rep,name=labels,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"labels"` Annotations []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,6,rep,name=annotations,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"annotations"` State string `protobuf:"bytes,7,opt,name=state,proto3" json:"state,omitempty"` Health string `protobuf:"bytes,8,opt,name=health,proto3" json:"health,omitempty"` LastError string `protobuf:"bytes,9,opt,name=lastError,proto3" json:"lastError,omitempty"` - Alerts []*Alert `protobuf:"bytes,10,rep,name=alerts,proto3" json:"alerts,omitempty"` + Alerts []*AlertDesc `protobuf:"bytes,10,rep,name=alerts,proto3" json:"alerts,omitempty"` } func (m *RuleDesc) Reset() { *m = RuleDesc{} } @@ -183,11 +183,11 @@ func (m *RuleDesc) GetAlert() string { return "" } -func (m *RuleDesc) GetFor() *time.Duration { +func (m *RuleDesc) GetFor() time.Duration { if m != nil { return m.For } - return nil + return 0 } func (m *RuleDesc) GetState() string { @@ -211,36 +211,36 @@ func (m *RuleDesc) GetLastError() string { return "" } -func (m *RuleDesc) GetAlerts() []*Alert { +func (m *RuleDesc) GetAlerts() []*AlertDesc { if m != nil { return m.Alerts } return nil } -type Alert struct { +type AlertDesc struct { State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` Labels []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,2,rep,name=labels,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"labels"` Annotations []github_com_cortexproject_cortex_pkg_ingester_client.LabelAdapter `protobuf:"bytes,3,rep,name=annotations,proto3,customtype=github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" json:"annotations"` Value float64 `protobuf:"fixed64,4,opt,name=value,proto3" json:"value,omitempty"` - ActiveAt *time.Time `protobuf:"bytes,5,opt,name=active_at,json=activeAt,proto3,stdtime" json:"active_at,omitempty"` - FiredAt *time.Time `protobuf:"bytes,6,opt,name=fired_at,json=firedAt,proto3,stdtime" json:"fired_at,omitempty"` - ResolvedAt *time.Time `protobuf:"bytes,7,opt,name=resolved_at,json=resolvedAt,proto3,stdtime" json:"resolved_at,omitempty"` - LastSentAt *time.Time `protobuf:"bytes,8,opt,name=last_sent_at,json=lastSentAt,proto3,stdtime" json:"last_sent_at,omitempty"` - ValidUntil *time.Time `protobuf:"bytes,9,opt,name=valid_until,json=validUntil,proto3,stdtime" json:"valid_until,omitempty"` + ActiveAt time.Time `protobuf:"bytes,5,opt,name=active_at,json=activeAt,proto3,stdtime" json:"active_at"` + FiredAt time.Time `protobuf:"bytes,6,opt,name=fired_at,json=firedAt,proto3,stdtime" json:"fired_at"` + ResolvedAt time.Time `protobuf:"bytes,7,opt,name=resolved_at,json=resolvedAt,proto3,stdtime" json:"resolved_at"` + LastSentAt time.Time `protobuf:"bytes,8,opt,name=last_sent_at,json=lastSentAt,proto3,stdtime" json:"last_sent_at"` + ValidUntil time.Time `protobuf:"bytes,9,opt,name=valid_until,json=validUntil,proto3,stdtime" json:"valid_until"` } -func (m *Alert) Reset() { *m = Alert{} } -func (*Alert) ProtoMessage() {} -func (*Alert) Descriptor() ([]byte, []int) { +func (m *AlertDesc) Reset() { *m = AlertDesc{} } +func (*AlertDesc) ProtoMessage() {} +func (*AlertDesc) Descriptor() ([]byte, []int) { return fileDescriptor_8e722d3e922f0937, []int{2} } -func (m *Alert) XXX_Unmarshal(b []byte) error { +func (m *AlertDesc) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *Alert) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *AlertDesc) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_Alert.Marshal(b, m, deterministic) + return xxx_messageInfo_AlertDesc.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalTo(b) @@ -250,118 +250,118 @@ func (m *Alert) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return b[:n], nil } } -func (m *Alert) XXX_Merge(src proto.Message) { - xxx_messageInfo_Alert.Merge(m, src) +func (m *AlertDesc) XXX_Merge(src proto.Message) { + xxx_messageInfo_AlertDesc.Merge(m, src) } -func (m *Alert) XXX_Size() int { +func (m *AlertDesc) XXX_Size() int { return m.Size() } -func (m *Alert) XXX_DiscardUnknown() { - xxx_messageInfo_Alert.DiscardUnknown(m) +func (m *AlertDesc) XXX_DiscardUnknown() { + xxx_messageInfo_AlertDesc.DiscardUnknown(m) } -var xxx_messageInfo_Alert proto.InternalMessageInfo +var xxx_messageInfo_AlertDesc proto.InternalMessageInfo -func (m *Alert) GetState() string { +func (m *AlertDesc) GetState() string { if m != nil { return m.State } return "" } -func (m *Alert) GetValue() float64 { +func (m *AlertDesc) GetValue() float64 { if m != nil { return m.Value } return 0 } -func (m *Alert) GetActiveAt() *time.Time { +func (m *AlertDesc) GetActiveAt() time.Time { if m != nil { return m.ActiveAt } - return nil + return time.Time{} } -func (m *Alert) GetFiredAt() *time.Time { +func (m *AlertDesc) GetFiredAt() time.Time { if m != nil { return m.FiredAt } - return nil + return time.Time{} } -func (m *Alert) GetResolvedAt() *time.Time { +func (m *AlertDesc) GetResolvedAt() time.Time { if m != nil { return m.ResolvedAt } - return nil + return time.Time{} } -func (m *Alert) GetLastSentAt() *time.Time { +func (m *AlertDesc) GetLastSentAt() time.Time { if m != nil { return m.LastSentAt } - return nil + return time.Time{} } -func (m *Alert) GetValidUntil() *time.Time { +func (m *AlertDesc) GetValidUntil() time.Time { if m != nil { return m.ValidUntil } - return nil + return time.Time{} } func init() { proto.RegisterType((*RuleGroupDesc)(nil), "rules.RuleGroupDesc") proto.RegisterType((*RuleDesc)(nil), "rules.RuleDesc") - proto.RegisterType((*Alert)(nil), "rules.Alert") + proto.RegisterType((*AlertDesc)(nil), "rules.AlertDesc") } func init() { proto.RegisterFile("rules.proto", fileDescriptor_8e722d3e922f0937) } var fileDescriptor_8e722d3e922f0937 = []byte{ - // 645 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0x4f, 0x6b, 0x14, 0x31, - 0x14, 0xdf, 0x74, 0xff, 0x67, 0x2b, 0x62, 0x10, 0x89, 0x45, 0xb2, 0x4b, 0x51, 0xd8, 0x8b, 0xbb, - 0x58, 0x8f, 0x45, 0x70, 0x97, 0x8a, 0x1e, 0x3c, 0xc8, 0xa8, 0x17, 0x2f, 0x25, 0x3b, 0xf3, 0x3a, - 0x1d, 0xcd, 0x4e, 0x86, 0x24, 0xb3, 0x78, 0x11, 0xfc, 0x08, 0x3d, 0xfa, 0x11, 0xfc, 0x28, 0x3d, - 0x16, 0xbc, 0x14, 0x0f, 0xd5, 0x4e, 0x11, 0xbc, 0x08, 0xfd, 0x08, 0x92, 0x64, 0xa6, 0x5b, 0xf4, - 0xb2, 0x08, 0xea, 0x69, 0xf2, 0x7b, 0x2f, 0xbf, 0xf7, 0xe7, 0xf7, 0x5e, 0x06, 0xf7, 0x54, 0x2e, - 0x40, 0x8f, 0x32, 0x25, 0x8d, 0x24, 0x4d, 0x07, 0x36, 0xee, 0xc6, 0x89, 0xd9, 0xcf, 0x67, 0xa3, - 0x50, 0xce, 0xc7, 0xb1, 0x8c, 0xe5, 0xd8, 0x79, 0x67, 0xf9, 0x9e, 0x43, 0x0e, 0xb8, 0x93, 0x67, - 0x6d, 0xb0, 0x58, 0xca, 0x58, 0xc0, 0xf2, 0x56, 0x94, 0x2b, 0x6e, 0x12, 0x99, 0x96, 0xfe, 0xfe, - 0xaf, 0x7e, 0x93, 0xcc, 0x41, 0x1b, 0x3e, 0xcf, 0xca, 0x0b, 0x0f, 0x2f, 0xe5, 0x0b, 0xa5, 0x32, - 0xf0, 0x36, 0x53, 0xf2, 0x35, 0x84, 0xa6, 0x44, 0xe3, 0xec, 0x4d, 0x3c, 0x4e, 0xd2, 0x18, 0xb4, - 0x01, 0x35, 0x0e, 0x45, 0x02, 0x69, 0xe5, 0xf2, 0x11, 0x36, 0x3f, 0x21, 0x7c, 0x25, 0xc8, 0x05, - 0x3c, 0x56, 0x32, 0xcf, 0x76, 0x40, 0x87, 0x84, 0xe0, 0x46, 0xca, 0xe7, 0x40, 0xd1, 0x00, 0x0d, - 0xbb, 0x81, 0x3b, 0x93, 0x5b, 0xb8, 0x6b, 0xbf, 0x3a, 0xe3, 0x21, 0xd0, 0x35, 0xe7, 0x58, 0x1a, - 0xc8, 0x36, 0xee, 0x24, 0xa9, 0x01, 0xb5, 0xe0, 0x82, 0xd6, 0x07, 0x68, 0xd8, 0xdb, 0xba, 0x39, - 0xf2, 0x95, 0x8f, 0xaa, 0xca, 0x47, 0x3b, 0x65, 0x67, 0xd3, 0xc6, 0x87, 0x2f, 0x7d, 0x14, 0x5c, - 0x10, 0xc8, 0x1d, 0xec, 0xb5, 0xa3, 0x8d, 0x41, 0x7d, 0xd8, 0xdb, 0xba, 0x3a, 0xf2, 0xb2, 0xda, - 0x9a, 0x6c, 0x39, 0x81, 0xf7, 0x12, 0x8a, 0xdb, 0x11, 0x08, 0x30, 0x10, 0xd1, 0xe6, 0x00, 0x0d, - 0x3b, 0x41, 0x05, 0x6d, 0xbd, 0xb9, 0x06, 0x45, 0x5b, 0xbe, 0x5e, 0x7b, 0xde, 0xfc, 0x56, 0xc7, - 0x9d, 0x2a, 0x82, 0xbd, 0x60, 0x75, 0xa9, 0x1a, 0xb2, 0x67, 0x72, 0x03, 0xb7, 0x14, 0x84, 0x52, - 0x45, 0x65, 0x37, 0x25, 0x22, 0xd7, 0x71, 0x93, 0x0b, 0x50, 0xc6, 0xf5, 0xd1, 0x0d, 0x3c, 0x20, - 0xf7, 0x70, 0x7d, 0x4f, 0x2a, 0xda, 0x58, 0xad, 0x37, 0x7b, 0x97, 0x68, 0xdc, 0x12, 0x7c, 0x06, - 0x42, 0xd3, 0xa6, 0xeb, 0xeb, 0xda, 0xa8, 0x94, 0xfd, 0xa9, 0xb5, 0x3e, 0xe3, 0x89, 0x9a, 0x3e, - 0x39, 0x3c, 0xe9, 0xd7, 0x3e, 0x9f, 0xf4, 0xff, 0x64, 0x88, 0x3e, 0xcc, 0x24, 0xe2, 0x99, 0x01, - 0x15, 0x94, 0xa9, 0xc8, 0x3b, 0xdc, 0xe3, 0x69, 0x2a, 0x8d, 0xab, 0x46, 0xd3, 0xd6, 0xdf, 0xcf, - 0x7c, 0x39, 0x9f, 0x15, 0x4f, 0x1b, 0x6e, 0x80, 0xb6, 0xbd, 0x78, 0x0e, 0x58, 0xa9, 0xf7, 0x81, - 0x0b, 0xb3, 0x4f, 0x3b, 0x5e, 0x6a, 0x8f, 0xec, 0x4e, 0x09, 0xae, 0xcd, 0x23, 0xa5, 0xa4, 0xa2, - 0x5d, 0xbf, 0x53, 0x17, 0x06, 0x72, 0x1b, 0xb7, 0x9c, 0xf6, 0x9a, 0x62, 0xd7, 0xc5, 0x7a, 0xb9, - 0x17, 0x13, 0x6b, 0x0c, 0x4a, 0xdf, 0xe6, 0x8f, 0x06, 0x6e, 0x3a, 0xcb, 0x32, 0x37, 0xba, 0x9c, - 0x7b, 0x39, 0x85, 0xb5, 0xff, 0x36, 0x85, 0xfa, 0xbf, 0x9f, 0xc2, 0x82, 0x8b, 0x1c, 0xdc, 0xba, - 0xa2, 0xc0, 0x03, 0xf2, 0x00, 0x77, 0x79, 0x68, 0x92, 0x05, 0xec, 0x72, 0xe3, 0x5e, 0x50, 0x6f, - 0x6b, 0xe3, 0xb7, 0x45, 0x7e, 0x51, 0xfd, 0x5e, 0xa6, 0x8d, 0x03, 0xf7, 0x4a, 0x3d, 0x65, 0x62, - 0xec, 0x13, 0xdf, 0x4b, 0x14, 0x44, 0x96, 0xdd, 0x5a, 0x91, 0xdd, 0x76, 0x8c, 0x89, 0x21, 0x13, - 0xdc, 0x53, 0xa0, 0xa5, 0x58, 0x78, 0x7e, 0x7b, 0x45, 0x3e, 0xae, 0x48, 0x13, 0x43, 0xa6, 0x78, - 0xdd, 0xee, 0xc6, 0xae, 0x86, 0xd4, 0xd8, 0x18, 0x9d, 0x55, 0x63, 0x58, 0xd6, 0x73, 0x48, 0x8d, - 0x2f, 0x63, 0xc1, 0x45, 0x12, 0xed, 0xe6, 0xa9, 0x49, 0x84, 0x5b, 0xb9, 0x95, 0x42, 0x38, 0xd2, - 0x4b, 0xcb, 0x99, 0x6e, 0x1f, 0x9d, 0xb2, 0xda, 0xf1, 0x29, 0xab, 0x9d, 0x9f, 0x32, 0xf4, 0xbe, - 0x60, 0xe8, 0x63, 0xc1, 0xd0, 0x61, 0xc1, 0xd0, 0x51, 0xc1, 0xd0, 0xd7, 0x82, 0xa1, 0xef, 0x05, - 0xab, 0x9d, 0x17, 0x0c, 0x1d, 0x9c, 0xb1, 0xda, 0xd1, 0x19, 0xab, 0x1d, 0x9f, 0xb1, 0xda, 0x2b, - 0xff, 0x0b, 0x9b, 0xb5, 0x5c, 0x8a, 0xfb, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xf4, 0x48, - 0x2d, 0x39, 0x06, 0x00, 0x00, + // 651 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0xbf, 0x6f, 0xd4, 0x30, + 0x14, 0x3e, 0xf7, 0x7a, 0xbf, 0x7c, 0x20, 0xc0, 0x42, 0xc8, 0x54, 0xc8, 0x77, 0xaa, 0x84, 0x74, + 0x0b, 0x39, 0xa9, 0x88, 0x89, 0x01, 0xae, 0x6a, 0x81, 0x81, 0x01, 0x05, 0x58, 0x58, 0x2a, 0x5f, + 0xf2, 0x9a, 0x06, 0x7c, 0x71, 0x64, 0x3b, 0x27, 0x16, 0x24, 0x16, 0xf6, 0x8e, 0xfc, 0x09, 0xfc, + 0x29, 0x1d, 0xbb, 0x51, 0x31, 0x14, 0x9a, 0x2e, 0x2c, 0x48, 0xfd, 0x13, 0x90, 0xed, 0xa4, 0x57, + 0xc1, 0xd2, 0x22, 0x01, 0x53, 0xfc, 0xf9, 0xf9, 0x7d, 0xef, 0x7b, 0xcf, 0x9f, 0x83, 0xfb, 0xaa, + 0x10, 0xa0, 0x83, 0x5c, 0x49, 0x23, 0x49, 0xcb, 0x81, 0x95, 0x3b, 0x49, 0x6a, 0x76, 0x8a, 0x69, + 0x10, 0xc9, 0xd9, 0x38, 0x91, 0x89, 0x1c, 0xbb, 0xe8, 0xb4, 0xd8, 0x76, 0xc8, 0x01, 0xb7, 0xf2, + 0x59, 0x2b, 0x2c, 0x91, 0x32, 0x11, 0xb0, 0x38, 0x15, 0x17, 0x8a, 0x9b, 0x54, 0x66, 0x55, 0x7c, + 0xf0, 0x6b, 0xdc, 0xa4, 0x33, 0xd0, 0x86, 0xcf, 0xf2, 0xea, 0xc0, 0xc3, 0x33, 0xf5, 0x22, 0xa9, + 0x0c, 0xbc, 0xcd, 0x95, 0x7c, 0x0d, 0x91, 0xa9, 0xd0, 0x38, 0x7f, 0x93, 0x8c, 0xd3, 0x2c, 0x01, + 0x6d, 0x40, 0x8d, 0x23, 0x91, 0x42, 0x56, 0x87, 0x3c, 0xc3, 0xea, 0x67, 0x84, 0x2f, 0x87, 0x85, + 0x80, 0xc7, 0x4a, 0x16, 0xf9, 0x06, 0xe8, 0x88, 0x10, 0xbc, 0x9c, 0xf1, 0x19, 0x50, 0x34, 0x44, + 0xa3, 0x5e, 0xe8, 0xd6, 0xe4, 0x16, 0xee, 0xd9, 0xaf, 0xce, 0x79, 0x04, 0x74, 0xc9, 0x05, 0x16, + 0x1b, 0xe4, 0x01, 0xee, 0xa6, 0x99, 0x01, 0x35, 0xe7, 0x82, 0x36, 0x87, 0x68, 0xd4, 0x5f, 0xbb, + 0x19, 0x78, 0xe5, 0x41, 0xad, 0x3c, 0xd8, 0xa8, 0x3a, 0x5b, 0xef, 0xee, 0x1d, 0x0e, 0x1a, 0x1f, + 0xbf, 0x0e, 0x50, 0x78, 0x9a, 0x44, 0x6e, 0x63, 0x3f, 0x3f, 0xba, 0x3c, 0x6c, 0x8e, 0xfa, 0x6b, + 0x57, 0x02, 0x3f, 0x5a, 0xab, 0xcb, 0x4a, 0x0a, 0x7d, 0x94, 0x50, 0xdc, 0x89, 0x41, 0x80, 0x81, + 0x98, 0xb6, 0x86, 0x68, 0xd4, 0x0d, 0x6b, 0x68, 0x35, 0x17, 0x1a, 0x14, 0x6d, 0x7b, 0xcd, 0x76, + 0xbd, 0xfa, 0xa3, 0x89, 0xbb, 0x35, 0x83, 0x3d, 0x60, 0x67, 0x53, 0x37, 0x65, 0xd7, 0xe4, 0x06, + 0x6e, 0x2b, 0x88, 0xa4, 0x8a, 0xab, 0x8e, 0x2a, 0x44, 0xae, 0xe3, 0x16, 0x17, 0xa0, 0x8c, 0xeb, + 0xa5, 0x17, 0x7a, 0x40, 0xee, 0xe1, 0xe6, 0xb6, 0x54, 0x74, 0xf9, 0xfc, 0xfd, 0xd9, 0xf3, 0x44, + 0xe3, 0xb6, 0xe0, 0x53, 0x10, 0x9a, 0xb6, 0x5c, 0x6f, 0xd7, 0x82, 0x6a, 0xfc, 0x4f, 0xed, 0xee, + 0x33, 0x9e, 0xaa, 0xf5, 0x27, 0x36, 0xe3, 0xcb, 0xe1, 0xe0, 0x4f, 0x2e, 0xd3, 0xd3, 0x4c, 0x62, + 0x9e, 0x1b, 0x50, 0x61, 0x55, 0x8a, 0xbc, 0xc3, 0x7d, 0x9e, 0x65, 0xd2, 0x38, 0x45, 0x9a, 0xb6, + 0xff, 0x7e, 0xe5, 0xb3, 0xf5, 0xec, 0x00, 0xb5, 0xe1, 0x06, 0x68, 0xc7, 0x0f, 0xd0, 0x01, 0x3b, + 0xee, 0x1d, 0xe0, 0xc2, 0xec, 0xd0, 0xae, 0x1f, 0xb7, 0x47, 0xd6, 0x5b, 0x82, 0x6b, 0xb3, 0xa9, + 0x94, 0x54, 0xb4, 0xe7, 0xbd, 0x75, 0xba, 0x41, 0x46, 0xb8, 0xed, 0xe6, 0xaf, 0x29, 0x76, 0x5d, + 0x5c, 0xad, 0xbc, 0x31, 0xb1, 0x9b, 0xce, 0x1c, 0x55, 0x7c, 0xf5, 0x43, 0x0b, 0xf7, 0x4e, 0x77, + 0x17, 0x1a, 0xd0, 0x59, 0x0d, 0x8b, 0xdb, 0x58, 0xfa, 0x6f, 0xb7, 0xd1, 0xfc, 0xf7, 0xb7, 0x31, + 0xe7, 0xa2, 0x00, 0x67, 0x5d, 0x14, 0x7a, 0x40, 0x26, 0xb8, 0xc7, 0x23, 0x93, 0xce, 0x61, 0x8b, + 0x1b, 0xf7, 0x9a, 0xfa, 0x6b, 0x2b, 0xbf, 0x99, 0xfa, 0x45, 0xfd, 0xbb, 0xf1, 0xae, 0xde, 0x75, + 0xaf, 0xd6, 0xa7, 0x4d, 0x8c, 0x7d, 0xf6, 0xdb, 0xa9, 0x82, 0xd8, 0x32, 0xb4, 0x2f, 0xc0, 0xd0, + 0x71, 0x59, 0x13, 0x43, 0x36, 0x71, 0x5f, 0x81, 0x96, 0x62, 0xee, 0x39, 0x3a, 0x17, 0xe0, 0xc0, + 0x75, 0xe2, 0xc4, 0x90, 0x47, 0xf8, 0x92, 0xf5, 0xcb, 0x96, 0x86, 0xcc, 0x58, 0x9e, 0xee, 0x45, + 0x78, 0x6c, 0xe6, 0x73, 0xc8, 0x8c, 0x97, 0x33, 0xe7, 0x22, 0x8d, 0xb7, 0x8a, 0xcc, 0xa4, 0xc2, + 0x59, 0xf1, 0xdc, 0x34, 0x2e, 0xf1, 0xa5, 0xcd, 0x5b, 0xbf, 0xbf, 0x7f, 0xc4, 0x1a, 0x07, 0x47, + 0xac, 0x71, 0x72, 0xc4, 0xd0, 0xfb, 0x92, 0xa1, 0x4f, 0x25, 0x43, 0x7b, 0x25, 0x43, 0xfb, 0x25, + 0x43, 0xdf, 0x4a, 0x86, 0xbe, 0x97, 0xac, 0x71, 0x52, 0x32, 0xb4, 0x7b, 0xcc, 0x1a, 0xfb, 0xc7, + 0xac, 0x71, 0x70, 0xcc, 0x1a, 0xaf, 0xfc, 0x2f, 0x6e, 0xda, 0x76, 0x65, 0xee, 0xfe, 0x0c, 0x00, + 0x00, 0xff, 0xff, 0x26, 0xdc, 0xc9, 0xc9, 0x5d, 0x06, 0x00, 0x00, } func (this *RuleGroupDesc) Equal(that interface{}) bool { @@ -389,13 +389,7 @@ func (this *RuleGroupDesc) Equal(that interface{}) bool { if this.Namespace != that1.Namespace { return false } - if this.Interval != nil && that1.Interval != nil { - if *this.Interval != *that1.Interval { - return false - } - } else if this.Interval != nil { - return false - } else if that1.Interval != nil { + if this.Interval != that1.Interval { return false } if len(this.Rules) != len(that1.Rules) { @@ -442,13 +436,7 @@ func (this *RuleDesc) Equal(that interface{}) bool { if this.Alert != that1.Alert { return false } - if this.For != nil && that1.For != nil { - if *this.For != *that1.For { - return false - } - } else if this.For != nil { - return false - } else if that1.For != nil { + if this.For != that1.For { return false } if len(this.Labels) != len(that1.Labels) { @@ -486,14 +474,14 @@ func (this *RuleDesc) Equal(that interface{}) bool { } return true } -func (this *Alert) Equal(that interface{}) bool { +func (this *AlertDesc) Equal(that interface{}) bool { if that == nil { return this == nil } - that1, ok := that.(*Alert) + that1, ok := that.(*AlertDesc) if !ok { - that2, ok := that.(Alert) + that2, ok := that.(AlertDesc) if ok { that1 = &that2 } else { @@ -527,39 +515,19 @@ func (this *Alert) Equal(that interface{}) bool { if this.Value != that1.Value { return false } - if that1.ActiveAt == nil { - if this.ActiveAt != nil { - return false - } - } else if !this.ActiveAt.Equal(*that1.ActiveAt) { + if !this.ActiveAt.Equal(that1.ActiveAt) { return false } - if that1.FiredAt == nil { - if this.FiredAt != nil { - return false - } - } else if !this.FiredAt.Equal(*that1.FiredAt) { + if !this.FiredAt.Equal(that1.FiredAt) { return false } - if that1.ResolvedAt == nil { - if this.ResolvedAt != nil { - return false - } - } else if !this.ResolvedAt.Equal(*that1.ResolvedAt) { + if !this.ResolvedAt.Equal(that1.ResolvedAt) { return false } - if that1.LastSentAt == nil { - if this.LastSentAt != nil { - return false - } - } else if !this.LastSentAt.Equal(*that1.LastSentAt) { + if !this.LastSentAt.Equal(that1.LastSentAt) { return false } - if that1.ValidUntil == nil { - if this.ValidUntil != nil { - return false - } - } else if !this.ValidUntil.Equal(*that1.ValidUntil) { + if !this.ValidUntil.Equal(that1.ValidUntil) { return false } return true @@ -602,12 +570,12 @@ func (this *RuleDesc) GoString() string { s = append(s, "}") return strings.Join(s, "") } -func (this *Alert) GoString() string { +func (this *AlertDesc) GoString() string { if this == nil { return "nil" } s := make([]string, 0, 13) - s = append(s, "&rules.Alert{") + s = append(s, "&rules.AlertDesc{") s = append(s, "State: "+fmt.Sprintf("%#v", this.State)+",\n") s = append(s, "Labels: "+fmt.Sprintf("%#v", this.Labels)+",\n") s = append(s, "Annotations: "+fmt.Sprintf("%#v", this.Annotations)+",\n") @@ -655,16 +623,14 @@ func (m *RuleGroupDesc) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintRules(dAtA, i, uint64(len(m.Namespace))) i += copy(dAtA[i:], m.Namespace) } - if m.Interval != nil { - dAtA[i] = 0x1a - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Interval))) - n1, err := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.Interval, dAtA[i:]) - if err != nil { - return 0, err - } - i += n1 + dAtA[i] = 0x1a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdDuration(m.Interval))) + n1, err := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Interval, dAtA[i:]) + if err != nil { + return 0, err } + i += n1 if len(m.Rules) > 0 { for _, msg := range m.Rules { dAtA[i] = 0x22 @@ -729,16 +695,14 @@ func (m *RuleDesc) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintRules(dAtA, i, uint64(len(m.Alert))) i += copy(dAtA[i:], m.Alert) } - if m.For != nil { - dAtA[i] = 0x22 - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdDuration(*m.For))) - n2, err := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.For, dAtA[i:]) - if err != nil { - return 0, err - } - i += n2 + dAtA[i] = 0x22 + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdDuration(m.For))) + n2, err := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.For, dAtA[i:]) + if err != nil { + return 0, err } + i += n2 if len(m.Labels) > 0 { for _, msg := range m.Labels { dAtA[i] = 0x2a @@ -796,7 +760,7 @@ func (m *RuleDesc) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func (m *Alert) Marshal() (dAtA []byte, err error) { +func (m *AlertDesc) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalTo(dAtA) @@ -806,7 +770,7 @@ func (m *Alert) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *Alert) MarshalTo(dAtA []byte) (int, error) { +func (m *AlertDesc) MarshalTo(dAtA []byte) (int, error) { var i int _ = i var l int @@ -847,56 +811,46 @@ func (m *Alert) MarshalTo(dAtA []byte) (int, error) { encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Value)))) i += 8 } - if m.ActiveAt != nil { - dAtA[i] = 0x2a - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ActiveAt))) - n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ActiveAt, dAtA[i:]) - if err != nil { - return 0, err - } - i += n3 + dAtA[i] = 0x2a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ActiveAt))) + n3, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ActiveAt, dAtA[i:]) + if err != nil { + return 0, err } - if m.FiredAt != nil { - dAtA[i] = 0x32 - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.FiredAt))) - n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.FiredAt, dAtA[i:]) - if err != nil { - return 0, err - } - i += n4 + i += n3 + dAtA[i] = 0x32 + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.FiredAt))) + n4, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.FiredAt, dAtA[i:]) + if err != nil { + return 0, err } - if m.ResolvedAt != nil { - dAtA[i] = 0x3a - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ResolvedAt))) - n5, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ResolvedAt, dAtA[i:]) - if err != nil { - return 0, err - } - i += n5 + i += n4 + dAtA[i] = 0x3a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ResolvedAt))) + n5, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ResolvedAt, dAtA[i:]) + if err != nil { + return 0, err } - if m.LastSentAt != nil { - dAtA[i] = 0x42 - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastSentAt))) - n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.LastSentAt, dAtA[i:]) - if err != nil { - return 0, err - } - i += n6 + i += n5 + dAtA[i] = 0x42 + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.LastSentAt))) + n6, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastSentAt, dAtA[i:]) + if err != nil { + return 0, err } - if m.ValidUntil != nil { - dAtA[i] = 0x4a - i++ - i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(*m.ValidUntil))) - n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.ValidUntil, dAtA[i:]) - if err != nil { - return 0, err - } - i += n7 + i += n6 + dAtA[i] = 0x4a + i++ + i = encodeVarintRules(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ValidUntil))) + n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ValidUntil, dAtA[i:]) + if err != nil { + return 0, err } + i += n7 return i, nil } @@ -923,10 +877,8 @@ func (m *RuleGroupDesc) Size() (n int) { if l > 0 { n += 1 + l + sovRules(uint64(l)) } - if m.Interval != nil { - l = github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Interval) - n += 1 + l + sovRules(uint64(l)) - } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Interval) + n += 1 + l + sovRules(uint64(l)) if len(m.Rules) > 0 { for _, e := range m.Rules { l = e.Size() @@ -961,10 +913,8 @@ func (m *RuleDesc) Size() (n int) { if l > 0 { n += 1 + l + sovRules(uint64(l)) } - if m.For != nil { - l = github_com_gogo_protobuf_types.SizeOfStdDuration(*m.For) - n += 1 + l + sovRules(uint64(l)) - } + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.For) + n += 1 + l + sovRules(uint64(l)) if len(m.Labels) > 0 { for _, e := range m.Labels { l = e.Size() @@ -998,7 +948,7 @@ func (m *RuleDesc) Size() (n int) { return n } -func (m *Alert) Size() (n int) { +func (m *AlertDesc) Size() (n int) { if m == nil { return 0 } @@ -1023,26 +973,16 @@ func (m *Alert) Size() (n int) { if m.Value != 0 { n += 9 } - if m.ActiveAt != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ActiveAt) - n += 1 + l + sovRules(uint64(l)) - } - if m.FiredAt != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.FiredAt) - n += 1 + l + sovRules(uint64(l)) - } - if m.ResolvedAt != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ResolvedAt) - n += 1 + l + sovRules(uint64(l)) - } - if m.LastSentAt != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.LastSentAt) - n += 1 + l + sovRules(uint64(l)) - } - if m.ValidUntil != nil { - l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.ValidUntil) - n += 1 + l + sovRules(uint64(l)) - } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ActiveAt) + n += 1 + l + sovRules(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.FiredAt) + n += 1 + l + sovRules(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ResolvedAt) + n += 1 + l + sovRules(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastSentAt) + n += 1 + l + sovRules(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ValidUntil) + n += 1 + l + sovRules(uint64(l)) return n } @@ -1066,7 +1006,7 @@ func (this *RuleGroupDesc) String() string { s := strings.Join([]string{`&RuleGroupDesc{`, `Name:` + fmt.Sprintf("%v", this.Name) + `,`, `Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`, - `Interval:` + strings.Replace(fmt.Sprintf("%v", this.Interval), "Duration", "duration.Duration", 1) + `,`, + `Interval:` + strings.Replace(strings.Replace(this.Interval.String(), "Duration", "duration.Duration", 1), `&`, ``, 1) + `,`, `Rules:` + strings.Replace(fmt.Sprintf("%v", this.Rules), "RuleDesc", "RuleDesc", 1) + `,`, `Deleted:` + fmt.Sprintf("%v", this.Deleted) + `,`, `User:` + fmt.Sprintf("%v", this.User) + `,`, @@ -1082,31 +1022,31 @@ func (this *RuleDesc) String() string { `Expr:` + fmt.Sprintf("%v", this.Expr) + `,`, `Record:` + fmt.Sprintf("%v", this.Record) + `,`, `Alert:` + fmt.Sprintf("%v", this.Alert) + `,`, - `For:` + strings.Replace(fmt.Sprintf("%v", this.For), "Duration", "duration.Duration", 1) + `,`, + `For:` + strings.Replace(strings.Replace(this.For.String(), "Duration", "duration.Duration", 1), `&`, ``, 1) + `,`, `Labels:` + fmt.Sprintf("%v", this.Labels) + `,`, `Annotations:` + fmt.Sprintf("%v", this.Annotations) + `,`, `State:` + fmt.Sprintf("%v", this.State) + `,`, `Health:` + fmt.Sprintf("%v", this.Health) + `,`, `LastError:` + fmt.Sprintf("%v", this.LastError) + `,`, - `Alerts:` + strings.Replace(fmt.Sprintf("%v", this.Alerts), "Alert", "Alert", 1) + `,`, + `Alerts:` + strings.Replace(fmt.Sprintf("%v", this.Alerts), "AlertDesc", "AlertDesc", 1) + `,`, `}`, }, "") return s } -func (this *Alert) String() string { +func (this *AlertDesc) String() string { if this == nil { return "nil" } - s := strings.Join([]string{`&Alert{`, + s := strings.Join([]string{`&AlertDesc{`, `State:` + fmt.Sprintf("%v", this.State) + `,`, `Labels:` + fmt.Sprintf("%v", this.Labels) + `,`, `Annotations:` + fmt.Sprintf("%v", this.Annotations) + `,`, `Value:` + fmt.Sprintf("%v", this.Value) + `,`, - `ActiveAt:` + strings.Replace(fmt.Sprintf("%v", this.ActiveAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, - `FiredAt:` + strings.Replace(fmt.Sprintf("%v", this.FiredAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, - `ResolvedAt:` + strings.Replace(fmt.Sprintf("%v", this.ResolvedAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, - `LastSentAt:` + strings.Replace(fmt.Sprintf("%v", this.LastSentAt), "Timestamp", "timestamp.Timestamp", 1) + `,`, - `ValidUntil:` + strings.Replace(fmt.Sprintf("%v", this.ValidUntil), "Timestamp", "timestamp.Timestamp", 1) + `,`, + `ActiveAt:` + strings.Replace(strings.Replace(this.ActiveAt.String(), "Timestamp", "timestamp.Timestamp", 1), `&`, ``, 1) + `,`, + `FiredAt:` + strings.Replace(strings.Replace(this.FiredAt.String(), "Timestamp", "timestamp.Timestamp", 1), `&`, ``, 1) + `,`, + `ResolvedAt:` + strings.Replace(strings.Replace(this.ResolvedAt.String(), "Timestamp", "timestamp.Timestamp", 1), `&`, ``, 1) + `,`, + `LastSentAt:` + strings.Replace(strings.Replace(this.LastSentAt.String(), "Timestamp", "timestamp.Timestamp", 1), `&`, ``, 1) + `,`, + `ValidUntil:` + strings.Replace(strings.Replace(this.ValidUntil.String(), "Timestamp", "timestamp.Timestamp", 1), `&`, ``, 1) + `,`, `}`, }, "") return s @@ -1241,10 +1181,7 @@ func (m *RuleGroupDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Interval == nil { - m.Interval = new(time.Duration) - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.Interval, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.Interval, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1512,10 +1449,7 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.For == nil { - m.For = new(time.Duration) - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(m.For, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.For, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1712,7 +1646,7 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Alerts = append(m.Alerts, &Alert{}) + m.Alerts = append(m.Alerts, &AlertDesc{}) if err := m.Alerts[len(m.Alerts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1741,7 +1675,7 @@ func (m *RuleDesc) Unmarshal(dAtA []byte) error { } return nil } -func (m *Alert) Unmarshal(dAtA []byte) error { +func (m *AlertDesc) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1764,10 +1698,10 @@ func (m *Alert) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: Alert: wiretype end group for non-group") + return fmt.Errorf("proto: AlertDesc: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: Alert: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: AlertDesc: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1910,10 +1844,7 @@ func (m *Alert) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ActiveAt == nil { - m.ActiveAt = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ActiveAt, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ActiveAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1946,10 +1877,7 @@ func (m *Alert) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.FiredAt == nil { - m.FiredAt = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.FiredAt, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.FiredAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -1982,10 +1910,7 @@ func (m *Alert) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ResolvedAt == nil { - m.ResolvedAt = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ResolvedAt, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ResolvedAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2018,10 +1943,7 @@ func (m *Alert) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.LastSentAt == nil { - m.LastSentAt = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.LastSentAt, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.LastSentAt, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2054,10 +1976,7 @@ func (m *Alert) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ValidUntil == nil { - m.ValidUntil = new(time.Time) - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.ValidUntil, dAtA[iNdEx:postIndex]); err != nil { + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ValidUntil, dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/pkg/ruler/rules/rules.proto b/pkg/ruler/rules/rules.proto index b12bc9be00f..3b842cdc5b8 100644 --- a/pkg/ruler/rules/rules.proto +++ b/pkg/ruler/rules/rules.proto @@ -17,7 +17,8 @@ option (gogoproto.unmarshaler_all) = true; message RuleGroupDesc { string name = 1; string namespace = 2; - google.protobuf.Duration interval = 3 [(gogoproto.stdduration) = true]; + google.protobuf.Duration interval = 3 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; repeated RuleDesc rules = 4; bool deleted = 5; string user = 6; @@ -28,7 +29,7 @@ message RuleDesc { string expr = 1; string record = 2; string alert = 3; - google.protobuf.Duration for = 4 [(gogoproto.stdduration) = true]; + google.protobuf.Duration for = 4 [(gogoproto.nullable) = false,(gogoproto.stdduration) = true]; repeated cortex.LabelPair labels = 5 [ (gogoproto.nullable) = false, (gogoproto.customtype) = @@ -42,10 +43,10 @@ message RuleDesc { string state = 7; string health = 8; string lastError = 9; - repeated Alert alerts = 10; + repeated AlertDesc alerts = 10; } -message Alert { +message AlertDesc { string state = 1; repeated cortex.LabelPair labels = 2 [ (gogoproto.nullable) = false, @@ -58,9 +59,14 @@ message Alert { "github.com/cortexproject/cortex/pkg/ingester/client.LabelAdapter" ]; double value = 4; - google.protobuf.Timestamp active_at = 5 [(gogoproto.stdtime) = true]; - google.protobuf.Timestamp fired_at = 6 [(gogoproto.stdtime) = true]; - google.protobuf.Timestamp resolved_at = 7 [(gogoproto.stdtime) = true]; - google.protobuf.Timestamp last_sent_at = 8 [(gogoproto.stdtime) = true]; - google.protobuf.Timestamp valid_until = 9 [(gogoproto.stdtime) = true]; + google.protobuf.Timestamp active_at = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp fired_at = 6 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp resolved_at = 7 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp last_sent_at = 8 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + google.protobuf.Timestamp valid_until = 9 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; } \ No newline at end of file diff --git a/pkg/ruler/store_mock_test.go b/pkg/ruler/store_mock_test.go index 3b0dae8893e..f8b3f9e7ed3 100644 --- a/pkg/ruler/store_mock_test.go +++ b/pkg/ruler/store_mock_test.go @@ -29,7 +29,7 @@ var ( Expr: "up < 1", }, }, - Interval: &interval, + Interval: interval, }, }, "user2": { @@ -43,7 +43,7 @@ var ( Expr: "up", }, }, - Interval: &interval, + Interval: interval, }, }, } From abe4ab711290fe1133d3e2eda454b6df2ac05d55 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 29 Jan 2020 18:01:38 -0500 Subject: [PATCH 25/29] ensure ruler is registered as grpc service Signed-off-by: Jacob Lisi --- pkg/cortex/modules.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index dd91a6c32b6..d493e905715 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -423,6 +423,7 @@ func (t *Cortex) initRuler(cfg *Config) (err error) { if cfg.Ruler.EnableAPI { subrouter := t.server.HTTP.PathPrefix(cfg.HTTPPrefix).Subrouter() t.ruler.RegisterRoutes(subrouter) + ruler.RegisterRulerServer(t.server.GRPC, t.ruler) } t.server.HTTP.Handle("/ruler_ring", t.ruler) From 15de020ab0936f42a0d156588ed918d5af62300f Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 29 Jan 2020 18:02:09 -0500 Subject: [PATCH 26/29] use noop querier for test cases Signed-off-by: Jacob Lisi --- pkg/ruler/ruler_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/ruler/ruler_test.go b/pkg/ruler/ruler_test.go index f213b6492c4..7d4660a2bb3 100644 --- a/pkg/ruler/ruler_test.go +++ b/pkg/ruler/ruler_test.go @@ -2,7 +2,6 @@ package ruler import ( "context" - "errors" "io/ioutil" "net/http" "net/http/httptest" @@ -58,7 +57,7 @@ func newTestRuler(t *testing.T, cfg Config) *Ruler { }) noopQueryable := storage.QueryableFunc(func(ctx context.Context, mint, maxt int64) (storage.Querier, error) { - return nil, errors.New("not implemented") + return storage.NoopQuerier(), nil }) l := log.NewLogfmtLogger(os.Stdout) From 53aadefdb88d55e26927f2675ecaa9de62c4c864 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Wed, 29 Jan 2020 18:12:40 -0500 Subject: [PATCH 27/29] format alert value string identical to Prometheus Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 60a5bc29a70..9d16876c17e 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -2,8 +2,8 @@ package ruler import ( "encoding/json" - "fmt" "net/http" + "strconv" "time" "github.com/go-kit/kit/log" @@ -155,7 +155,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { Annotations: client.FromLabelAdaptersToLabels(a.Annotations), State: a.GetState(), ActiveAt: &a.ActiveAt, - Value: fmt.Sprintf("%f", a.Value), + Value: strconv.FormatFloat(a.Value, 'e', -1, 64), }) } grp.Rules[i] = alertingRule{ @@ -228,7 +228,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { Annotations: client.FromLabelAdaptersToLabels(a.Annotations), State: a.GetState(), ActiveAt: &a.ActiveAt, - Value: fmt.Sprintf("%f", a.Value), + Value: strconv.FormatFloat(a.Value, 'e', -1, 64), }) } } From c7fe74f8e78915b9406c06950efb68bd9bf693d2 Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Thu, 30 Jan 2020 12:09:40 -0500 Subject: [PATCH 28/29] refactor per PR comments Signed-off-by: Jacob Lisi --- pkg/ruler/api.go | 16 ++++++++-------- pkg/ruler/ruler.go | 2 +- pkg/ruler/rules/compat.go | 14 +++++--------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/pkg/ruler/api.go b/pkg/ruler/api.go index 9d16876c17e..2ac27d83ba9 100644 --- a/pkg/ruler/api.go +++ b/pkg/ruler/api.go @@ -99,10 +99,10 @@ type recordingRule struct { Type v1.RuleType `json:"type"` } -func respondError(logger log.Logger, w http.ResponseWriter, msg string, errType v1.ErrorType) { +func respondError(logger log.Logger, w http.ResponseWriter, msg string) { b, err := json.Marshal(&response{ Status: "error", - ErrorType: errType, + ErrorType: v1.ErrServer, Error: msg, Data: nil, }) @@ -124,7 +124,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - respondError(logger, w, "no valid org id found", v1.ErrServer) + respondError(logger, w, "no valid org id found") return } @@ -132,7 +132,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - respondError(logger, w, err.Error(), v1.ErrServer) + respondError(logger, w, err.Error()) return } @@ -190,7 +190,7 @@ func (r *Ruler) rules(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) - respondError(logger, w, "unable to marshal the requested data", v1.ErrServer) + respondError(logger, w, "unable to marshal the requested data") return } w.Header().Set("Content-Type", "application/json") @@ -205,7 +205,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { userID, ctx, err := user.ExtractOrgIDFromHTTPRequest(req) if err != nil { level.Error(logger).Log("msg", "error extracting org id from context", "err", err) - respondError(logger, w, "no valid org id found", v1.ErrServer) + respondError(logger, w, "no valid org id found") return } @@ -213,7 +213,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { rgs, err := r.GetRules(ctx, userID) if err != nil { - respondError(logger, w, err.Error(), v1.ErrServer) + respondError(logger, w, err.Error()) return } @@ -241,7 +241,7 @@ func (r *Ruler) alerts(w http.ResponseWriter, req *http.Request) { }) if err != nil { level.Error(logger).Log("msg", "error marshaling json response", "err", err) - respondError(logger, w, "unable to marshal the requested data", v1.ErrServer) + respondError(logger, w, "unable to marshal the requested data") return } w.Header().Set("Content-Type", "application/json") diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 42471aed96b..dafc1322b04 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -431,7 +431,7 @@ func (r *Ruler) syncManager(ctx native_ctx.Context, user string, groups store.Ru } err = manager.Update(r.cfg.EvaluationInterval, files, nil) if err != nil { - level.Error(r.logger).Log("dsg", "unable to update rule manager", "user", user, "err", err) + level.Error(r.logger).Log("msg", "unable to update rule manager", "user", user, "err", err) return } } diff --git a/pkg/ruler/rules/compat.go b/pkg/ruler/rules/compat.go index 4561ccedf3d..693157d15d8 100644 --- a/pkg/ruler/rules/compat.go +++ b/pkg/ruler/rules/compat.go @@ -12,11 +12,10 @@ import ( // ToProto transforms a formatted prometheus rulegroup to a rule group protobuf func ToProto(user string, namespace string, rl rulefmt.RuleGroup) *RuleGroupDesc { - dur := time.Duration(rl.Interval) rg := RuleGroupDesc{ Name: rl.Name, Namespace: namespace, - Interval: dur, + Interval: time.Duration(rl.Interval), Rules: formattedRuleToProto(rl.Rules), User: user, } @@ -26,14 +25,11 @@ func ToProto(user string, namespace string, rl rulefmt.RuleGroup) *RuleGroupDesc func formattedRuleToProto(rls []rulefmt.Rule) []*RuleDesc { rules := make([]*RuleDesc, len(rls)) for i := range rls { - f := time.Duration(rls[i].For) - rules[i] = &RuleDesc{ - Expr: rls[i].Expr, - Record: rls[i].Record, - Alert: rls[i].Alert, - - For: f, + Expr: rls[i].Expr, + Record: rls[i].Record, + Alert: rls[i].Alert, + For: time.Duration(rls[i].For), Labels: client.FromLabelsToLabelAdapters(labels.FromMap(rls[i].Labels)), Annotations: client.FromLabelsToLabelAdapters(labels.FromMap(rls[i].Annotations)), } From ecf1860edd4ce7db6f11baaac9f43f15ed24de3e Mon Sep 17 00:00:00 2001 From: Jacob Lisi Date: Sun, 2 Feb 2020 14:42:17 -0500 Subject: [PATCH 29/29] fix rebase changelog Signed-off-by: Jacob Lisi --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b96b485627f..7160e572048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ * `--querier.query-store-after` has been added in it's place. * [FEATURE] Added user sub rings to distribute users to a subset of ingesters. #1947 * `--experimental.distributor.user-subring-size` -* [FEATURE] Added flag `experimental.ruler.enable-api` to enable the ruler api which implements the Prometheus API `/api/v1/rules` and `/api/v1/alerts` endpoints. #1999 +* [FEATURE] Added flag `-experimental.ruler.enable-api` to enable the ruler api which implements the Prometheus API `/api/v1/rules` and `/api/v1/alerts` endpoints under the configured `-http.prefix`. #1999 * [ENHANCEMENT] Experimental TSDB: Export TSDB Syncer metrics from Compactor component, they are prefixed with `cortex_compactor_`. #2023 * [ENHANCEMENT] Experimental TSDB: Added dedicated flag `-experimental.tsdb.bucket-store.tenant-sync-concurrency` to configure the maximum number of concurrent tenants for which blocks are synched. #2026 * [ENHANCEMENT] Experimental TSDB: Expose metrics for objstore operations (prefixed with `cortex__thanos_objstore_`, component being one of `ingester`, `querier` and `compactor`). #2027