-
Notifications
You must be signed in to change notification settings - Fork 3.7k
feat: add failed and slow queries to query stats #27536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1054f81
f9766e5
869b1b9
052ecf6
51920b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,8 @@ const ( | |
| statQueriesActive = "queriesActive" // Number of queries currently being executed. | ||
| statQueriesExecuted = "queriesExecuted" // Number of queries that have been executed (started). | ||
| statQueriesFinished = "queriesFinished" // Number of queries that have finished. | ||
| statQueriesFailed = "queriesFailed" // Number of queries that have failed. | ||
| statQueriesSlow = "queriesSlow" // Snapshot of in-flight queries running longer than log-queries-after. | ||
| statQueryExecutionDuration = "queryDurationNs" // Total (wall) time spent executing queries. | ||
| statRecoveredPanics = "recoveredPanics" // Number of panics recovered by Query Executor. | ||
|
|
||
|
|
@@ -264,6 +266,7 @@ type Statistics struct { | |
| ActiveQueries int64 | ||
| ExecutedQueries int64 | ||
| FinishedQueries int64 | ||
| FailedQueries int64 | ||
| QueryExecutionDuration int64 | ||
| RecoveredPanics int64 | ||
| } | ||
|
|
@@ -277,6 +280,8 @@ func (e *Executor) Statistics(tags map[string]string) []models.Statistic { | |
| statQueriesActive: atomic.LoadInt64(&e.stats.ActiveQueries), | ||
| statQueriesExecuted: atomic.LoadInt64(&e.stats.ExecutedQueries), | ||
| statQueriesFinished: atomic.LoadInt64(&e.stats.FinishedQueries), | ||
| statQueriesFailed: atomic.LoadInt64(&e.stats.FailedQueries), | ||
| statQueriesSlow: e.TaskManager.SlowQueryCount(), | ||
| statQueryExecutionDuration: atomic.LoadInt64(&e.stats.QueryExecutionDuration), | ||
| statRecoveredPanics: atomic.LoadInt64(&e.stats.RecoveredPanics), | ||
| }, | ||
|
|
@@ -308,14 +313,30 @@ func (e *Executor) executeQuery(query *influxql.Query, opt ExecutionOptions, clo | |
|
|
||
| atomic.AddInt64(&e.stats.ActiveQueries, 1) | ||
| atomic.AddInt64(&e.stats.ExecutedQueries, 1) | ||
|
|
||
| // A query is counted as failed at most once, in the deferred cleanup below. | ||
| // Two signals feed it: failed, for terminal errors executeQuery emits | ||
| // directly on the results channel (before ctx exists, or bypassing it); and | ||
| // ctx.Failed(), set whenever any Result with a non-nil Err is sent through | ||
| // the ExecutionContext — including errors a StatementExecutor sends itself | ||
| // while returning nil, and ErrNotExecuted emitted for interrupted queries. | ||
| // Panics are counted separately in recover(), which runs after this closure. | ||
| failed := false | ||
| var ctx *ExecutionContext | ||
| defer func(start time.Time) { | ||
| atomic.AddInt64(&e.stats.ActiveQueries, -1) | ||
| atomic.AddInt64(&e.stats.FinishedQueries, 1) | ||
| if failed || (ctx != nil && ctx.Failed()) { | ||
| atomic.AddInt64(&e.stats.FailedQueries, 1) | ||
| } | ||
| atomic.AddInt64(&e.stats.QueryExecutionDuration, time.Since(start).Nanoseconds()) | ||
| }(time.Now()) | ||
|
|
||
| ctx, detach, err := e.TaskManager.AttachQuery(query, opt, closing) | ||
| var detach func() | ||
| var err error | ||
| ctx, detach, err = e.TaskManager.AttachQuery(query, opt, closing) | ||
| if err != nil { | ||
| failed = true | ||
| select { | ||
| case results <- &Result{Err: err}: | ||
| case <-opt.AbortCh: | ||
|
|
@@ -362,6 +383,7 @@ LOOP: | |
| case "_tags": | ||
| command = "SHOW TAG VALUES" | ||
| } | ||
| failed = true | ||
| results <- &Result{ | ||
| Err: fmt.Errorf("unable to use system source '%s': use %s instead", s.Name, command), | ||
| } | ||
|
|
@@ -375,6 +397,7 @@ LOOP: | |
| // This can occur on meta read statements which convert to SELECT statements. | ||
| newStmt, err := RewriteStatement(stmt) | ||
| if err != nil { | ||
| failed = true | ||
| results <- &Result{Err: err} | ||
| break | ||
| } | ||
|
Copilot marked this conversation as resolved.
|
||
|
|
@@ -427,6 +450,11 @@ LOOP: | |
| } | ||
|
|
||
| if interrupted { | ||
| // A query killed or timed out between statements is a failed query, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we consider a cancelled query as failed? Or should we use a different metric for this i.e.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think canceled queries will be such a small percentage, we can consider them failed because of user unhappiness. |
||
| // consistent with one interrupted during a statement (err != nil | ||
| // above). The ErrNotExecuted fan-out below sets ctx.Failed() when | ||
| // statements remain, but not when this was the last statement. | ||
| failed = true | ||
| break | ||
| } | ||
| } | ||
|
|
@@ -456,6 +484,7 @@ func init() { | |
| func (e *Executor) recover(query *influxql.Query, results chan *Result) { | ||
| if err := recover(); err != nil { | ||
| atomic.AddInt64(&e.stats.RecoveredPanics, 1) // Capture the panic in _internal stats. | ||
| atomic.AddInt64(&e.stats.FailedQueries, 1) // A panicked query is a failed query. | ||
| e.Logger.Error(fmt.Sprintf("%s [panic:%s] %s", query.String(), err, debug.Stack())) | ||
|
davidby-influx marked this conversation as resolved.
Outdated
|
||
| results <- &Result{ | ||
| StatementID: -1, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.