Graphite: Backend tag values autocomplete endpoint (#110773)

* Add lint rules

* Backend decoupling

- Add standalone files
- Add graphite query type
- Add logger to Service
- Create logger in the ProvideService method
- Use a pointer for the HTTP client provider
- Update logger usage everywhere
- Update tracer type
- Replace simplejson with json
- Add dummy CallResource and CheckHealth methods
- Update tests

* Update ConfigEditor imports

* Update types imports

* Update datasource

- Switch to using semver package
- Update imports

* Update store imports

* Update helper imports and notification creation

* Update context import

* Update version numbers and logic

* Copy array_move from core

* Test updates

* Add required files and update plugin.json

* Update core references and packages

* Remove commented code

* Update wire

* Lint

* Fix import

* Copy null type

* More lint

* Update snapshot

* Refactor backend

- Split query logic into separate file
- Move utils to separate file

* Add health-check logic

- Support backend healthcheck if the FF is enabled

* Remove query import support as unneeded

* Add test

* Add util function for decoding responses

* Add events types

* Add resource handler

* Add events handler and generic resource req handler

* Tests

* Update frontend

- Add types
- Update events function to support backend requests

* Lint and typing

* Lint

* Add metrics find endpoint

- Add types
- Add generic response parser
- Add endpoint
- Tests

* Update FE functoin to use backend endpoint

* Lint

* Simplify request

* Update test

* Metrics expand type

* Extract shared logic and add metric expand endpoint

* Update tests

* Call metric expand from backend

* Rename type for clarity

* Add get resource req handler

* Refactor doGraphiteRequest, parseResponse

Update tests

* Migrate functions endpoint to backend

* Support tags autocomplete in backend

- Add tests
- Add types
- Remove unneeded comments

* Support tag values autocomplete

- Remove unused frontend endpoints
- Add types
- Update tests

* Add tests

* Review

* Review

* Fix packages

* Format

* Fix merge issues

* Review

* Fix undefined values

* Extract request creation

- Add method for create requests generically with tests
- Replace usage in query method
- Update usages in resource handlers
- Update tests
- Update types

* Lint
This commit is contained in:
Andreas Christou
2025-09-15 11:35:29 +01:00
committed by GitHub
parent f392bb6f94
commit df2bb6be0a
7 changed files with 243 additions and 109 deletions
+51 -17
View File
@@ -26,6 +26,8 @@ func (s *Service) newResourceMux() *http.ServeMux {
mux.HandleFunc("/metrics/expand", handleResourceReq(s.handleMetricsExpand, s))
mux.HandleFunc("/functions", handleResourceReq(s.handleFunctions, s))
mux.HandleFunc("/tags/autoComplete/tags", handleResourceReq(s.handleTagsAutocomplete, s))
mux.HandleFunc("/tags/autoComplete/values", handleResourceReq(s.handleTagValuesAutocomplete, s))
return mux
}
@@ -87,12 +89,12 @@ func handleResourceReq[T any](handlerFn resourceHandler[T], s *Service) func(rw
}
func (s *Service) handleEvents(ctx context.Context, dsInfo *datasourceInfo, eventsRequestJson *GraphiteEventsRequest) ([]byte, int, error) {
queryParams := map[string]string{
"from": eventsRequestJson.From,
"until": eventsRequestJson.Until,
queryParams := map[string][]string{
"from": {eventsRequestJson.From},
"until": {eventsRequestJson.Until},
}
if eventsRequestJson.Tags != "" {
queryParams["tags"] = eventsRequestJson.Tags
queryParams["tags"] = []string{eventsRequestJson.Tags}
}
req, err := s.createRequest(ctx, dsInfo, URLParams{
@@ -128,12 +130,12 @@ func (s *Service) handleMetricsFind(ctx context.Context, dsInfo *datasourceInfo,
data := url.Values{}
data.Set("query", metricsFindRequestJson.Query)
queryParams := map[string]string{}
queryParams := map[string][]string{}
if metricsFindRequestJson.From != "" {
queryParams["from"] = metricsFindRequestJson.From
queryParams["from"] = []string{metricsFindRequestJson.From}
}
if metricsFindRequestJson.Until != "" {
queryParams["until"] = metricsFindRequestJson.Until
queryParams["until"] = []string{metricsFindRequestJson.Until}
}
req, err := s.createRequest(ctx, dsInfo, URLParams{
@@ -165,14 +167,14 @@ func (s *Service) handleMetricsExpand(ctx context.Context, dsInfo *datasourceInf
return nil, http.StatusBadRequest, fmt.Errorf("query is required")
}
queryParams := map[string]string{
"query": metricsExpandRequestJson.Query,
queryParams := map[string][]string{
"query": {metricsExpandRequestJson.Query},
}
if metricsExpandRequestJson.From != "" {
queryParams["from"] = metricsExpandRequestJson.From
queryParams["from"] = []string{metricsExpandRequestJson.From}
}
if metricsExpandRequestJson.Until != "" {
queryParams["until"] = metricsExpandRequestJson.Until
queryParams["until"] = []string{metricsExpandRequestJson.Until}
}
req, err := s.createRequest(ctx, dsInfo, URLParams{
@@ -205,11 +207,11 @@ func (s *Service) handleMetricsExpand(ctx context.Context, dsInfo *datasourceInf
}
func (s *Service) handleTagsAutocomplete(ctx context.Context, dsInfo *datasourceInfo, tagsAutocompleteRequestJson *GraphiteTagsRequest) ([]byte, int, error) {
queryParams := map[string]string{
"from": tagsAutocompleteRequestJson.From,
"until": tagsAutocompleteRequestJson.Until,
"limit": fmt.Sprintf("%d", tagsAutocompleteRequestJson.Limit),
"tagPrefix": tagsAutocompleteRequestJson.TagPrefix,
queryParams := map[string][]string{
"from": {tagsAutocompleteRequestJson.From},
"until": {tagsAutocompleteRequestJson.Until},
"limit": {fmt.Sprintf("%d", tagsAutocompleteRequestJson.Limit)},
"tagPrefix": {tagsAutocompleteRequestJson.TagPrefix},
}
req, err := s.createRequest(ctx, dsInfo, URLParams{
SubPath: "tags/autoComplete/tags",
@@ -217,7 +219,7 @@ func (s *Service) handleTagsAutocomplete(ctx context.Context, dsInfo *datasource
QueryParams: queryParams,
})
if err != nil {
return nil, http.StatusInternalServerError, fmt.Errorf("failed to create metrics expand request %v", err)
return nil, http.StatusInternalServerError, fmt.Errorf("failed to create tags autocomplete request %v", err)
}
tags, _, statusCode, err := doGraphiteRequest[[]string](ctx, dsInfo, s.logger, req, false)
@@ -233,6 +235,38 @@ func (s *Service) handleTagsAutocomplete(ctx context.Context, dsInfo *datasource
return tagsResponse, statusCode, nil
}
func (s *Service) handleTagValuesAutocomplete(ctx context.Context, dsInfo *datasourceInfo, tagValuesAutocompleteRequestJson *GraphiteTagValuesRequest) ([]byte, int, error) {
queryParams := map[string][]string{
"expr": tagValuesAutocompleteRequestJson.Expr,
"tag": {tagValuesAutocompleteRequestJson.Tag},
"from": {tagValuesAutocompleteRequestJson.From},
"until": {tagValuesAutocompleteRequestJson.Until},
"limit": {fmt.Sprintf("%d", tagValuesAutocompleteRequestJson.Limit)},
"valuePrefix": {tagValuesAutocompleteRequestJson.ValuePrefix},
}
req, err := s.createRequest(ctx, dsInfo, URLParams{
SubPath: "tags/autoComplete/values",
Method: http.MethodGet,
QueryParams: queryParams,
})
if err != nil {
return nil, http.StatusInternalServerError, fmt.Errorf("failed to create tag values autocomplete request %v", err)
}
tagValues, _, statusCode, err := doGraphiteRequest[[]string](ctx, dsInfo, s.logger, req, false)
if err != nil {
return nil, statusCode, fmt.Errorf("tag values autocomplete request failed: %v", err)
}
tagValuesResponse, err := json.Marshal(tagValues)
if err != nil {
return nil, http.StatusInternalServerError, fmt.Errorf("failed to marshal tag values autocomplete response: %s", err)
}
return tagValuesResponse, statusCode, nil
}
func (s *Service) handleFunctions(ctx context.Context, dsInfo *datasourceInfo, _ *any) ([]byte, int, error) {
req, err := s.createRequest(ctx, dsInfo, URLParams{
SubPath: "functions",