mirror of https://github.com/grafana/loki
Support protobuf `QueryRequest` in querier. (#10858)
**What this PR does / why we need it**:
This is one step to support pure protobuf encoding without `httpgrpc`.
It is only on the scheduler and is fully backwards compatible.
**Which issue(s) this PR fixes**:
This is a sub change of https://github.com/grafana/loki/pull/10688
**Checklist**
- [ ] Reviewed the
[`CONTRIBUTING.md`](https://github.com/grafana/loki/blob/main/CONTRIBUTING.md)
guide (**required**)
- [ ] Documentation added
- [x] Tests updated
- [ ] `CHANGELOG.md` updated
- [ ] If the change is worth mentioning in the release notes, add
`add-to-release-notes` label
- [ ] Changes that require user attention or interaction to upgrade are
documented in `docs/sources/setup/upgrade/_index.md`
- [ ] For Helm chart changes bump the Helm chart version in
`production/helm/loki/Chart.yaml` and update
`production/helm/loki/CHANGELOG.md` and
`production/helm/loki/README.md`. [Example
PR](d10549e3ec)
---------
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Co-authored-by: Kaviraj <kavirajkanagaraj@gmail.com>
Co-authored-by: Danny Kopping <dannykopping@gmail.com>
pull/10955/head^2
parent
6b6e5b8ee6
commit
9fcc42dc48
@ -0,0 +1,105 @@ |
||||
package querier |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"net/http" |
||||
|
||||
"github.com/opentracing/opentracing-go" |
||||
|
||||
"github.com/grafana/loki/pkg/loghttp" |
||||
"github.com/grafana/loki/pkg/logproto" |
||||
"github.com/grafana/loki/pkg/querier/queryrange" |
||||
"github.com/grafana/loki/pkg/querier/queryrange/queryrangebase" |
||||
) |
||||
|
||||
type Handler struct { |
||||
api *QuerierAPI |
||||
} |
||||
|
||||
func NewQuerierHandler(api *QuerierAPI) *Handler { |
||||
return &Handler{ |
||||
api: api, |
||||
} |
||||
} |
||||
|
||||
func (h *Handler) Do(ctx context.Context, req queryrangebase.Request) (queryrangebase.Response, error) { |
||||
span, ctx := opentracing.StartSpanFromContext(ctx, "queryHandler") |
||||
defer span.Finish() |
||||
|
||||
switch concrete := req.(type) { |
||||
case *queryrange.LokiRequest: |
||||
res, err := h.api.RangeQueryHandler(ctx, concrete) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
params, err := queryrange.ParamsFromRequest(req) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return queryrange.ResultToResponse(res, params) |
||||
case *queryrange.LokiInstantRequest: |
||||
res, err := h.api.InstantQueryHandler(ctx, concrete) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
params, err := queryrange.ParamsFromRequest(req) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return queryrange.ResultToResponse(res, params) |
||||
case *queryrange.LokiSeriesRequest: |
||||
request := &logproto.SeriesRequest{ |
||||
Start: concrete.StartTs, |
||||
End: concrete.EndTs, |
||||
Groups: concrete.Match, |
||||
Shards: concrete.Shards, |
||||
} |
||||
result, statResult, err := h.api.SeriesHandler(ctx, request) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &queryrange.LokiSeriesResponse{ |
||||
Status: "success", |
||||
Version: uint32(loghttp.VersionV1), |
||||
Data: result.Series, |
||||
Statistics: statResult, |
||||
}, nil |
||||
case *queryrange.LabelRequest: |
||||
res, err := h.api.LabelHandler(ctx, &concrete.LabelRequest) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &queryrange.LokiLabelNamesResponse{ |
||||
Status: "success", |
||||
Version: uint32(loghttp.VersionV1), |
||||
Data: res.Values, |
||||
}, nil |
||||
case *logproto.IndexStatsRequest: |
||||
request := loghttp.NewRangeQueryWithDefaults() |
||||
request.Start = concrete.From.Time() |
||||
request.End = concrete.Through.Time() |
||||
request.Query = concrete.GetQuery() |
||||
request.UpdateStep() |
||||
|
||||
result, err := h.api.IndexStatsHandler(ctx, request) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &queryrange.IndexStatsResponse{Response: result}, nil |
||||
case *logproto.VolumeRequest: |
||||
return h.api.VolumeHandler(ctx, concrete) |
||||
default: |
||||
return nil, fmt.Errorf("unsupported query type %T", req) |
||||
} |
||||
} |
||||
|
||||
func NewQuerierHTTPHandler(h *Handler) http.Handler { |
||||
return queryrange.NewSerializeHTTPHandler(h, queryrange.DefaultCodec) |
||||
} |
||||
@ -0,0 +1,76 @@ |
||||
package queryrange |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"github.com/opentracing/opentracing-go" |
||||
|
||||
"github.com/grafana/loki/pkg/loghttp" |
||||
"github.com/grafana/loki/pkg/querier/queryrange/queryrangebase" |
||||
serverutil "github.com/grafana/loki/pkg/util/server" |
||||
) |
||||
|
||||
type serializeRoundTripper struct { |
||||
codec queryrangebase.Codec |
||||
next queryrangebase.Handler |
||||
} |
||||
|
||||
func NewSerializeRoundTripper(next queryrangebase.Handler, codec queryrangebase.Codec) http.RoundTripper { |
||||
return &serializeRoundTripper{ |
||||
next: next, |
||||
codec: codec, |
||||
} |
||||
} |
||||
|
||||
func (rt *serializeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { |
||||
ctx := r.Context() |
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "limitedRoundTripper.do") |
||||
defer sp.Finish() |
||||
|
||||
request, err := rt.codec.DecodeRequest(ctx, r, nil) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
response, err := rt.next.Do(ctx, request) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return rt.codec.EncodeResponse(ctx, r, response) |
||||
} |
||||
|
||||
type serializeHTTPHandler struct { |
||||
codec queryrangebase.Codec |
||||
next queryrangebase.Handler |
||||
} |
||||
|
||||
func NewSerializeHTTPHandler(next queryrangebase.Handler, codec queryrangebase.Codec) http.Handler { |
||||
return &serializeHTTPHandler{ |
||||
next: next, |
||||
codec: codec, |
||||
} |
||||
} |
||||
|
||||
func (rt *serializeHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
||||
ctx := r.Context() |
||||
sp, ctx := opentracing.StartSpanFromContext(ctx, "serializeHTTPHandler.ServerHTTP") |
||||
defer sp.Finish() |
||||
|
||||
request, err := rt.codec.DecodeRequest(ctx, r, nil) |
||||
if err != nil { |
||||
serverutil.WriteError(err, w) |
||||
return |
||||
} |
||||
|
||||
response, err := rt.next.Do(ctx, request) |
||||
if err != nil { |
||||
serverutil.WriteError(err, w) |
||||
return |
||||
} |
||||
|
||||
version := loghttp.GetVersion(r.RequestURI) |
||||
if err := encodeResponseJSONTo(version, response, w); err != nil { |
||||
serverutil.WriteError(err, w) |
||||
} |
||||
} |
||||
@ -0,0 +1,132 @@ |
||||
package queryrange |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"net/http" |
||||
"net/http/httptest" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/grafana/dskit/user" |
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/grafana/loki/pkg/loghttp" |
||||
"github.com/grafana/loki/pkg/logproto" |
||||
"github.com/grafana/loki/pkg/logqlmodel" |
||||
"github.com/grafana/loki/pkg/querier/queryrange/queryrangebase" |
||||
) |
||||
|
||||
func TestResponseFormat(t *testing.T) { |
||||
for _, tc := range []struct { |
||||
url string |
||||
accept string |
||||
response queryrangebase.Response |
||||
expectedCode int |
||||
expectedRespone string |
||||
}{ |
||||
{ |
||||
url: "/api/prom/query", |
||||
response: &LokiResponse{ |
||||
Direction: logproto.BACKWARD, |
||||
Limit: 200, |
||||
Data: LokiData{ |
||||
ResultType: loghttp.ResultTypeStream, |
||||
Result: logqlmodel.Streams{ |
||||
logproto.Stream{ |
||||
Entries: []logproto.Entry{ |
||||
{ |
||||
Timestamp: time.Unix(0, 123456789012345).UTC(), |
||||
Line: "super line", |
||||
}, |
||||
}, |
||||
Labels: `{foo="bar"}`, |
||||
}, |
||||
}, |
||||
}, |
||||
Status: "success", |
||||
Statistics: statsResult, |
||||
}, |
||||
expectedCode: http.StatusOK, |
||||
expectedRespone: `{ |
||||
` + statsResultString + ` |
||||
"streams": [ |
||||
{ |
||||
"labels": "{foo=\"bar\"}", |
||||
"entries": [ |
||||
{ |
||||
"line": "super line", |
||||
"ts": "1970-01-02T10:17:36.789012345Z" |
||||
} |
||||
] |
||||
} |
||||
] |
||||
}`, |
||||
}, |
||||
{ |
||||
url: "/loki/api/v1/query_range", |
||||
response: &LokiResponse{ |
||||
Direction: logproto.BACKWARD, |
||||
Limit: 200, |
||||
Data: LokiData{ |
||||
ResultType: loghttp.ResultTypeStream, |
||||
Result: logqlmodel.Streams{ |
||||
logproto.Stream{ |
||||
Entries: []logproto.Entry{ |
||||
{ |
||||
Timestamp: time.Unix(0, 123456789012345).UTC(), |
||||
Line: "super line", |
||||
}, |
||||
}, |
||||
Labels: `{foo="bar"}`, |
||||
}, |
||||
}, |
||||
}, |
||||
Status: "success", |
||||
Statistics: statsResult, |
||||
}, |
||||
expectedCode: http.StatusOK, |
||||
expectedRespone: `{ |
||||
"status": "success", |
||||
"data": { |
||||
"resultType": "streams", |
||||
` + statsResultString + ` |
||||
"result": [{ |
||||
"stream": {"foo": "bar"}, |
||||
"values": [ |
||||
["123456789012345", "super line"] |
||||
] |
||||
}] |
||||
} |
||||
}`, |
||||
}, |
||||
{ |
||||
url: "/loki/wrong/path", |
||||
response: nil, |
||||
expectedCode: http.StatusNotFound, |
||||
expectedRespone: "unknown request path: /loki/wrong/path\n", |
||||
}, |
||||
} { |
||||
t.Run(fmt.Sprintf("%s returns the expected format", tc.url), func(t *testing.T) { |
||||
handler := queryrangebase.HandlerFunc(func(ctx context.Context, r queryrangebase.Request) (queryrangebase.Response, error) { |
||||
return tc.response, nil |
||||
}) |
||||
httpHandler := NewSerializeHTTPHandler(handler, DefaultCodec) |
||||
|
||||
w := httptest.NewRecorder() |
||||
req := httptest.NewRequest(http.MethodGet, tc.url+ |
||||
"?start=0"+ |
||||
"&end=1"+ |
||||
"&query=%7Bfoo%3D%22bar%22%7D", nil) |
||||
req = req.WithContext(user.InjectOrgID(context.Background(), "1")) |
||||
httpHandler.ServeHTTP(w, req) |
||||
|
||||
require.Equalf(t, tc.expectedCode, w.Code, "unexpected response: %s", w.Body.String()) |
||||
if tc.expectedCode/100 == 2 { |
||||
require.JSONEq(t, tc.expectedRespone, w.Body.String()) |
||||
} else { |
||||
require.Equal(t, tc.expectedRespone, w.Body.String()) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
@ -1,247 +1,239 @@ |
||||
package querier |
||||
|
||||
import ( |
||||
"net/http" |
||||
"net/http/httptest" |
||||
//"context"
|
||||
//"net/http"
|
||||
//"net/http/httptest"
|
||||
"testing" |
||||
/* |
||||
"github.com/gorilla/mux" |
||||
"github.com/grafana/dskit/middleware" |
||||
"github.com/grafana/dskit/services" |
||||
"github.com/stretchr/testify/assert" |
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/gorilla/mux" |
||||
"github.com/grafana/dskit/middleware" |
||||
"github.com/grafana/dskit/services" |
||||
"github.com/stretchr/testify/assert" |
||||
"github.com/stretchr/testify/require" |
||||
|
||||
querier_worker "github.com/grafana/loki/pkg/querier/worker" |
||||
) |
||||
"github.com/grafana/loki/pkg/querier/queryrange/queryrangebase" |
||||
querier_worker "github.com/grafana/loki/pkg/querier/worker" |
||||
*/) |
||||
|
||||
func Test_InitQuerierService(t *testing.T) { |
||||
var mockQueryHandlers = map[string]http.Handler{ |
||||
"/loki/api/v1/query": http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { |
||||
_, err := res.Write([]byte(`{"handler": "test"}`)) |
||||
res.Header().Del("Content-Type") |
||||
require.NoError(t, err) |
||||
}), |
||||
} |
||||
|
||||
var alwaysExternalHandlers = map[string]http.Handler{ |
||||
"/loki/api/v1/tail": http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { |
||||
_, err := res.Write([]byte("test tail handler")) |
||||
require.NoError(t, err) |
||||
}), |
||||
} |
||||
|
||||
testContext := func(config WorkerServiceConfig, authMiddleware middleware.Interface) (*mux.Router, services.Service) { |
||||
externalRouter := mux.NewRouter() |
||||
|
||||
if authMiddleware == nil { |
||||
authMiddleware = middleware.Identity |
||||
} |
||||
|
||||
pathPrefix := "" |
||||
querierWorkerService, err := InitWorkerService( |
||||
config, |
||||
nil, |
||||
pathPrefix, |
||||
mockQueryHandlers, |
||||
alwaysExternalHandlers, |
||||
externalRouter, |
||||
http.HandlerFunc(externalRouter.ServeHTTP), |
||||
authMiddleware, |
||||
) |
||||
require.NoError(t, err) |
||||
|
||||
return externalRouter, querierWorkerService |
||||
} |
||||
|
||||
t.Run("when querier is configured to run standalone, without a query frontend", func(t *testing.T) { |
||||
t.Run("register the internal query handlers externally", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
|
||||
externalRouter, _ := testContext(config, nil) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, `{"handler": "test"}`, recorder.Body.String()) |
||||
|
||||
// Tail endpoints always external
|
||||
recorder = httptest.NewRecorder() |
||||
request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, "test tail handler", recorder.Body.String()) |
||||
}) |
||||
|
||||
t.Run("wrap external handler with auth middleware", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
// TODO: use in modules test
|
||||
/* |
||||
var alwaysExternalHandlers = map[string]http.Handler{ |
||||
"/loki/api/v1/tail": http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { |
||||
_, err := res.Write([]byte("test tail handler")) |
||||
require.NoError(t, err) |
||||
}), |
||||
} |
||||
|
||||
requestedAuthenticated := false |
||||
mockAuthMiddleware := middleware.Func(func(next http.Handler) http.Handler { |
||||
requestedAuthenticated = true |
||||
return next |
||||
}) |
||||
|
||||
externalRouter, _ := testContext(config, mockAuthMiddleware) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.True(t, requestedAuthenticated) |
||||
handler := queryrangebase.HandlerFunc(func(ctx context.Context, r queryrangebase.Request) (queryrangebase.Response, error) { |
||||
return nil, nil |
||||
}) |
||||
|
||||
t.Run("wrap external handler with response json middleware", func(t *testing.T) { |
||||
// note: this test only assures that the content type of the response is
|
||||
// set if the handler function does not override it, which happens in the
|
||||
// actual implementation, see
|
||||
// https://github.com/grafana/loki/blob/34a012adcfade43291de3a7670f53679ea06aefe/pkg/lokifrontend/frontend/transport/handler.go#L136-L139
|
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
testContext := func(config WorkerServiceConfig) (*mux.Router, services.Service) { |
||||
externalRouter := mux.NewRouter() |
||||
|
||||
externalRouter, _ := testContext(config, nil) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
|
||||
contentTypeHeader := recorder.Header().Get("Content-Type") |
||||
assert.Equal(t, "application/json; charset=UTF-8", contentTypeHeader) |
||||
}) |
||||
querierWorkerService, err := InitWorkerService( |
||||
config, |
||||
nil, |
||||
handler, |
||||
) |
||||
require.NoError(t, err) |
||||
|
||||
t.Run("do not create a querier worker service if neither frontend address nor scheduler address has been configured", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
return externalRouter, querierWorkerService |
||||
} |
||||
|
||||
_, workerService := testContext(config, nil) |
||||
assert.Nil(t, workerService) |
||||
}) |
||||
t.Run("when querier is configured to run standalone, without a query frontend", func(t *testing.T) { |
||||
t.Run("register the internal query handlers externally", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
|
||||
externalRouter, _ := testContext(config) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, `{"handler": "test"}`, recorder.Body.String()) |
||||
|
||||
// Tail endpoints always external
|
||||
recorder = httptest.NewRecorder() |
||||
request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, "test tail handler", recorder.Body.String()) |
||||
}) |
||||
|
||||
t.Run("wrap external handler with auth middleware", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
|
||||
requestedAuthenticated := false |
||||
mockAuthMiddleware := middleware.Func(func(next http.Handler) http.Handler { |
||||
requestedAuthenticated = true |
||||
return next |
||||
}) |
||||
|
||||
externalRouter, _ := testContext(config, mockAuthMiddleware) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.True(t, requestedAuthenticated) |
||||
}) |
||||
|
||||
t.Run("wrap external handler with response json middleware", func(t *testing.T) { |
||||
// note: this test only assures that the content type of the response is
|
||||
// set if the handler function does not override it, which happens in the
|
||||
// actual implementation, see
|
||||
// https://github.com/grafana/loki/blob/34a012adcfade43291de3a7670f53679ea06aefe/pkg/lokifrontend/frontend/transport/handler.go#L136-L139
|
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
|
||||
externalRouter, _ := testContext(config, nil) |
||||
|
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
|
||||
contentTypeHeader := recorder.Header().Get("Content-Type") |
||||
assert.Equal(t, "application/json; charset=UTF-8", contentTypeHeader) |
||||
}) |
||||
|
||||
t.Run("do not create a querier worker service if neither frontend address nor scheduler address has been configured", func(t *testing.T) { |
||||
config := WorkerServiceConfig{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &querier_worker.Config{}, |
||||
} |
||||
|
||||
_, workerService := testContext(config, nil) |
||||
assert.Nil(t, workerService) |
||||
}) |
||||
|
||||
t.Run("return a querier worker service if frontend or scheduler address has been configured", func(t *testing.T) { |
||||
withFrontendConfig := WorkerServiceConfig{ |
||||
QuerierWorkerConfig: &querier_worker.Config{ |
||||
FrontendAddress: "http://example.com", |
||||
}, |
||||
} |
||||
withSchedulerConfig := WorkerServiceConfig{ |
||||
QuerierWorkerConfig: &querier_worker.Config{ |
||||
SchedulerAddress: "http://example.com", |
||||
}, |
||||
} |
||||
|
||||
for _, config := range []WorkerServiceConfig{ |
||||
withFrontendConfig, |
||||
withSchedulerConfig, |
||||
} { |
||||
_, workerService := testContext(config, nil) |
||||
assert.NotNil(t, workerService) |
||||
} |
||||
}) |
||||
}) |
||||
|
||||
t.Run("return a querier worker service if frontend or scheduler address has been configured", func(t *testing.T) { |
||||
withFrontendConfig := WorkerServiceConfig{ |
||||
QuerierWorkerConfig: &querier_worker.Config{ |
||||
FrontendAddress: "http://example.com", |
||||
t.Run("when query frontend, scheduler, or all target is enabled", func(t *testing.T) { |
||||
defaultWorkerConfig := querier_worker.Config{} |
||||
nonStandaloneTargetPermutations := []WorkerServiceConfig{ |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
} |
||||
withSchedulerConfig := WorkerServiceConfig{ |
||||
QuerierWorkerConfig: &querier_worker.Config{ |
||||
SchedulerAddress: "http://example.com", |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
} |
||||
|
||||
for _, config := range []WorkerServiceConfig{ |
||||
withFrontendConfig, |
||||
withSchedulerConfig, |
||||
} { |
||||
_, workerService := testContext(config, nil) |
||||
assert.NotNil(t, workerService) |
||||
} |
||||
}) |
||||
}) |
||||
|
||||
t.Run("when query frontend, scheduler, or all target is enabled", func(t *testing.T) { |
||||
defaultWorkerConfig := querier_worker.Config{} |
||||
nonStandaloneTargetPermutations := []WorkerServiceConfig{ |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: false, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: false, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: false, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
{ |
||||
QueryFrontendEnabled: true, |
||||
QuerySchedulerEnabled: true, |
||||
AllEnabled: true, |
||||
QuerierWorkerConfig: &defaultWorkerConfig, |
||||
}, |
||||
} |
||||
|
||||
t.Run("do not register the internal query handler externally", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
externalRouter, _ := testContext(config, nil) |
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 404, recorder.Code) |
||||
|
||||
// Tail endpoints always external
|
||||
recorder = httptest.NewRecorder() |
||||
request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, "test tail handler", recorder.Body.String()) |
||||
} |
||||
}) |
||||
t.Run("do not register the internal query handler externally", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
externalRouter, _ := testContext(config) |
||||
recorder := httptest.NewRecorder() |
||||
request := httptest.NewRequest("GET", "/loki/api/v1/query", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 404, recorder.Code) |
||||
|
||||
// Tail endpoints always external
|
||||
recorder = httptest.NewRecorder() |
||||
request = httptest.NewRequest("GET", "/loki/api/v1/tail", nil) |
||||
externalRouter.ServeHTTP(recorder, request) |
||||
assert.Equal(t, 200, recorder.Code) |
||||
assert.Equal(t, "test tail handler", recorder.Body.String()) |
||||
} |
||||
}) |
||||
|
||||
t.Run("use localhost as the worker address if none is set", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
workerConfig := querier_worker.Config{} |
||||
config.QuerierWorkerConfig = &workerConfig |
||||
config.GrpcListenPort = 1234 |
||||
t.Run("use localhost as the worker address if none is set", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
workerConfig := querier_worker.Config{} |
||||
config.QuerierWorkerConfig = &workerConfig |
||||
config.GrpcListenPort = 1234 |
||||
|
||||
testContext(config, nil) |
||||
testContext(config) |
||||
|
||||
assert.Equal(t, "127.0.0.1:1234", workerConfig.FrontendAddress) |
||||
} |
||||
}) |
||||
assert.Equal(t, "127.0.0.1:1234", workerConfig.FrontendAddress) |
||||
} |
||||
}) |
||||
|
||||
t.Run("always return a query worker service", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
workerConfig := querier_worker.Config{} |
||||
config.QuerierWorkerConfig = &workerConfig |
||||
config.GrpcListenPort = 1234 |
||||
t.Run("always return a query worker service", func(t *testing.T) { |
||||
for _, config := range nonStandaloneTargetPermutations { |
||||
workerConfig := querier_worker.Config{} |
||||
config.QuerierWorkerConfig = &workerConfig |
||||
config.GrpcListenPort = 1234 |
||||
|
||||
_, querierWorkerService := testContext(config, nil) |
||||
_, querierWorkerService := testContext(config) |
||||
|
||||
assert.NotNil(t, querierWorkerService) |
||||
} |
||||
assert.NotNil(t, querierWorkerService) |
||||
} |
||||
}) |
||||
}) |
||||
}) |
||||
*/ |
||||
} |
||||
|
||||
Loading…
Reference in new issue