mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 23:32:30 +08:00
SQL Expressions: Add sql expression specific timeout and output limit (#104834)
Adds settings for SQL expressions: sql_expression_cell_output_limit Set the maximum number of cells that can be returned from a SQL expression. Default is 100000. sql_expression_timeout The duration a SQL expression will run before being cancelled. The default is 10s.
This commit is contained in:
@ -13,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/expr/metrics"
|
||||
"github.com/grafana/grafana/pkg/expr/sql"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -30,12 +31,16 @@ type SQLCommand struct {
|
||||
query string
|
||||
varsToQuery []string
|
||||
refID string
|
||||
limit int64
|
||||
format string
|
||||
|
||||
format string
|
||||
|
||||
inputLimit int64
|
||||
outputLimit int64
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// NewSQLCommand creates a new SQLCommand.
|
||||
func NewSQLCommand(refID, format, rawSQL string, limit int64) (*SQLCommand, error) {
|
||||
func NewSQLCommand(refID, format, rawSQL string, intputLimit, outputLimit int64, timeout time.Duration) (*SQLCommand, error) {
|
||||
if rawSQL == "" {
|
||||
return nil, ErrMissingSQLQuery
|
||||
}
|
||||
@ -63,13 +68,15 @@ func NewSQLCommand(refID, format, rawSQL string, limit int64) (*SQLCommand, erro
|
||||
query: rawSQL,
|
||||
varsToQuery: tables,
|
||||
refID: refID,
|
||||
limit: limit,
|
||||
inputLimit: intputLimit,
|
||||
outputLimit: outputLimit,
|
||||
timeout: timeout,
|
||||
format: format,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UnmarshalSQLCommand creates a SQLCommand from Grafana's frontend query.
|
||||
func UnmarshalSQLCommand(rn *rawNode, limit int64) (*SQLCommand, error) {
|
||||
func UnmarshalSQLCommand(rn *rawNode, cfg *setting.Cfg) (*SQLCommand, error) {
|
||||
if rn.TimeRange == nil {
|
||||
logger.Error("time range must be specified for refID", "refID", rn.RefID)
|
||||
return nil, fmt.Errorf("time range must be specified for refID %s", rn.RefID)
|
||||
@ -89,7 +96,7 @@ func UnmarshalSQLCommand(rn *rawNode, limit int64) (*SQLCommand, error) {
|
||||
formatRaw := rn.Query["format"]
|
||||
format, _ := formatRaw.(string)
|
||||
|
||||
return NewSQLCommand(rn.RefID, format, expression, limit)
|
||||
return NewSQLCommand(rn.RefID, format, expression, cfg.SQLExpressionCellLimit, cfg.SQLExpressionOutputCellLimit, cfg.SQLExpressionTimeout)
|
||||
}
|
||||
|
||||
// NeedsVars returns the variable names (refIds) that are dependencies
|
||||
@ -131,11 +138,11 @@ func (gr *SQLCommand) Execute(ctx context.Context, now time.Time, vars mathexp.V
|
||||
tc = totalCells(allFrames)
|
||||
|
||||
// limit of 0 or less means no limit (following convention)
|
||||
if gr.limit > 0 && tc > gr.limit {
|
||||
if gr.inputLimit > 0 && tc > gr.inputLimit {
|
||||
return mathexp.Results{},
|
||||
fmt.Errorf(
|
||||
"SQL expression: total cell count across all input tables exceeds limit of %d. Total cells: %d",
|
||||
gr.limit,
|
||||
gr.inputLimit,
|
||||
tc,
|
||||
)
|
||||
}
|
||||
@ -143,7 +150,7 @@ func (gr *SQLCommand) Execute(ctx context.Context, now time.Time, vars mathexp.V
|
||||
logger.Debug("Executing query", "query", gr.query, "frames", len(allFrames))
|
||||
|
||||
db := sql.DB{}
|
||||
frame, err := db.QueryFrames(ctx, tracer, gr.refID, gr.query, allFrames)
|
||||
frame, err := db.QueryFrames(ctx, tracer, gr.refID, gr.query, allFrames, sql.WithMaxOutputCells(gr.outputLimit), sql.WithTimeout(gr.timeout))
|
||||
|
||||
rsp := mathexp.Results{}
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user