Skip to content

Commit

Permalink
pkg/query/api/v1: initial implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Sergiusz Urbaniak <sergiusz.urbaniak@gmail.com>
  • Loading branch information
s-urbaniak committed Apr 27, 2020
1 parent 71fb105 commit e8bc4de
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 9 deletions.
2 changes: 1 addition & 1 deletion cmd/thanos/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ func runQuery(
ins := extpromhttp.NewInstrumentationMiddleware(reg)
ui.NewQueryUI(logger, reg, stores, flagsMap).Register(router.WithPrefix(webRoutePrefix), ins)

api := v1.NewAPI(logger, reg, engine, queryableCreator, enableAutodownsampling, enablePartialResponse, queryReplicaLabels, instantDefaultMaxSourceResolution, nil)
api := v1.NewAPI(logger, reg, engine, queryableCreator, enableAutodownsampling, enablePartialResponse, queryReplicaLabels, instantDefaultMaxSourceResolution, query.NewRulesRetriever(proxy))

api.Register(router.WithPrefix(path.Join(webRoutePrefix, "/api/v1")), tracer, logger, ins)

Expand Down
54 changes: 51 additions & 3 deletions pkg/query/api/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"math"
"net/http"
"strconv"
"strings"
"time"

"github.com/NYTimes/gziphandler"
Expand All @@ -38,11 +39,11 @@ import (
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/pkg/timestamp"
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/rules"
"github.com/prometheus/prometheus/storage"
extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http"
"github.com/thanos-io/thanos/pkg/query"
"github.com/thanos-io/thanos/pkg/runutil"
"github.com/thanos-io/thanos/pkg/store/storepb"
"github.com/thanos-io/thanos/pkg/tracing"
)

Expand Down Expand Up @@ -98,7 +99,7 @@ func SetCORS(w http.ResponseWriter) {
type ApiFunc func(r *http.Request) (interface{}, []error, *ApiError)

type rulesRetriever interface {
RuleGroups() ([]*rules.Group, error)
RuleGroups(context.Context) ([]*storepb.RuleGroup, storage.Warnings, error)
}

// API can register a set of endpoints in a router and handle
Expand Down Expand Up @@ -638,5 +639,52 @@ func (api *API) labelNames(r *http.Request) (interface{}, []error, *ApiError) {
}

func (api *API) rules(r *http.Request) (interface{}, []error, *ApiError) {
panic("implement me")
var (
res = &storepb.RuleGroups{}
typeParam = strings.ToLower(r.URL.Query().Get("type"))
)

if typeParam != "" && typeParam != "alert" && typeParam != "record" {
return nil, nil, &ApiError{errorBadData, errors.Errorf("invalid query parameter type='%v'", typeParam)}
}

returnAlerts := typeParam == "" || typeParam == "alert"
returnRecording := typeParam == "" || typeParam == "record"

groups, warnings, err := api.rulesRetriever.RuleGroups(r.Context())
if err != nil {
return nil, nil, &ApiError{ErrorInternal, fmt.Errorf("error retrieving rules: %v", err)}
}

for _, grp := range groups {
apiRuleGroup := &storepb.RuleGroup{
Name: grp.Name,
File: grp.File,
Interval: grp.Interval,
EvaluationDurationSeconds: grp.EvaluationDurationSeconds,
LastEvaluation: grp.LastEvaluation,
DeprecatedPartialResponseStrategy: grp.DeprecatedPartialResponseStrategy,
PartialResponseStrategy: grp.PartialResponseStrategy,
}

for _, r := range grp.Rules {
switch {
case r.GetAlert() != nil:
if !returnAlerts {
break
}
apiRuleGroup.Rules = append(apiRuleGroup.Rules, r)
case r.GetRecording() != nil:
if !returnRecording {
break
}
apiRuleGroup.Rules = append(apiRuleGroup.Rules, r)
default:
return nil, nil, &ApiError{ErrorInternal, fmt.Errorf("rule %v: unsupported", r)}
}
}
res.Groups = append(res.Groups, apiRuleGroup)
}

return res, warnings, nil
}
49 changes: 44 additions & 5 deletions pkg/query/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,59 @@
package query

import (
"github.com/prometheus/prometheus/rules"
"context"

"github.com/pkg/errors"
"github.com/prometheus/prometheus/storage"
"github.com/thanos-io/thanos/pkg/store/storepb"
)

func NewRulesRetriever(rs storepb.RulesServer) *rulesRetriever {
return &rulesRetriever{
rulesServer: rs,
proxy: rs,
}
}

type rulesRetriever struct {
rulesServer storepb.RulesServer
proxy storepb.RulesServer
}

func (rr *rulesRetriever) RuleGroups(ctx context.Context) ([]*storepb.RuleGroup, storage.Warnings, error) {
resp := &rulesServer{ctx: ctx}

if err := rr.proxy.Rules(&storepb.RulesRequest{
PartialResponseStrategy: storepb.PartialResponseStrategy_ABORT,
}, resp); err != nil {
return nil, nil, errors.Wrap(err, "proxy RuleGroups()")
}

return resp.groups, resp.warnings, nil
}

type rulesServer struct {
// This field just exist to pseudo-implement the unused methods of the interface.
storepb.Rules_RulesServer
ctx context.Context

warnings []error
groups []*storepb.RuleGroup
}

func (srv *rulesServer) Send(res *storepb.RulesResponse) error {
if res.GetWarning() != "" {
srv.warnings = append(srv.warnings, errors.New(res.GetWarning()))
return nil
}

if res.GetGroup() == nil {
return errors.New("no group")
}

srv.groups = append(srv.groups, res.GetGroup())
return nil

}

func (rr *rulesRetriever) RuleGroups() ([]*rules.Group, error) {
return nil, nil
func (srv *rulesServer) Context() context.Context {
return srv.ctx
}

0 comments on commit e8bc4de

Please sign in to comment.