@@ -6,10 +6,8 @@ package transport
6
6
import (
7
7
"bytes"
8
8
"context"
9
- "encoding/json"
10
9
"errors"
11
10
"fmt"
12
- "github.com/prometheus/client_golang/prometheus/promauto"
13
11
"github.com/prometheus/prometheus/util/stats"
14
12
"io"
15
13
"net/http"
44
42
type HandlerConfig struct {
45
43
LogQueriesLongerThan time.Duration `yaml:"log_queries_longer_than"`
46
44
MaxBodySize int64 `yaml:"max_body_size"`
47
- QueryStatsEnabled bool `yaml:"query_stats_enabled"`
48
45
}
49
46
50
47
// Handler accepts queries and forwards them to RoundTripper. It can log slow queries,
@@ -68,27 +65,6 @@ func NewHandler(cfg HandlerConfig, roundTripper http.RoundTripper, log log.Logge
68
65
roundTripper : roundTripper ,
69
66
}
70
67
71
- if cfg .QueryStatsEnabled {
72
- h .querySeconds = promauto .With (reg ).NewHistogramVec (prometheus.HistogramOpts {
73
- Name : "thanos_query_frontend_query_seconds" ,
74
- Help : "Total amount of wall clock time spend processing queries." ,
75
- Buckets : []float64 {0.01 , 0.1 , 0.5 , 1 , 2 , 5 , 10 , 30 , 60 , 120 , 360 },
76
- }, []string {"user" })
77
-
78
- h .querySamplesTotal = promauto .With (reg ).NewHistogramVec (prometheus.HistogramOpts {
79
- Name : "thanos_query_frontend_query_total_fetched_samples" ,
80
- Help : "Number of samples touched to execute a query." ,
81
- Buckets : []float64 {1 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 , 100000000 },
82
- }, []string {"user" })
83
-
84
- h .activeUsers = util .NewActiveUsersCleanupWithDefaultValues (func (user string ) {
85
- h .querySeconds .DeleteLabelValues (user )
86
- h .querySamplesTotal .DeleteLabelValues (user )
87
- })
88
- // If cleaner stops or fail, we will simply not clean the metrics for inactive users.
89
- _ = h .activeUsers .StartAsync (context .Background ())
90
- }
91
-
92
68
return h
93
69
}
94
70
@@ -129,38 +105,15 @@ func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
129
105
130
106
w .WriteHeader (resp .StatusCode )
131
107
132
- var respBuf bytes.Buffer
133
- if f .cfg .QueryStatsEnabled {
134
- // Buffer the response body for query stat tracking later
135
- resp .Body = io .NopCloser (io .TeeReader (resp .Body , & respBuf ))
136
- }
137
-
138
108
// log copy response body error so that we will know even though success response code returned
139
109
bytesCopied , err := io .Copy (w , resp .Body )
140
110
if err != nil && ! errors .Is (err , syscall .EPIPE ) {
141
111
level .Error (util_log .WithContext (r .Context (), f .log )).Log ("msg" , "write response body error" , "bytesCopied" , bytesCopied , "err" , err )
142
112
}
143
113
144
- if f .cfg .QueryStatsEnabled {
145
- // Parse the stats field out of the response body
146
- var statsResponse ResponseWithStats
147
- if err := json .Unmarshal (respBuf .Bytes (), & statsResponse ); err == nil {
148
- if statsResponse .Data .Stats != nil {
149
- queryString = f .parseRequestQueryString (r , buf )
150
- f .reportQueryStats (r , queryString , queryResponseTime , statsResponse .Data .Stats )
151
- } else {
152
- // Don't fail the request if the stats are nil, just log a warning
153
- level .Warn (util_log .WithContext (r .Context (), f .log )).Log ("msg" , "error parsing query stats" , "err" , errors .New ("stats are nil" ))
154
- }
155
- } else {
156
- // Don't fail the request if the stats are nil, just log a warning
157
- level .Warn (util_log .WithContext (r .Context (), f .log )).Log ("msg" , "error parsing query stats" , "err" , err )
158
- }
159
- }
160
-
161
114
// Check whether we should parse the query string.
162
115
shouldReportSlowQuery := f .cfg .LogQueriesLongerThan != 0 && queryResponseTime > f .cfg .LogQueriesLongerThan
163
- if shouldReportSlowQuery || f . cfg . QueryStatsEnabled {
116
+ if shouldReportSlowQuery {
164
117
queryString = f .parseRequestQueryString (r , buf )
165
118
}
166
119
@@ -203,47 +156,6 @@ func (f *Handler) reportSlowQuery(r *http.Request, responseHeaders http.Header,
203
156
level .Info (util_log .WithContext (r .Context (), f .log )).Log (logMessage ... )
204
157
}
205
158
206
- func (f * Handler ) reportQueryStats (r * http.Request , queryString url.Values , queryResponseTime time.Duration , stats * stats.BuiltinStats ) {
207
- remoteUser , _ , _ := r .BasicAuth ()
208
-
209
- // Log stats.
210
- logMessage := []interface {}{
211
- "msg" , "query stats" ,
212
- "component" , "query-frontend" ,
213
- "method" , r .Method ,
214
- "path" , r .URL .Path ,
215
- "remote_user" , remoteUser ,
216
- "remote_addr" , r .RemoteAddr ,
217
- "response_time" , queryResponseTime ,
218
- "query_timings_preparation_time" , stats .Timings .QueryPreparationTime ,
219
- "query_timings_eval_total_time" , stats .Timings .EvalTotalTime ,
220
- "query_timings_exec_total_time" , stats .Timings .ExecTotalTime ,
221
- "query_timings_exec_queue_time" , stats .Timings .ExecQueueTime ,
222
- "query_timings_inner_eval_time" , stats .Timings .InnerEvalTime ,
223
- "query_timings_result_sort_time" , stats .Timings .ResultSortTime ,
224
- }
225
- if stats .Samples != nil {
226
- samples := stats .Samples
227
-
228
- logMessage = append (logMessage , []interface {}{
229
- "total_queryable_samples" , samples .TotalQueryableSamples ,
230
- "peak_samples" , samples .PeakSamples ,
231
- }... )
232
- }
233
-
234
- logMessage = append (logMessage , formatQueryString (queryString )... )
235
-
236
- level .Info (util_log .WithContext (r .Context (), f .log )).Log (logMessage ... )
237
-
238
- // Record metrics.
239
- if f .querySeconds != nil {
240
- f .querySeconds .WithLabelValues (remoteUser ).Observe (queryResponseTime .Seconds ())
241
- }
242
- if f .querySamplesTotal != nil && stats .Samples != nil {
243
- f .querySamplesTotal .WithLabelValues (remoteUser ).Observe (float64 (stats .Samples .TotalQueryableSamples ))
244
- }
245
- }
246
-
247
159
func (f * Handler ) parseRequestQueryString (r * http.Request , bodyBuf bytes.Buffer ) url.Values {
248
160
// Use previously buffered body.
249
161
r .Body = io .NopCloser (& bodyBuf )
0 commit comments