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  }