diff --git a/pkg/tsdb/loki/parse_query.go b/pkg/tsdb/loki/parse_query.go index e212e43568a02..d6c81f1c1c797 100644 --- a/pkg/tsdb/loki/parse_query.go +++ b/pkg/tsdb/loki/parse_query.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/tsdb/intervalv2" + "github.com/grafana/grafana/pkg/tsdb/loki/kinds/dataquery" ) const ( @@ -18,6 +19,7 @@ const ( varRange = "$__range" varRangeS = "$__range_s" varRangeMs = "$__range_ms" + varAutoRange = "$__auto" ) const ( @@ -28,7 +30,7 @@ const ( varRangeMsAlt = "${__range_ms}" ) -func interpolateVariables(expr string, interval time.Duration, timeRange time.Duration) string { +func interpolateVariables(expr string, interval time.Duration, timeRange time.Duration, step time.Duration, queryType dataquery.LokiQueryType) string { intervalText := intervalv2.FormatDuration(interval) intervalMsText := strconv.FormatInt(int64(interval/time.Millisecond), 10) @@ -50,6 +52,19 @@ func interpolateVariables(expr string, interval time.Duration, timeRange time.Du expr = strings.ReplaceAll(expr, varRangeMsAlt, rangeMsText) expr = strings.ReplaceAll(expr, varRangeSAlt, rangeSText) expr = strings.ReplaceAll(expr, varRangeAlt, rangeSText+"s") + + // Interpolate $__auto range variable to step in range queries and to $__range in instant queries + // re := regexp.MustCompile(`\s*\[auto\]\s*\)`) + if queryType == dataquery.LokiQueryTypeRange { + //expr = re.ReplaceAllString(expr, "[" + intervalv2.FormatDuration(step)+"])") + expr = strings.ReplaceAll(expr, varAutoRange, intervalText) + } + + if queryType == dataquery.LokiQueryTypeInstant { + //expr = re.ReplaceAllString(expr, "[" + rangeSText + "s])") + expr = strings.ReplaceAll(expr, varAutoRange, rangeSText+"s") + } + return expr } @@ -131,8 +146,6 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { return nil, err } - expr := interpolateVariables(model.Expr, interval, timeRange) - queryType, err := parseQueryType(model.QueryType) if err != nil { return nil, err @@ -143,6 +156,8 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { return nil, err } + expr := interpolateVariables(model.Expr, interval, timeRange, step, queryType) + var maxLines int64 if model.MaxLines != nil { maxLines = *model.MaxLines diff --git a/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx b/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx index c89734d7b62db..5700c9faed2cd 100644 --- a/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx +++ b/public/app/plugins/datasource/loki/components/LokiLabelBrowser.tsx @@ -201,7 +201,7 @@ export class UnthemedLokiLabelBrowser extends React.Component ( documentation: f.documentation, })); -const FUNCTION_COMPLETIONS: Completion[] = RANGE_VEC_FUNCTIONS.map((f) => ({ - type: 'FUNCTION', - label: f.label, - insertText: `${f.insertText ?? ''}({$0}[\\$__interval])`, // i don't know what to do when this is nullish. it should not be. - isSnippet: true, - triggerOnInsert: true, - detail: f.detail, - documentation: f.documentation, -})); +const FUNCTION_COMPLETIONS: Completion[] = RANGE_VEC_FUNCTIONS.map((f) => { + return { + type: 'FUNCTION', + label: f.label, + insertText: `${f.insertText ?? ''}({$0}[\\$__auto_range])`, // i don't know what to do when this is nullish. it should not be. + isSnippet: true, + triggerOnInsert: true, + detail: f.detail, + documentation: f.documentation, + }; +}); const BUILT_IN_FUNCTIONS_COMPLETIONS: Completion[] = BUILT_IN_FUNCTIONS.map((f) => ({ type: 'FUNCTION', @@ -71,13 +73,21 @@ const BUILT_IN_FUNCTIONS_COMPLETIONS: Completion[] = BUILT_IN_FUNCTIONS.map((f) documentation: f.documentation, })); -const DURATION_COMPLETIONS: Completion[] = ['$__interval', '$__range', '1m', '5m', '10m', '30m', '1h', '1d'].map( - (text) => ({ - type: 'DURATION', - label: text, - insertText: text, - }) -); +const DURATION_COMPLETIONS: Completion[] = [ + '$__auto_range', + '$__interval', + '$__range', + '1m', + '5m', + '10m', + '30m', + '1h', + '1d', +].map((text) => ({ + type: 'DURATION', + label: text, + insertText: text, +})); const UNWRAP_FUNCTION_COMPLETIONS: Completion[] = [ { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index c0da2484716e4..03403dc4f4704 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -197,7 +197,7 @@ export class LokiDatasource refId: `${REF_ID_STARTER_LOG_VOLUME}${normalizedQuery.refId}`, queryType: LokiQueryType.Range, supportingQueryType: SupportingQueryType.LogsVolume, - expr: `sum by (level) (count_over_time(${expr}[$__interval]))`, + expr: `sum by (level) (count_over_time(${expr}[$__auto_range]))`, }; case SupplementaryQueryType.LogsSample: diff --git a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts index c7d689a53ae6c..1587908001da2 100644 --- a/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts +++ b/public/app/plugins/datasource/loki/querybuilder/LokiQueryModeller.ts @@ -122,7 +122,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { { id: LokiOperationId.LabelFilterNoErrors, params: [] }, { id: LokiOperationId.Unwrap, params: [''] }, { id: LokiOperationId.LabelFilterNoErrors, params: [] }, - { id: LokiOperationId.SumOverTime, params: ['$__interval'] }, + { id: LokiOperationId.SumOverTime, params: ['$__auto_range'] }, { id: LokiOperationId.Sum, params: [] }, ], }, @@ -132,7 +132,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { // sum by() (count_over_time({}[$__interval) operations: [ { id: LokiOperationId.LineContains, params: [''] }, - { id: LokiOperationId.CountOverTime, params: ['$__interval'] }, + { id: LokiOperationId.CountOverTime, params: ['$__auto_range'] }, { id: LokiOperationId.Sum, params: [] }, ], }, @@ -144,7 +144,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { { id: LokiOperationId.LineContains, params: [''] }, { id: LokiOperationId.Logfmt, params: [] }, { id: LokiOperationId.LabelFilterNoErrors, params: [] }, - { id: LokiOperationId.CountOverTime, params: ['$__interval'] }, + { id: LokiOperationId.CountOverTime, params: ['$__auto_range'] }, { id: LokiOperationId.Sum, params: [] }, ], }, @@ -154,7 +154,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { // bytes_over_time({}[$__interval]) operations: [ { id: LokiOperationId.LineContains, params: [''] }, - { id: LokiOperationId.BytesOverTime, params: ['$__interval'] }, + { id: LokiOperationId.BytesOverTime, params: ['$__auto_range'] }, ], }, { @@ -173,7 +173,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { operations: [ { id: LokiOperationId.Logfmt, params: [] }, { id: LokiOperationId.LabelFilterNoErrors, params: [] }, - { id: LokiOperationId.CountOverTime, params: ['$__interval'] }, + { id: LokiOperationId.CountOverTime, params: ['$__auto_range'] }, { id: LokiOperationId.Sum, params: [] }, { id: LokiOperationId.TopK, params: [10] }, ], @@ -187,7 +187,7 @@ export class LokiQueryModeller extends LokiAndPromQueryModellerBase { { id: LokiOperationId.LabelFilterNoErrors, params: [] }, { id: LokiOperationId.Unwrap, params: ['latency'] }, { id: LokiOperationId.LabelFilterNoErrors, params: [] }, - { id: LokiOperationId.QuantileOverTime, params: ['$__interval', 0.5] }, + { id: LokiOperationId.QuantileOverTime, params: ['$__auto_range', 0.5] }, { id: LokiOperationId.Sum, params: [] }, ], }, diff --git a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts index 0a26a20e4b725..c9b34aea21c23 100644 --- a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts +++ b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts @@ -17,7 +17,8 @@ import { LokiOperationId, LokiOperationOrder, LokiVisualQuery, LokiVisualQueryOp export function createRangeOperation(name: string, isRangeOperationWithGrouping?: boolean): QueryBuilderOperationDef { const params = [getRangeVectorParamDef()]; - const defaultParams = ['$__interval']; + const defaultParams = ['$__auto_range']; + let paramChangedHandler = undefined; if (name === LokiOperationId.QuantileOverTime) { @@ -55,6 +56,8 @@ export function createRangeOperation(name: string, isRangeOperationWithGrouping? if (op.params[0] === '$__interval') { return `${opDocs} \`$__interval\` is a variable that will be replaced with the [calculated interval](https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#__interval) based on the time range and width of the graph. In Dashboards, you can affect the interval variable using **Max data points** and **Min interval**. You can find these options under **Query options** right of the data source select dropdown.`; + } else if (op.params[0] === '$__auto_range') { + return `${opDocs} \`$__auto_range\` is a variable that will be replaced with the value of step in range queries and value of $__range in instant queries.`; } else { return `${opDocs} The [range vector](https://grafana.com/docs/loki/latest/logql/metric_queries/#range-vector-aggregation) is set to \`${op.params[0]}\`.`; } @@ -137,14 +140,14 @@ function operationWithRangeVectorRenderer( innerExpr: string ) { const params = model.params ?? []; - const rangeVector = params[0] ?? '$__interval'; + const rangeVector = params[0] ?? '$__auto_range'; // QuantileOverTime is only range vector with more than one param if (params.length === 2 && model.id === LokiOperationId.QuantileOverTime) { const quantile = params[1]; return `${model.id}(${quantile}, ${innerExpr} [${rangeVector}])`; } - return `${model.id}(${innerExpr} [${params[0] ?? '$__interval'}])`; + return `${model.id}(${innerExpr} [${params[0] ?? '$__auto_range'}])`; } export function labelFilterRenderer(model: QueryBuilderOperation, def: QueryBuilderOperationDef, innerExpr: string) { @@ -237,7 +240,7 @@ export function addLokiOperation( modeller, (def) => def.category === LokiVisualQueryOperationCategory.Functions ); - operations.splice(placeToInsert, 0, { id: LokiOperationId.Rate, params: ['$__interval'] }); + operations.splice(placeToInsert, 0, { id: LokiOperationId.Rate, params: ['$__auto_range'] }); } operations.push(newOperation); break; @@ -292,6 +295,6 @@ function getRangeVectorParamDef(): QueryBuilderOperationParamDef { return { name: 'Range', type: 'string', - options: ['$__interval', '$__range', '1m', '5m', '10m', '1h', '24h'], + options: ['$__auto_range', '$__interval', '$__range', '1m', '5m', '10m', '1h', '24h'], }; }