Skip to content

Commit 245d1f9

Browse files
committed
add active query tracker to query frontend
Signed-off-by: Ahmed Hassan <[email protected]>
1 parent e31c57c commit 245d1f9

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

docs/configuration/config-file-reference.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4506,6 +4506,17 @@ The `query_frontend_config` configures the Cortex query-frontend.
45064506
# CLI flag: -frontend.enabled-ruler-query-stats
45074507
[enabled_ruler_query_stats_log: <boolean> | default = false]
45084508
4509+
# Active query tracker monitors active queries, and writes them to the file in
4510+
# given directory. If Cortex discovers any queries in this log during startup,
4511+
# it will log them to the log file. Setting to empty value disables active query
4512+
# tracker, which also disables -frontend.max-concurrent option.
4513+
# CLI flag: -frontend.active-query-tracker-dir
4514+
[active_query_tracker_dir: <string> | default = ""]
4515+
4516+
# The maximum number of concurrent queries running in query frontend.
4517+
# CLI flag: -frontend.max-concurrent
4518+
[max_concurrent: <int> | default = 500]
4519+
45094520
# If a querier disconnects without sending notification about graceful shutdown,
45104521
# the query-frontend will keep the querier in the tenant's shard until the
45114522
# forget delay has passed. This feature is useful to reduce the blast radius

pkg/frontend/transport/handler.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
util_api "github.com/cortexproject/cortex/pkg/util/api"
3131
"github.com/cortexproject/cortex/pkg/util/limiter"
3232
util_log "github.com/cortexproject/cortex/pkg/util/log"
33+
"github.com/prometheus/prometheus/promql"
3334
)
3435

3536
const (
@@ -81,13 +82,17 @@ type HandlerConfig struct {
8182
MaxBodySize int64 `yaml:"max_body_size"`
8283
QueryStatsEnabled bool `yaml:"query_stats_enabled"`
8384
EnabledRulerQueryStatsLog bool `yaml:"enabled_ruler_query_stats_log"`
85+
ActiveQueryTrackerDir string `yaml:"active_query_tracker_dir"`
86+
MaxConcurrent int `yaml:"max_concurrent"`
8487
}
8588

8689
func (cfg *HandlerConfig) RegisterFlags(f *flag.FlagSet) {
8790
f.DurationVar(&cfg.LogQueriesLongerThan, "frontend.log-queries-longer-than", 0, "Log queries that are slower than the specified duration. Set to 0 to disable. Set to < 0 to enable on all queries.")
8891
f.Int64Var(&cfg.MaxBodySize, "frontend.max-body-size", 10*1024*1024, "Max body size for downstream prometheus.")
8992
f.BoolVar(&cfg.QueryStatsEnabled, "frontend.query-stats-enabled", false, "True to enable query statistics tracking. When enabled, a message with some statistics is logged for every query.")
9093
f.BoolVar(&cfg.EnabledRulerQueryStatsLog, "frontend.enabled-ruler-query-stats", false, "If enabled, report the query stats log for queries coming from the ruler to evaluate rules. It only takes effect when '-ruler.frontend-address' is configured.")
94+
f.StringVar(&cfg.ActiveQueryTrackerDir, "frontend.active-query-tracker-dir", "", "Active query tracker monitors active queries, and writes them to the file in given directory. If Cortex discovers any queries in this log during startup, it will log them to the log file. Setting to empty value disables active query tracker, which also disables -frontend.max-concurrent option.")
95+
f.IntVar(&cfg.MaxConcurrent, "frontend.max-concurrent", 500, "The maximum number of concurrent queries running in query frontend.")
9196
}
9297

9398
// Handler accepts queries and forwards them to RoundTripper. It can log slow queries,
@@ -109,6 +114,7 @@ type Handler struct {
109114
rejectedQueries *prometheus.CounterVec
110115
slowQueries *prometheus.CounterVec
111116
activeUsers *util.ActiveUsersCleanupService
117+
activeQueryTracker promql.QueryTracker
112118

113119
initSlowQueryMetric sync.Once
114120
reg prometheus.Registerer
@@ -176,6 +182,10 @@ func NewHandler(cfg HandlerConfig, tenantFederationCfg tenantfederation.Config,
176182
_ = h.activeUsers.StartAsync(context.Background())
177183
}
178184

185+
if cfg.ActiveQueryTrackerDir != "" {
186+
h.activeQueryTracker = promql.NewActiveQueryTracker(cfg.ActiveQueryTrackerDir, cfg.MaxConcurrent, util_log.GoKitLogToSlog(log))
187+
}
188+
179189
return h
180190
}
181191

@@ -297,6 +307,22 @@ func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
297307
r.Body = io.NopCloser(&buf)
298308
}
299309

310+
var trackerIndex int
311+
if f.activeQueryTracker != nil {
312+
path := r.URL.Path
313+
if q := r.Form.Get("query"); q != "" {
314+
queryStr := fmt.Sprintf("[tenant:%s] %s %s", userID, path, q)
315+
trackerIndex, _ = f.activeQueryTracker.Insert(r.Context(), queryStr)
316+
} else if matches := r.Form["match[]"]; len(matches) > 0 {
317+
queryStr := fmt.Sprintf("[tenant:%s] %s %s", userID, path, strings.Join(matches, ","))
318+
trackerIndex, _ = f.activeQueryTracker.Insert(r.Context(), queryStr)
319+
} else {
320+
queryStr := fmt.Sprintf("[tenant:%s] %s", userID, path)
321+
trackerIndex, _ = f.activeQueryTracker.Insert(r.Context(), queryStr)
322+
}
323+
defer f.activeQueryTracker.Delete(trackerIndex)
324+
}
325+
300326
source := tripperware.GetSource(r.Header.Get("User-Agent"))
301327
// Log request
302328
if f.cfg.QueryStatsEnabled {

0 commit comments

Comments
 (0)