Skip to content

Commit

Permalink
api: use jsoniter (#7816)
Browse files Browse the repository at this point in the history
  • Loading branch information
GiedriusS authored Oct 11, 2024
1 parent af0900b commit d215f5b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 8 deletions.
36 changes: 30 additions & 6 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ import (
"github.com/thanos-io/thanos/pkg/logging"
"github.com/thanos-io/thanos/pkg/server/http/middleware"
"github.com/thanos-io/thanos/pkg/tracing"

// NOTE(GiedriusS): to register jsoniter marshalers.
_ "github.com/prometheus/prometheus/web/api/v1"
)

type status string
Expand Down Expand Up @@ -218,10 +221,10 @@ func GetInstr(
SetCORS(w)
}
if data, warnings, err, releaseResources := f(r); err != nil {
RespondError(w, err, data)
RespondError(w, err, data, logger)
releaseResources()
} else if data != nil {
Respond(w, data, warnings)
Respond(w, data, warnings, logger)
releaseResources()
} else {
w.WriteHeader(http.StatusNoContent)
Expand Down Expand Up @@ -252,7 +255,7 @@ func shouldNotCacheBecauseOfWarnings(warnings []error) bool {
return false
}

func Respond(w http.ResponseWriter, data interface{}, warnings []error) {
func Respond(w http.ResponseWriter, data interface{}, warnings []error, logger log.Logger) {
w.Header().Set("Content-Type", "application/json")
if shouldNotCacheBecauseOfWarnings(warnings) {
w.Header().Set("Cache-Control", "no-store")
Expand All @@ -266,10 +269,21 @@ func Respond(w http.ResponseWriter, data interface{}, warnings []error) {
for _, warn := range warnings {
resp.Warnings = append(resp.Warnings, warn.Error())
}
_ = json.NewEncoder(w).Encode(resp)

json := jsoniter.ConfigCompatibleWithStandardLibrary
b, err := json.Marshal(resp)
if err != nil {
level.Error(logger).Log("msg", "error marshaling response", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

if n, err := w.Write(b); err != nil {
level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err)
}
}

func RespondError(w http.ResponseWriter, apiErr *ApiError, data interface{}) {
func RespondError(w http.ResponseWriter, apiErr *ApiError, data interface{}, logger log.Logger) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "no-store")

Expand All @@ -288,10 +302,20 @@ func RespondError(w http.ResponseWriter, apiErr *ApiError, data interface{}) {
}
w.WriteHeader(code)

_ = json.NewEncoder(w).Encode(&response{
json := jsoniter.ConfigCompatibleWithStandardLibrary
b, err := json.Marshal(&response{
Status: StatusError,
ErrorType: apiErr.Typ,
Error: apiErr.Err.Error(),
Data: data,
})
if err != nil {
level.Error(logger).Log("msg", "error marshaling response", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

if n, err := w.Write(b); err != nil {
level.Error(logger).Log("msg", "error writing response", "bytesWritten", n, "err", err)
}
}
37 changes: 35 additions & 2 deletions pkg/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/prometheus/common/route"
promLabels "github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/promql/parser"
promApiV1 "github.com/prometheus/prometheus/web/api/v1"
Expand Down Expand Up @@ -71,7 +72,7 @@ func TestMarshallMatrixNull(t *testing.T) {

func TestRespondSuccess(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Respond(w, "test", nil)
Respond(w, "test", nil, log.NewNopLogger())
}))
defer s.Close()

Expand Down Expand Up @@ -108,7 +109,7 @@ func TestRespondSuccess(t *testing.T) {

func TestRespondError(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
RespondError(w, &ApiError{ErrorTimeout, errors.New("message")}, "test")
RespondError(w, &ApiError{ErrorTimeout, errors.New("message")}, "test", log.NewNopLogger())
}))
defer s.Close()

Expand Down Expand Up @@ -174,3 +175,35 @@ func TestOptionsMethod(t *testing.T) {
}
}
}

type nilWriter struct{}

var _ = http.ResponseWriter(&nilWriter{})

func (nilWriter) Write(p []byte) (n int, err error) {
return 0, nil
}

func (nilWriter) Header() http.Header {
return http.Header{}
}

func (nilWriter) WriteHeader(statusCode int) {}

func BenchmarkRespond(b *testing.B) {
floats := []promql.FPoint{}

for i := 0; i < 10000; i++ {
floats = append(floats, promql.FPoint{T: 1435781451 + int64(i), F: 1234.123 + float64(i)})
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
Respond(&nilWriter{}, promql.Matrix{
promql.Series{
Metric: promLabels.FromMap(map[string]string{"__name__": "up", "job": "prometheus"}),
Floats: floats,
},
}, nil, log.NewNopLogger())
}
}

0 comments on commit d215f5b

Please sign in to comment.