mirror of
https://github.com/prometheus/prometheus
synced 2024-12-27 17:13:22 +00:00
Merge pull request #4359 from prometheus/report-errors
Log errors encountered when marshalling and writing responses.
This commit is contained in:
commit
b1f600343f
@ -28,6 +28,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
"github.com/go-kit/kit/log/level"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/common/route"
|
"github.com/prometheus/common/route"
|
||||||
@ -125,6 +127,7 @@ type API struct {
|
|||||||
|
|
||||||
db func() *tsdb.DB
|
db func() *tsdb.DB
|
||||||
enableAdmin bool
|
enableAdmin bool
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPI returns an initialized API type.
|
// NewAPI returns an initialized API type.
|
||||||
@ -138,6 +141,7 @@ func NewAPI(
|
|||||||
readyFunc func(http.HandlerFunc) http.HandlerFunc,
|
readyFunc func(http.HandlerFunc) http.HandlerFunc,
|
||||||
db func() *tsdb.DB,
|
db func() *tsdb.DB,
|
||||||
enableAdmin bool,
|
enableAdmin bool,
|
||||||
|
logger log.Logger,
|
||||||
) *API {
|
) *API {
|
||||||
return &API{
|
return &API{
|
||||||
QueryEngine: qe,
|
QueryEngine: qe,
|
||||||
@ -160,9 +164,9 @@ func (api *API) Register(r *route.Router) {
|
|||||||
setCORS(w)
|
setCORS(w)
|
||||||
data, err, finalizer := f(r)
|
data, err, finalizer := f(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondError(w, err, data)
|
api.respondError(w, err, data)
|
||||||
} else if data != nil {
|
} else if data != nil {
|
||||||
respond(w, data)
|
api.respond(w, data)
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
@ -819,23 +823,38 @@ func mergeLabels(primary, secondary []*prompb.Label) []*prompb.Label {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func respond(w http.ResponseWriter, data interface{}) {
|
func (api *API) respond(w http.ResponseWriter, data interface{}) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
|
|
||||||
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
b, err := json.Marshal(&response{
|
b, err := json.Marshal(&response{
|
||||||
Status: statusSuccess,
|
Status: statusSuccess,
|
||||||
Data: data,
|
Data: data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
level.Error(api.logger).Log("msg", "error marshalling json response", "err", err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write(b)
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
if n, err := w.Write(b); err != nil {
|
||||||
|
level.Error(api.logger).Log("msg", "error writing response", "bytesWritten", n, "err", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondError(w http.ResponseWriter, apiErr *apiError, data interface{}) {
|
func (api *API) respondError(w http.ResponseWriter, apiErr *apiError, data interface{}) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
b, err := json.Marshal(&response{
|
||||||
|
Status: statusError,
|
||||||
|
ErrorType: apiErr.typ,
|
||||||
|
Error: apiErr.err.Error(),
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
level.Error(api.logger).Log("msg", "error marshalling json response", "err", err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var code int
|
var code int
|
||||||
switch apiErr.typ {
|
switch apiErr.typ {
|
||||||
@ -852,19 +871,12 @@ func respondError(w http.ResponseWriter, apiErr *apiError, data interface{}) {
|
|||||||
default:
|
default:
|
||||||
code = http.StatusInternalServerError
|
code = http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
w.WriteHeader(code)
|
|
||||||
|
|
||||||
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
w.Header().Set("Content-Type", "application/json")
|
||||||
b, err := json.Marshal(&response{
|
w.WriteHeader(code)
|
||||||
Status: statusError,
|
if n, err := w.Write(b); err != nil {
|
||||||
ErrorType: apiErr.typ,
|
level.Error(api.logger).Log("msg", "error writing response", "bytesWritten", n, "err", err)
|
||||||
Error: apiErr.err.Error(),
|
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
w.Write(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTime(s string) (time.Time, error) {
|
func parseTime(s string) (time.Time, error) {
|
||||||
|
@ -750,7 +750,8 @@ func TestReadEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
func TestRespondSuccess(t *testing.T) {
|
func TestRespondSuccess(t *testing.T) {
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
respond(w, "test")
|
api := API{}
|
||||||
|
api.respond(w, "test")
|
||||||
}))
|
}))
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
@ -787,7 +788,8 @@ func TestRespondSuccess(t *testing.T) {
|
|||||||
|
|
||||||
func TestRespondError(t *testing.T) {
|
func TestRespondError(t *testing.T) {
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
respondError(w, &apiError{errorTimeout, errors.New("message")}, "test")
|
api := API{}
|
||||||
|
api.respondError(w, &apiError{errorTimeout, errors.New("message")}, "test")
|
||||||
}))
|
}))
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
@ -1039,7 +1041,8 @@ func TestRespond(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
respond(w, c.response)
|
api := API{}
|
||||||
|
api.respond(w, c.response)
|
||||||
}))
|
}))
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
@ -1078,7 +1081,8 @@ func BenchmarkRespond(b *testing.B) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
api := API{}
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
respond(&testResponseWriter, response)
|
api.respond(&testResponseWriter, response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,6 +227,7 @@ func New(logger log.Logger, o *Options) *Handler {
|
|||||||
h.testReady,
|
h.testReady,
|
||||||
h.options.TSDB,
|
h.options.TSDB,
|
||||||
h.options.EnableAdminAPI,
|
h.options.EnableAdminAPI,
|
||||||
|
logger,
|
||||||
)
|
)
|
||||||
|
|
||||||
if o.RoutePrefix != "/" {
|
if o.RoutePrefix != "/" {
|
||||||
|
Loading…
Reference in New Issue
Block a user