diff --git a/rpcserver/jsonrpc_server.go b/rpcserver/jsonrpc_server.go index 8aa29a1..2c34989 100644 --- a/rpcserver/jsonrpc_server.go +++ b/rpcserver/jsonrpc_server.go @@ -155,9 +155,11 @@ func (h *JSONRPCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer func() { incRequestCount(methodForMetrics, h.ServerName) - incRequestDuration(methodForMetrics, time.Since(startAt).Milliseconds(), h.ServerName) + incRequestDuration(time.Since(startAt), methodForMetrics, h.ServerName) }() + stepStartAt := time.Now() + if r.Method != http.MethodPost { // Respond with GET response content if it's set if r.Method == http.MethodGet && len(h.GetResponseContent) > 0 { @@ -191,6 +193,15 @@ func (h *JSONRPCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { incIncorrectRequest(h.ServerName) return } + defer func(size int) { + incRequestSizeBytes(size, methodForMetrics, h.ServerName) + }(len(body)) + + stepTime := time.Since(stepStartAt) + defer func(stepTime time.Duration) { + incRequestDurationStep(stepTime, methodForMetrics, h.ServerName, "io") + }(stepTime) + stepStartAt = time.Now() if h.VerifyRequestSignatureFromHeader { signatureHeader := r.Header.Get("x-flashbots-signature") @@ -261,18 +272,27 @@ func (h *JSONRPCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } methodForMetrics = req.Method + incRequestDurationStep(time.Since(stepStartAt), methodForMetrics, h.ServerName, "parse") + stepStartAt = time.Now() + // call method result, err := method.call(ctx, req.Params) if err != nil { h.writeJSONRPCError(w, req.ID, CodeCustomError, err.Error()) incRequestErrorCount(methodForMetrics, h.ServerName) + incRequestDurationStep(time.Since(stepStartAt), methodForMetrics, h.ServerName, "call") return } + incRequestDurationStep(time.Since(stepStartAt), methodForMetrics, h.ServerName, "call") + stepStartAt = time.Now() + marshaledResult, err := json.Marshal(result) if err != nil { h.writeJSONRPCError(w, req.ID, CodeInternalError, err.Error()) incInternalErrors(h.ServerName) + + incRequestDurationStep(time.Since(stepStartAt), methodForMetrics, h.ServerName, "response") return } @@ -285,6 +305,8 @@ func (h *JSONRPCHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Error: nil, } h.writeJSONRPCResponse(w, res) + + incRequestDurationStep(time.Since(stepStartAt), methodForMetrics, h.ServerName, "response") } func GetHighPriority(ctx context.Context) bool { diff --git a/rpcserver/metrics.go b/rpcserver/metrics.go index 828aee5..1b87485 100644 --- a/rpcserver/metrics.go +++ b/rpcserver/metrics.go @@ -2,6 +2,7 @@ package rpcserver import ( "fmt" + "time" "github.com/VictoriaMetrics/metrics" ) @@ -23,6 +24,11 @@ const ( errorCountLabel = `goutils_rpcserver_error_count{method="%s",server_name="%s"}` // total duration of the request requestDurationLabel = `goutils_rpcserver_request_duration_milliseconds{method="%s",server_name="%s"}` + // partial duration of the request + requestDurationStepLabel = `goutils_rpcserver_request_step_duration_milliseconds{method="%s",server_name="%s",step="%s"}` + + // request size in bytes + requestSizeBytes = `goutils_rpcserver_request_size_bytes{method="%s",server_name="%s"}` ) func incRequestCount(method, serverName string) { @@ -40,12 +46,24 @@ func incRequestErrorCount(method, serverName string) { metrics.GetOrCreateCounter(l).Inc() } -func incRequestDuration(method string, duration int64, serverName string) { +func incRequestDuration(duration time.Duration, method string, serverName string) { + millis := float64(duration.Microseconds()) / 1000.0 l := fmt.Sprintf(requestDurationLabel, method, serverName) - metrics.GetOrCreateSummary(l).Update(float64(duration)) + metrics.GetOrCreateSummary(l).Update(millis) } func incInternalErrors(serverName string) { l := fmt.Sprintf(internalErrorsCounter, serverName) metrics.GetOrCreateCounter(l).Inc() } + +func incRequestDurationStep(duration time.Duration, method, serverName, step string) { + millis := float64(duration.Microseconds()) / 1000.0 + l := fmt.Sprintf(requestDurationStepLabel, method, serverName, step) + metrics.GetOrCreateSummary(l).Update(millis) +} + +func incRequestSizeBytes(size int, method string, serverName string) { + l := fmt.Sprintf(requestSizeBytes, method, serverName) + metrics.GetOrCreateSummary(l).Update(float64(size)) +}