Prometheus: Remove middleware for custom headers (#51518)

mob/ue-timezone
Andrej Ocenas 3 years ago committed by GitHub
parent 60454192b7
commit 2372501368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      pkg/tsdb/prometheus/buffered/time_series_query.go
  2. 55
      pkg/tsdb/prometheus/buffered/time_series_query_test.go
  3. 24
      pkg/tsdb/prometheus/middleware/req_headers.go

@ -13,12 +13,10 @@ import (
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
sdkHTTPClient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
"github.com/grafana/grafana/pkg/tsdb/prometheus/middleware"
"github.com/grafana/grafana/pkg/tsdb/prometheus/utils"
"github.com/grafana/grafana/pkg/util/maputil"
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
@ -94,10 +92,6 @@ func New(roundTripper http.RoundTripper, tracer tracing.Tracer, settings backend
}
func (b *Buffered) ExecuteTimeSeriesQuery(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// Add headers from the request to context so they are added later on by a context middleware. This is because
// prom client does not allow us to do this directly.
ctxWithHeaders := sdkHTTPClient.WithContextualMiddleware(ctx, middleware.ReqHeadersMiddleware(req.Headers))
queries, err := b.parseTimeSeriesQuery(req)
if err != nil {
result := backend.QueryDataResponse{
@ -106,7 +100,7 @@ func (b *Buffered) ExecuteTimeSeriesQuery(ctx context.Context, req *backend.Quer
return &result, fmt.Errorf("error parsing time series query: %v", err)
}
return b.runQueries(ctxWithHeaders, queries)
return b.runQueries(ctx, queries)
}
func (b *Buffered) runQueries(ctx context.Context, queries []*PrometheusQuery) (*backend.QueryDataResponse, error) {

@ -1,17 +1,13 @@
package buffered
import (
"context"
"math"
"net/http"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/grafana/grafana-plugin-sdk-go/backend"
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/infra/log/logtest"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
apiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
p "github.com/prometheus/common/model"
@ -20,57 +16,6 @@ import (
var now = time.Now()
type FakeRoundTripper struct {
Req *http.Request
}
func (frt *FakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
frt.Req = req
return &http.Response{}, nil
}
func FakeMiddleware(rt *FakeRoundTripper) sdkhttpclient.Middleware {
return sdkhttpclient.NamedMiddlewareFunc("fake", func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper {
return rt
})
}
func TestPrometheus_ExecuteTimeSeriesQuery(t *testing.T) {
t.Run("adding req headers", func(t *testing.T) {
// This makes sure we add req headers from the front end request to the request to prometheus. We do that
// through contextual middleware so this setup is a bit complex and the test itself goes a bit too much into
// internals.
// This ends the trip and saves the request on the instance so we can inspect it.
rt := &FakeRoundTripper{}
// DefaultMiddlewares also contain contextual middleware which is the one we need to use.
middlewares := sdkhttpclient.DefaultMiddlewares()
middlewares = append(middlewares, FakeMiddleware(rt))
// Setup http client in at least similar way to how grafana provides it to the service
provider := sdkhttpclient.NewProvider(sdkhttpclient.ProviderOptions{Middlewares: sdkhttpclient.DefaultMiddlewares()})
roundTripper, err := provider.GetTransport(sdkhttpclient.Options{
Middlewares: middlewares,
})
require.NoError(t, err)
buffered, err := New(roundTripper, nil, backend.DataSourceInstanceSettings{JSONData: []byte("{}")}, &logtest.Fake{})
require.NoError(t, err)
_, err = buffered.ExecuteTimeSeriesQuery(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{},
// This header should end up in the outgoing request to prometheus
Headers: map[string]string{"foo": "bar"},
Queries: []backend.DataQuery{{
JSON: []byte(`{"expr": "metric{label=\"test\"}", "rangeQuery": true}`),
}},
})
require.NoError(t, err)
require.NotNil(t, rt.Req)
require.Equal(t, http.Header{"Content-Type": []string{"application/x-www-form-urlencoded"}, "foo": []string{"bar"}}, rt.Req.Header)
})
}
func TestPrometheus_timeSeriesQuery_formatLegend(t *testing.T) {
t.Run("converting metric name", func(t *testing.T) {
metric := map[p.LabelName]p.LabelValue{

@ -1,24 +0,0 @@
package middleware
import (
"net/http"
sdkHTTPClient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
)
// ReqHeadersMiddleware is used so that we can pass req headers through the prometheus go client as it does not allow
// access to the request directly. Should be used together with WithContextualMiddleware so that it is attached to
// the context of each request with its unique headers.
func ReqHeadersMiddleware(headers map[string]string) sdkHTTPClient.Middleware {
return sdkHTTPClient.NamedMiddlewareFunc("prometheus-req-headers-middleware", func(opts sdkHTTPClient.Options, next http.RoundTripper) http.RoundTripper {
return sdkHTTPClient.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
for k, v := range headers {
// As custom headers middleware is before contextual we may overwrite custom headers here with those
// that came with the request which probably makes sense.
req.Header[k] = []string{v}
}
return next.RoundTrip(req)
})
})
}
Loading…
Cancel
Save