github.com/go-graphite/carbonapi@v0.17.0/zipper/protocols/victoriametrics/find.go (about) 1 package victoriametrics 2 3 import ( 4 "context" 5 "fmt" 6 "net/url" 7 8 "github.com/ansel1/merry" 9 "go.uber.org/zap" 10 11 protov3 "github.com/go-graphite/protocol/carbonapi_v3_pb" 12 13 "github.com/go-graphite/carbonapi/zipper/types" 14 ) 15 16 func (c *VictoriaMetricsGroup) Find(ctx context.Context, request *protov3.MultiGlobRequest) (*protov3.MultiGlobResponse, *types.Stats, merry.Error) { 17 supportedFeatures, _ := c.featureSet.Load().(*vmSupportedFeatures) 18 if !supportedFeatures.SupportGraphiteFindAPI { 19 // VictoriaMetrics <1.41.0 doesn't support graphite find api, reverting back to prometheus code-path 20 return c.BackendServer.Find(ctx, request) 21 } 22 var r protov3.MultiGlobResponse 23 var e merry.Error 24 25 logger := c.logger.With( 26 zap.String("type", "find"), 27 zap.Strings("request", request.Metrics), 28 zap.Any("supported_features", supportedFeatures), 29 ) 30 stats := &types.Stats{} 31 var serverUrl string 32 if len(c.vmClusterTenantID) > 0 { 33 serverUrl = fmt.Sprintf("http://127.0.0.1/select/%s/graphite/metrics/find", c.vmClusterTenantID) 34 } else { 35 serverUrl = "http://127.0.0.1/metrics/find" 36 } 37 rewrite, _ := url.Parse(serverUrl) 38 39 r.Metrics = make([]protov3.GlobResponse, 0) 40 parser := c.parserPool.Get() 41 defer c.parserPool.Put(parser) 42 43 for _, query := range request.Metrics { 44 // Find only graphite metric name for first find 45 if query == "*" { 46 query = "*." 47 } 48 49 v := url.Values{ 50 "query": []string{query}, 51 } 52 53 rewrite.RawQuery = v.Encode() 54 stats.FindRequests++ 55 res, queryErr := c.httpQuery.DoQuery(ctx, logger, rewrite.RequestURI(), nil) 56 if queryErr != nil { 57 stats.FindErrors++ 58 if merry.Is(queryErr, types.ErrTimeoutExceeded) { 59 stats.Timeouts++ 60 stats.FindTimeouts++ 61 } 62 if e == nil { 63 e = merry.Wrap(queryErr).WithValue("query", query) 64 } else { 65 e = e.WithCause(queryErr) 66 } 67 continue 68 } 69 parsedJSON, err := parser.ParseBytes(res.Response) 70 if err != nil { 71 if e == nil { 72 e = merry.Wrap(err).WithValue("query", query) 73 } else { 74 e = e.WithCause(err) 75 } 76 continue 77 } 78 79 globs, err := parsedJSON.Array() 80 if err != nil { 81 if e == nil { 82 e = merry.Wrap(err).WithValue("query", query) 83 } else { 84 e = e.WithCause(err) 85 } 86 continue 87 } 88 89 stats.Servers = append(stats.Servers, res.Server) 90 matches := make([]protov3.GlobMatch, 0, len(globs)) 91 for _, m := range globs { 92 p := m.GetObject() 93 isLeaf := p.Get("leaf").GetInt() == 1 94 path := string(p.Get("id").GetStringBytes()) 95 if len(path) > 1 && path[len(path)-1] == '.' { 96 path = path[0 : len(path)-1] 97 } 98 matches = append(matches, protov3.GlobMatch{ 99 Path: path, 100 IsLeaf: isLeaf, 101 }) 102 } 103 r.Metrics = append(r.Metrics, protov3.GlobResponse{ 104 Name: query, 105 Matches: matches, 106 }) 107 } 108 109 if e != nil { 110 logger.Error("errors occurred while getting results", 111 zap.Any("errors", e), 112 ) 113 return &r, stats, e 114 } 115 return &r, stats, nil 116 } 117 118 func (c *VictoriaMetricsGroup) ProbeTLDs(ctx context.Context) ([]string, merry.Error) { 119 logger := c.logger.With(zap.String("function", "prober")) 120 req := &protov3.MultiGlobRequest{ 121 Metrics: []string{"*"}, 122 } 123 124 logger.Debug("doing request", 125 zap.Strings("request", req.Metrics), 126 ) 127 128 res, _, err := c.Find(ctx, req) 129 if err != nil { 130 return nil, err 131 } 132 133 var tlds []string 134 for _, m := range res.Metrics { 135 for _, v := range m.Matches { 136 tlds = append(tlds, v.Path) 137 } 138 } 139 140 logger.Debug("will return data", 141 zap.Strings("tlds", tlds), 142 ) 143 144 return tlds, nil 145 }