Skip to content
This repository was archived by the owner on Aug 23, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1795 from grafana/metrics_expand
Browse files Browse the repository at this point in the history
implement /metrics/expand endpoint
  • Loading branch information
replay authored Aug 12, 2020
2 parents be6b494 + 4434106 commit 6c3706a
Show file tree
Hide file tree
Showing 6 changed files with 433 additions and 0 deletions.
70 changes: 70 additions & 0 deletions api/graphite.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/grafana/metrictank/idx/memory"
"github.com/grafana/metrictank/schema"
"github.com/tinylib/msgp/msgp"
"golang.org/x/sync/errgroup"
macaron "gopkg.in/macaron.v1"

"github.com/grafana/metrictank/api/middleware"
Expand Down Expand Up @@ -371,6 +372,75 @@ func (s *Server) metricsFind(ctx *middleware.Context, request models.GraphiteFin
}
}

func (s *Server) metricsExpand(ctx *middleware.Context, request models.GraphiteExpand) {
g, errGroupCtx := errgroup.WithContext(ctx.Req.Context())
results := make([]map[string]struct{}, len(request.Query))
for i, query := range request.Query {
i, query := i, query
g.Go(func() error {
series, err := s.findSeries(errGroupCtx, ctx.OrgId, []string{query}, 0)
if err != nil {
return err
}
results[i] = make(map[string]struct{})
for _, s := range series {
for _, n := range s.Series {
if request.LeavesOnly && !n.Leaf {
continue
}

results[i][n.Path] = struct{}{}
}
}
return nil
})
}
if err := g.Wait(); err != nil {
response.Write(ctx, response.WrapError(err))
return
}

// check to see if the request has been canceled, if so abort now.
select {
case <-ctx.Req.Context().Done():
//request canceled
response.Write(ctx, response.RequestCanceledErr)
return
default:
}

if request.GroupByExpr {
// keyed by query string
resultsGrouped := make(map[string][]string, len(results))
for resultIdx, queryResults := range results {
// query and results can be associated via their shared idx
query := request.Query[resultIdx]
resultsGrouped[query] = make([]string, 0, len(queryResults))
for queryResult := range queryResults {
resultsGrouped[query] = append(resultsGrouped[query], queryResult)
}
sort.StringSlice(resultsGrouped[query]).Sort()
}

response.Write(ctx, response.NewJson(200, resultsGrouped, request.Jsonp))
} else {
// all results in one flat list
resultsUngrouped := make(map[string]struct{})
for _, paths := range results {
for path := range paths {
resultsUngrouped[path] = struct{}{}
}
}
resultSlice := make([]string, 0, len(resultsUngrouped))
for result := range resultsUngrouped {
resultSlice = append(resultSlice, result)
}
sort.StringSlice(resultSlice).Sort()

response.Write(ctx, response.NewJson(200, resultSlice, request.Jsonp))
}
}

func (s *Server) listLocal(orgId uint32) []idx.Archive {

// query nodes have no data
Expand Down
7 changes: 7 additions & 0 deletions api/models/graphite.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@ type GraphiteFind struct {
Jsonp string `json:"jsonp" form:"jsonp"`
}

type GraphiteExpand struct {
Query []string `json:"query" form:"query" binding:"Required"`
GroupByExpr bool `json:"groupByExpr" form:"groupByExpr"`
LeavesOnly bool `json:"leavesOnly" form:"leavesOnly"`
Jsonp string `json:"jsonp" form:"jsonp"`
}

type MetricsDelete struct {
Query string `json:"query" form:"query" binding:"Required"`
}
Expand Down
218 changes: 218 additions & 0 deletions api/models/graphite_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6c3706a

Please sign in to comment.