mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 15:29:01 +08:00
feat: custom timeout and contextTimeout flag in response (#4022)
This commit is contained in:
parent
01df53074c
commit
7451e885c3
@ -3042,6 +3042,17 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que
|
|||||||
resp := v3.QueryRangeResponse{
|
resp := v3.QueryRangeResponse{
|
||||||
Result: result,
|
Result: result,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This checks if the time for context to complete has exceeded.
|
||||||
|
// it adds flag to notify the user of incomplete respone
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
resp.ContextTimeout = true
|
||||||
|
resp.ContextTimeoutMessage = "result might contain incomplete data due to context timeout, for custom timeout set the timeout header eg:- timeout:120"
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
aH.Respond(w, resp)
|
aH.Respond(w, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +428,22 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRouteContextTimeout(overrideTimeout string) time.Duration {
|
||||||
|
var timeout time.Duration
|
||||||
|
var err error
|
||||||
|
if overrideTimeout != "" {
|
||||||
|
timeout, err = time.ParseDuration(overrideTimeout + "s")
|
||||||
|
if err != nil {
|
||||||
|
timeout = constants.ContextTimeout
|
||||||
|
}
|
||||||
|
if timeout > constants.ContextTimeoutMaxAllowed {
|
||||||
|
timeout = constants.ContextTimeoutMaxAllowed
|
||||||
|
}
|
||||||
|
return timeout
|
||||||
|
}
|
||||||
|
return constants.ContextTimeout
|
||||||
|
}
|
||||||
|
|
||||||
func setTimeoutMiddleware(next http.Handler) http.Handler {
|
func setTimeoutMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@ -435,7 +451,7 @@ func setTimeoutMiddleware(next http.Handler) http.Handler {
|
|||||||
// check if route is not excluded
|
// check if route is not excluded
|
||||||
url := r.URL.Path
|
url := r.URL.Path
|
||||||
if _, ok := constants.TimeoutExcludedRoutes[url]; !ok {
|
if _, ok := constants.TimeoutExcludedRoutes[url]; !ok {
|
||||||
ctx, cancel = context.WithTimeout(r.Context(), constants.ContextTimeout)
|
ctx, cancel = context.WithTimeout(r.Context(), getRouteContextTimeout(r.Header.Get("timeout")))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
pkg/query-service/app/server_test.go
Normal file
41
pkg/query-service/app/server_test.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetRouteContextTimeout(t *testing.T) {
|
||||||
|
var testGetRouteContextTimeoutData = []struct {
|
||||||
|
Name string
|
||||||
|
OverrideValue string
|
||||||
|
timeout time.Duration
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "default",
|
||||||
|
OverrideValue: "",
|
||||||
|
timeout: 60 * time.Second,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "override",
|
||||||
|
OverrideValue: "180",
|
||||||
|
timeout: 180 * time.Second,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "override more than max",
|
||||||
|
OverrideValue: "610",
|
||||||
|
timeout: 600 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
for _, test := range testGetRouteContextTimeoutData {
|
||||||
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
|
res := getRouteContextTimeout(test.OverrideValue)
|
||||||
|
assert.Equal(t, test.timeout, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -135,6 +135,17 @@ func GetContextTimeout() time.Duration {
|
|||||||
|
|
||||||
var ContextTimeout = GetContextTimeout()
|
var ContextTimeout = GetContextTimeout()
|
||||||
|
|
||||||
|
func GetContextTimeoutMaxAllowed() time.Duration {
|
||||||
|
contextTimeoutStr := GetOrDefaultEnv("CONTEXT_TIMEOUT_MAX_ALLOWED", "600")
|
||||||
|
contextTimeoutDuration, err := time.ParseDuration(contextTimeoutStr + "s")
|
||||||
|
if err != nil {
|
||||||
|
return time.Minute
|
||||||
|
}
|
||||||
|
return contextTimeoutDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
var ContextTimeoutMaxAllowed = GetContextTimeoutMaxAllowed()
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TraceID = "traceID"
|
TraceID = "traceID"
|
||||||
ServiceName = "serviceName"
|
ServiceName = "serviceName"
|
||||||
|
@ -613,8 +613,10 @@ func (h *Having) CacheKey() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type QueryRangeResponse struct {
|
type QueryRangeResponse struct {
|
||||||
ResultType string `json:"resultType"`
|
ContextTimeout bool `json:"contextTimeout,omitempty"`
|
||||||
Result []*Result `json:"result"`
|
ContextTimeoutMessage string `json:"contextTimeoutMessage,omitempty"`
|
||||||
|
ResultType string `json:"resultType"`
|
||||||
|
Result []*Result `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user