-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathhandler_test.go
More file actions
162 lines (141 loc) · 4.25 KB
/
handler_test.go
File metadata and controls
162 lines (141 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) The Cortex Authors.
// Licensed under the Apache License 2.0.
package transport
import (
"bytes"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)
type fakeRoundTripper struct {
response *http.Response
err error
requestLatency time.Duration
}
func (f *fakeRoundTripper) RoundTrip(_ *http.Request) (*http.Response, error) {
time.Sleep(f.requestLatency)
return f.response, f.err
}
func TestHandler_SlowQueryLog(t *testing.T) {
t.Parallel()
cfg := HandlerConfig{
QueryStatsEnabled: true,
LogQueriesLongerThan: 1 * time.Microsecond,
}
tests := []struct {
name string
url string
logParts []string
}{
{
name: "Basic query",
url: "/api/v1/query?query=absent(up)&start=1714262400&end=1714266000",
logParts: []string{
"slow query detected",
"time_taken=",
"path=/api/v1/query",
"param_query=absent(up)",
"param_start=1714262400",
"param_end=1714266000",
"trace_id=test-trace-id-123",
},
},
{
name: "Series call",
url: "/api/v1/series?match[]={__name__=~\"up\"}",
logParts: []string{
"slow query detected",
"time_taken=",
"path=/api/v1/series",
},
},
{
name: "Query with different parameters",
url: "/api/v1/query_range?query=rate(http_requests_total[5m])&start=1714262400&end=1714266000&step=15",
logParts: []string{
"slow query detected",
"time_taken=",
"path=/api/v1/query_range",
"param_query=rate(http_requests_total[5m])",
"param_start=1714262400",
"param_end=1714266000",
"param_step=15",
},
},
{
name: "Query with prefixed API string",
url: "/external-prefix/api/v1/query?query=absent(up)&start=1714262400&end=1714266000",
logParts: []string{
"slow query detected",
"time_taken=",
"path=/external-prefix/api/v1/query",
"param_query=absent(up)",
"param_start=1714262400",
"param_end=1714266000",
},
},
{
name: "Non-query endpoint",
url: "/favicon.ico",
// No slow query log for non-query endpoints
logParts: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
fakeRoundTripper := &fakeRoundTripper{
requestLatency: 2 * time.Microsecond,
response: &http.Response{
StatusCode: http.StatusOK,
Header: http.Header{
"Content-Type": []string{"application/json"},
"Server-Timing": []string{"querier;dur=1.23"},
},
Body: io.NopCloser(bytes.NewBufferString(`{}`)),
},
}
logWriter := &bytes.Buffer{}
logger := log.NewLogfmtLogger(log.NewSyncWriter(logWriter))
handler := NewHandler(cfg, fakeRoundTripper, logger, prometheus.NewRegistry())
recorder := httptest.NewRecorder()
recorder.Header().Set("X-Thanos-Trace-Id", "test-trace-id-123")
handler.ServeHTTP(recorder, httptest.NewRequest("GET", tt.url, nil))
for _, part := range tt.logParts {
require.Contains(t, logWriter.String(), part)
}
})
}
}
func TestHandler_SlowQueryLogOnError(t *testing.T) {
t.Parallel()
cfg := HandlerConfig{
QueryStatsEnabled: true,
LogQueriesLongerThan: 1 * time.Microsecond,
}
fakeRT := &fakeRoundTripper{
requestLatency: 2 * time.Microsecond,
response: nil,
err: errDeadlineExceeded,
}
logWriter := &bytes.Buffer{}
logger := log.NewLogfmtLogger(log.NewSyncWriter(logWriter))
handler := NewHandler(cfg, fakeRT, logger, prometheus.NewRegistry())
// Simulate tracing middleware setting the trace ID on the ResponseWriter
// before the handler runs. The slow query log must include this trace ID
// even when the round-tripper returns an error (resp is nil).
recorder := httptest.NewRecorder()
recorder.Header().Set("X-Thanos-Trace-Id", "test-trace-abc123")
handler.ServeHTTP(recorder, httptest.NewRequest("GET", "/api/v1/query?query=up", nil))
// Verify slow query is logged even when round-tripper returns an error
require.Contains(t, logWriter.String(), "slow query detected")
require.Contains(t, logWriter.String(), "time_taken=")
require.Contains(t, logWriter.String(), "path=/api/v1/query")
require.Contains(t, logWriter.String(), "param_query=up")
require.Contains(t, logWriter.String(), "test-trace-abc123")
}