loki: send metadata requests through backend (#48063)

This commit is contained in:
Gábor Farkas 2022-04-25 13:16:14 +02:00 committed by GitHub
parent c5547123bc
commit d8a754c4a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 8 deletions

View File

@ -25,7 +25,7 @@ func newLokiAPI(client *http.Client, url string, log log.Logger) *LokiAPI {
return &LokiAPI{client: client, url: url, log: log}
}
func makeRequest(ctx context.Context, lokiDsUrl string, query lokiQuery) (*http.Request, error) {
func makeDataRequest(ctx context.Context, lokiDsUrl string, query lokiQuery) (*http.Request, error) {
qs := url.Values{}
qs.Set("query", query.Expr)
@ -135,8 +135,8 @@ func makeLokiError(body io.ReadCloser) error {
return fmt.Errorf("%v", errorMessage)
}
func (api *LokiAPI) Query(ctx context.Context, query lokiQuery) (*loghttp.QueryResponse, error) {
req, err := makeRequest(ctx, api.url, query)
func (api *LokiAPI) DataQuery(ctx context.Context, query lokiQuery) (*loghttp.QueryResponse, error) {
req, err := makeDataRequest(ctx, api.url, query)
if err != nil {
return nil, err
}
@ -164,3 +164,41 @@ func (api *LokiAPI) Query(ctx context.Context, query lokiQuery) (*loghttp.QueryR
return &response, nil
}
func makeRawRequest(ctx context.Context, lokiDsUrl string, resourceURL string) (*http.Request, error) {
lokiUrl, err := url.Parse(lokiDsUrl)
if err != nil {
return nil, err
}
url, err := lokiUrl.Parse(resourceURL)
if err != nil {
return nil, err
}
return http.NewRequestWithContext(ctx, "GET", url.String(), nil)
}
func (api *LokiAPI) RawQuery(ctx context.Context, resourceURL string) ([]byte, error) {
req, err := makeRawRequest(ctx, api.url, resourceURL)
if err != nil {
return nil, err
}
resp, err := api.client.Do(req)
if err != nil {
return nil, err
}
defer func() {
if err := resp.Body.Close(); err != nil {
api.log.Warn("Failed to close response body", "err", err)
}
}()
if resp.StatusCode/100 != 2 {
return nil, makeLokiError(resp.Body)
}
return io.ReadAll(resp.Body)
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"regexp"
"strings"
"sync"
"github.com/grafana/grafana-plugin-sdk-go/backend"
@ -25,8 +26,9 @@ type Service struct {
}
var (
_ backend.QueryDataHandler = (*Service)(nil)
_ backend.StreamHandler = (*Service)(nil)
_ backend.QueryDataHandler = (*Service)(nil)
_ backend.StreamHandler = (*Service)(nil)
_ backend.CallResourceHandler = (*Service)(nil)
)
func ProvideService(httpClientProvider httpclient.Provider, tracer tracing.Tracer) *Service {
@ -89,6 +91,40 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
}
}
func (s *Service) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
url := req.URL
// a very basic is-this-url-valid check
if req.Method != "GET" {
return fmt.Errorf("invalid resource method: %s", req.Method)
}
if (!strings.HasPrefix(url, "/loki/api/v1/label?")) &&
(!strings.HasPrefix(url, "/loki/api/v1/label/")) && // the `/label/$label_name/values` form
(!strings.HasPrefix(url, "/loki/api/v1/series?")) {
return fmt.Errorf("invalid resource URL: %s", url)
}
dsInfo, err := s.getDSInfo(req.PluginContext)
if err != nil {
return err
}
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, s.plog)
bytes, err := api.RawQuery(ctx, url)
if err != nil {
return err
}
return sender.Send(&backend.CallResourceResponse{
Status: http.StatusOK,
Headers: map[string][]string{
"content-type": {"application/json"},
},
Body: bytes,
})
}
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
result := backend.NewQueryDataResponse()
@ -129,7 +165,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
// we extracted this part of the functionality to make it easy to unit-test it
func runQuery(ctx context.Context, api *LokiAPI, query *lokiQuery) (data.Frames, error) {
value, err := api.Query(ctx, *query)
value, err := api.DataQuery(ctx, *query)
if err != nil {
return data.Frames{}, err
}

View File

@ -439,8 +439,13 @@ export class LokiDatasource
}
async metadataRequest(url: string, params?: Record<string, string | number>) {
const res = await lastValueFrom(this._request(url, params, { hideFromInspector: true }));
return res.data.data || res.data.values || [];
if (config.featureToggles.lokiBackendMode) {
const res = await this.getResource(url, params);
return res.data || res.values || [];
} else {
const res = await lastValueFrom(this._request(url, params, { hideFromInspector: true }));
return res.data.data || res.data.values || [];
}
}
async metricFindQuery(query: string) {