Loki: fix status in body not matching http status code (#114201)

* fix: status in body not matching http status code
This commit is contained in:
Galen Kistler
2025-11-21 04:40:29 -06:00
committed by GitHub
parent 42babc7ce7
commit 3d2f702ae5
2 changed files with 46 additions and 9 deletions
+5 -1
View File
@@ -199,6 +199,7 @@ func (api *LokiAPI) DataQuery(ctx context.Context, query lokiQuery, responseOpts
res := backend.DataResponse{
Error: err,
ErrorSource: backend.ErrorSourceFromHTTPStatus(resp.StatusCode),
Status: backend.Status(resp.StatusCode),
}
lp = append(lp, "status", "error", "error", err, "statusSource", res.ErrorSource)
api.log.Debug("Error received from Loki", lp...)
@@ -214,6 +215,7 @@ func (api *LokiAPI) DataQuery(ctx context.Context, query lokiQuery, responseOpts
iter := jsoniter.Parse(jsoniter.ConfigDefault, resp.Body, 1024)
res := converter.ReadPrometheusStyleResult(iter, converter.Options{})
res.Status = backend.Status(resp.StatusCode)
if res.Error != nil {
span.RecordError(res.Error)
@@ -305,7 +307,9 @@ func (api *LokiAPI) RawQuery(ctx context.Context, resourcePath string) (RawLokiR
}
body, err = json.Marshal(lokiResponseErr)
if err != nil {
return RawLokiResponse{}, err
return RawLokiResponse{
Status: resp.StatusCode,
}, err
}
}
+41 -8
View File
@@ -250,6 +250,7 @@ func TestApiReturnValues(t *testing.T) {
require.True(t, called)
require.Equal(t, "gzip", encodedBytes.Encoding)
require.Equal(t, []byte("{\"message\":\"foo\"}"), encodedBytes.Body)
require.Equal(t, 400, encodedBytes.Status)
})
t.Run("Loki should return the error as is", func(t *testing.T) {
@@ -280,6 +281,18 @@ func TestApiReturnValues(t *testing.T) {
require.Error(t, err)
require.ErrorContains(t, err, "foo")
})
t.Run("should set status for successful requests", func(t *testing.T) {
called := false
api := makeMockedAPI(200, "application/json", []byte("{\"message\":\"foo\"}"), func(req *http.Request) {
called = true
})
res, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", SupportingQueryType: SupportingQueryLogsVolume, QueryType: QueryTypeRange}, ResponseOpts{})
require.NoError(t, err)
require.True(t, called)
require.Equal(t, backend.Status(http.StatusOK), res.Status)
})
}
func TestErrorSources(t *testing.T) {
@@ -287,7 +300,7 @@ func TestErrorSources(t *testing.T) {
t.Run("should set correct error source for downstream errors", func(t *testing.T) {
called := false
api := makeMockedAPI(400, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusBadRequest, "application/json", errorResponse, func(req *http.Request) {
called = true
})
@@ -296,11 +309,12 @@ func TestErrorSources(t *testing.T) {
require.True(t, called)
require.NotNil(t, res.Error)
require.Equal(t, backend.ErrorSourceDownstream, res.ErrorSource)
require.Equal(t, backend.Status(http.StatusBadRequest), res.Status)
})
t.Run("should set correct error source for plugin errors", func(t *testing.T) {
called := false
api := makeMockedAPI(406, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusNotAcceptable, "application/json", errorResponse, func(req *http.Request) {
called = true
})
@@ -309,11 +323,12 @@ func TestErrorSources(t *testing.T) {
require.True(t, called)
require.NotNil(t, res.Error)
require.Equal(t, backend.ErrorSourcePlugin, res.ErrorSource)
require.Equal(t, backend.Status(http.StatusNotAcceptable), res.Status)
})
t.Run("should set correct error source for server errors", func(t *testing.T) {
called := false
api := makeMockedAPI(500, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusInternalServerError, "application/json", errorResponse, func(req *http.Request) {
called = true
})
@@ -322,11 +337,26 @@ func TestErrorSources(t *testing.T) {
require.True(t, called)
require.NotNil(t, res.Error)
require.Equal(t, backend.ErrorSourceDownstream, res.ErrorSource)
require.Equal(t, backend.Status(http.StatusInternalServerError), res.Status)
})
t.Run("should set correct error source for server timeout error", func(t *testing.T) {
called := false
api := makeMockedAPI(http.StatusGatewayTimeout, "application/json", errorResponse, func(req *http.Request) {
called = true
})
res, err := api.DataQuery(context.Background(), lokiQuery{QueryType: QueryTypeRange}, ResponseOpts{})
require.NoError(t, err)
require.True(t, called)
require.NotNil(t, res.Error)
require.Equal(t, backend.ErrorSourceDownstream, res.ErrorSource)
require.Equal(t, backend.Status(http.StatusGatewayTimeout), res.Status)
})
t.Run("should handle downstream HTTP errors", func(t *testing.T) {
called := false
api := makeMockedAPI(400, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusBadRequest, "application/json", errorResponse, func(req *http.Request) {
called = true
})
@@ -336,30 +366,33 @@ func TestErrorSources(t *testing.T) {
require.NotNil(t, res.Error)
require.Equal(t, backend.ErrorSourceDownstream, res.ErrorSource)
require.Contains(t, res.Error.Error(), "test error")
require.Equal(t, backend.Status(http.StatusBadRequest), res.Status)
})
t.Run("should handle client errors in RawQuery", func(t *testing.T) {
called := false
api := makeMockedAPI(400, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusBadRequest, "application/json", errorResponse, func(req *http.Request) {
called = true
})
res, err := api.RawQuery(context.Background(), "/loki/api/v1/labels")
require.NoError(t, err)
require.True(t, called)
require.Equal(t, 400, res.Status)
require.Equal(t, http.StatusBadRequest, res.Status)
require.Contains(t, string(res.Body), "test error")
})
t.Run("should handle server errors in RawQuery", func(t *testing.T) {
called := false
api := makeMockedAPI(500, "application/json", errorResponse, func(req *http.Request) {
api := makeMockedAPI(http.StatusInternalServerError, "application/json", errorResponse, func(req *http.Request) {
called = true
})
_, err := api.RawQuery(context.Background(), "/loki/api/v1/labels")
res, err := api.RawQuery(context.Background(), "/loki/api/v1/labels")
require.Error(t, err)
require.True(t, called)
require.Contains(t, err.Error(), "test error")
// Status code of 0 gets mapped to InternalServerError (500)
require.Equal(t, 0, res.Status)
})
}