diff --git a/docs/sources/developers/kinds/composable/lokidataquery/schema-reference.md b/docs/sources/developers/kinds/composable/lokidataquery/schema-reference.md new file mode 100644 index 00000000000..0953661df24 --- /dev/null +++ b/docs/sources/developers/kinds/composable/lokidataquery/schema-reference.md @@ -0,0 +1,47 @@ +--- +keywords: + - grafana + - schema +title: LokiDataQuery kind +--- +> Both documentation generation and kinds schemas are in active development and subject to change without prior notice. + +## LokiDataQuery + +#### Maturity: experimental +#### Version: 0.0 + + + +It extends [DataQuery](#dataquery). + +| Property | Type | Required | Description | +|----------------|---------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `expr` | string | **Yes** | The LogQL query. | +| `refId` | string | **Yes** | *(Inherited from [DataQuery](#dataquery))*
A - Z | +| `datasource` | | No | *(Inherited from [DataQuery](#dataquery))*
For mixed data sources the selected datasource is on the query level.
For non mixed scenarios this is undefined.
TODO find a better way to do this ^ that's friendly to schema
TODO this shouldn't be unknown but DataSourceRef | null | +| `editorMode` | string | No | Possible values are: `code`, `builder`. | +| `hide` | boolean | No | *(Inherited from [DataQuery](#dataquery))*
true if query is disabled (ie should not be returned to the dashboard) | +| `instant` | boolean | No | @deprecated, now use queryType. | +| `key` | string | No | *(Inherited from [DataQuery](#dataquery))*
Unique, guid like, string used in explore mode | +| `legendFormat` | string | No | Used to override the name of the series. | +| `maxLines` | integer | No | Used to limit the number of log rows returned. | +| `queryType` | string | No | *(Inherited from [DataQuery](#dataquery))*
Specify the query flavor
TODO make this required and give it a default | +| `range` | boolean | No | @deprecated, now use queryType. | +| `resolution` | integer | No | Used to scale the interval value. | + +### DataQuery + +These are the common properties available to all queries in all datasources. +Specific implementations will *extend* this interface, adding the required +properties for the given context. + +| Property | Type | Required | Description | +|--------------|---------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `refId` | string | **Yes** | A - Z | +| `datasource` | | No | For mixed data sources the selected datasource is on the query level.
For non mixed scenarios this is undefined.
TODO find a better way to do this ^ that's friendly to schema
TODO this shouldn't be unknown but DataSourceRef | null | +| `hide` | boolean | No | true if query is disabled (ie should not be returned to the dashboard) | +| `key` | string | No | Unique, guid like, string used in explore mode | +| `queryType` | string | No | Specify the query flavor
TODO make this required and give it a default | + + diff --git a/pkg/kindsys/report.json b/pkg/kindsys/report.json index 1e3fe9c0ddb..0b3ca46a0b6 100644 --- a/pkg/kindsys/report.json +++ b/pkg/kindsys/report.json @@ -908,7 +908,9 @@ }, "lokidataquery": { "category": "composable", - "codeowners": [], + "codeowners": [ + "grafana/observability-logs" + ], "currentVersion": [ 0, 0 @@ -916,13 +918,13 @@ "grafanaMaturityCount": 0, "lineageIsGroup": false, "links": { - "docs": "n/a", - "go": "n/a", - "schema": "n/a", - "ts": "n/a" + "docs": "https://grafana.com/docs/grafana/next/developers/kinds/composable/lokidataquery/schema-reference", + "go": "https://github.com/grafana/grafana/tree/main/pkg/tsdb/loki/kinds/dataquery/types_dataquery_gen.go", + "schema": "https://github.com/grafana/grafana/tree/main/public/app/plugins/datasource/loki/dataquery.cue", + "ts": "https://github.com/grafana/grafana/tree/main/public/app/plugins/datasource/loki/dataquery.gen.ts" }, "machineName": "lokidataquery", - "maturity": "planned", + "maturity": "experimental", "name": "LokiDataQuery", "pluralMachineName": "lokidataquerys", "pluralName": "LokiDataQuerys", @@ -1981,6 +1983,7 @@ "gaugepanelcfg", "histogrampanelcfg", "librarypanel", + "lokidataquery", "newspanelcfg", "nodegraphpanelcfg", "phlaredataquery", @@ -1993,7 +1996,7 @@ "textpanelcfg", "xychartpanelcfg" ], - "count": 19 + "count": 20 }, "mature": { "name": "mature", @@ -2045,7 +2048,6 @@ "jaegerdatasourcecfg", "livepanelcfg", "logspanelcfg", - "lokidataquery", "lokidatasourcecfg", "microsoftsqlserverdataquery", "microsoftsqlserverdatasourcecfg", @@ -2070,7 +2072,7 @@ "zipkindataquery", "zipkindatasourcecfg" ], - "count": 53 + "count": 52 }, "stable": { "name": "stable", diff --git a/pkg/tsdb/loki/kinds/dataquery/types_dataquery_gen.go b/pkg/tsdb/loki/kinds/dataquery/types_dataquery_gen.go new file mode 100644 index 00000000000..02706b278e7 --- /dev/null +++ b/pkg/tsdb/loki/kinds/dataquery/types_dataquery_gen.go @@ -0,0 +1,105 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. +// +// Generated by: +// public/app/plugins/gen.go +// Using jennies: +// PluginGoTypesJenny +// +// Run 'make gen-cue' from repository root to regenerate. + +package dataquery + +// Defines values for EditorMode. +const ( + EditorModeBuilder EditorMode = "builder" + + EditorModeCode EditorMode = "code" +) + +// Defines values for LokiQueryDirection. +const ( + LokiQueryDirectionBackward LokiQueryDirection = "backward" + + LokiQueryDirectionForward LokiQueryDirection = "forward" +) + +// Defines values for LokiQueryType. +const ( + LokiQueryTypeInstant LokiQueryType = "instant" + + LokiQueryTypeRange LokiQueryType = "range" + + LokiQueryTypeStream LokiQueryType = "stream" +) + +// Defines values for QueryEditorMode. +const ( + QueryEditorModeBuilder QueryEditorMode = "builder" + + QueryEditorModeCode QueryEditorMode = "code" +) + +// Defines values for SupportingQueryType. +const ( + SupportingQueryTypeDataSample SupportingQueryType = "dataSample" + + SupportingQueryTypeLogsSample SupportingQueryType = "logsSample" + + SupportingQueryTypeLogsVolume SupportingQueryType = "logsVolume" +) + +// LokiDataQuery defines model for LokiDataQuery. +type LokiDataQuery struct { + // For mixed data sources the selected datasource is on the query level. + // For non mixed scenarios this is undefined. + // TODO find a better way to do this ^ that's friendly to schema + // TODO this shouldn't be unknown but DataSourceRef | null + Datasource *interface{} `json:"datasource,omitempty"` + EditorMode *EditorMode `json:"editorMode,omitempty"` + + // The LogQL query. + Expr string `json:"expr"` + + // true if query is disabled (ie should not be returned to the dashboard) + Hide *bool `json:"hide,omitempty"` + + // @deprecated, now use queryType. + Instant *bool `json:"instant,omitempty"` + + // Unique, guid like, string used in explore mode + Key *string `json:"key,omitempty"` + + // Used to override the name of the series. + LegendFormat *string `json:"legendFormat,omitempty"` + + // Used to limit the number of log rows returned. + MaxLines *int64 `json:"maxLines,omitempty"` + + // Specify the query flavor + // TODO make this required and give it a default + QueryType *string `json:"queryType,omitempty"` + + // @deprecated, now use queryType. + Range *bool `json:"range,omitempty"` + + // A - Z + RefId string `json:"refId"` + + // Used to scale the interval value. + Resolution *int64 `json:"resolution,omitempty"` +} + +// EditorMode defines model for LokiDataQuery.EditorMode. +type EditorMode string + +// LokiQueryDirection defines model for LokiQueryDirection. +type LokiQueryDirection string + +// LokiQueryType defines model for LokiQueryType. +type LokiQueryType string + +// QueryEditorMode defines model for QueryEditorMode. +type QueryEditorMode string + +// SupportingQueryType defines model for SupportingQueryType. +type SupportingQueryType string diff --git a/pkg/tsdb/loki/loki.go b/pkg/tsdb/loki/loki.go index 06c57a90924..ced18ad9fd4 100644 --- a/pkg/tsdb/loki/loki.go +++ b/pkg/tsdb/loki/loki.go @@ -19,6 +19,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/tsdb/loki/kinds/dataquery" ) var logger = log.New("tsdb.loki") @@ -57,15 +58,9 @@ type datasourceInfo struct { } type QueryJSONModel struct { - QueryType string `json:"queryType"` - Expr string `json:"expr"` - Direction string `json:"direction"` - LegendFormat string `json:"legendFormat"` - Interval string `json:"interval"` - IntervalMS int `json:"intervalMS"` - Resolution int64 `json:"resolution"` - MaxLines int `json:"maxLines"` - SupportingQueryType string `json:"supportingQueryType"` + dataquery.LokiDataQuery + Direction *string `json:"direction,omitempty"` + SupportingQueryType *string `json:"supportingQueryType"` } func parseQueryModel(raw json.RawMessage) (*QueryJSONModel, error) { diff --git a/pkg/tsdb/loki/parse_query.go b/pkg/tsdb/loki/parse_query.go index b4b1f889088..f510f0c43bb 100644 --- a/pkg/tsdb/loki/parse_query.go +++ b/pkg/tsdb/loki/parse_query.go @@ -53,48 +53,57 @@ func interpolateVariables(expr string, interval time.Duration, timeRange time.Du return expr } -func parseQueryType(jsonValue string) (QueryType, error) { - switch jsonValue { - case "instant": - return QueryTypeInstant, nil - case "range": - return QueryTypeRange, nil - case "": +func parseQueryType(jsonPointerValue *string) (QueryType, error) { + if jsonPointerValue == nil { // there are older queries stored in alerting that did not have queryType, // those were range-queries return QueryTypeRange, nil - default: - return QueryTypeRange, fmt.Errorf("invalid queryType: %s", jsonValue) + } else { + jsonValue := *jsonPointerValue + switch jsonValue { + case "instant": + return QueryTypeInstant, nil + case "range": + return QueryTypeRange, nil + default: + return QueryTypeRange, fmt.Errorf("invalid queryType: %s", jsonValue) + } } } -func parseDirection(jsonValue string) (Direction, error) { - switch jsonValue { - case "backward": - return DirectionBackward, nil - case "forward": - return DirectionForward, nil - case "": +func parseDirection(jsonPointerValue *string) (Direction, error) { + if jsonPointerValue == nil { // there are older queries stored in alerting that did not have queryDirection, // we default to "backward" return DirectionBackward, nil - default: - return DirectionBackward, fmt.Errorf("invalid queryDirection: %s", jsonValue) + } else { + jsonValue := *jsonPointerValue + switch jsonValue { + case "backward": + return DirectionBackward, nil + case "forward": + return DirectionForward, nil + default: + return DirectionBackward, fmt.Errorf("invalid queryDirection: %s", jsonValue) + } } } -func parseSupportingQueryType(jsonValue string) (SupportingQueryType, error) { - switch jsonValue { - case "logsVolume": - return SupportingQueryLogsVolume, nil - case "logsSample": - return SupportingQueryLogsSample, nil - case "dataSample": - return SupportingQueryDataSample, nil - case "": +func parseSupportingQueryType(jsonPointerValue *string) (SupportingQueryType, error) { + if jsonPointerValue == nil { return SupportingQueryNone, nil - default: - return SupportingQueryNone, fmt.Errorf("invalid supportingQueryType: %s", jsonValue) + } else { + jsonValue := *jsonPointerValue + switch jsonValue { + case "logsVolume": + return SupportingQueryLogsVolume, nil + case "logsSample": + return SupportingQueryLogsSample, nil + case "dataSample": + return SupportingQueryDataSample, nil + default: + return SupportingQueryNone, fmt.Errorf("invalid supportingQueryType: %s", jsonValue) + } } } @@ -110,8 +119,8 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { end := query.TimeRange.To var resolution int64 = 1 - if model.Resolution >= 1 && model.Resolution <= 5 || model.Resolution == 10 { - resolution = model.Resolution + if model.Resolution != nil && (*model.Resolution >= 1 && *model.Resolution <= 5 || *model.Resolution == 10) { + resolution = *model.Resolution } interval := query.Interval @@ -131,6 +140,16 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { return nil, err } + var maxLines int64 + if model.MaxLines != nil { + maxLines = *model.MaxLines + } + + var legendFormat string + if model.LegendFormat != nil { + legendFormat = *model.LegendFormat + } + supportingQueryType, err := parseSupportingQueryType(model.SupportingQueryType) if err != nil { return nil, err @@ -141,8 +160,8 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) { QueryType: queryType, Direction: direction, Step: step, - MaxLines: model.MaxLines, - LegendFormat: model.LegendFormat, + MaxLines: int(maxLines), + LegendFormat: legendFormat, Start: start, End: end, RefID: query.RefID, diff --git a/pkg/tsdb/loki/types.go b/pkg/tsdb/loki/types.go index c2f1b130fb5..06f8b1836b5 100644 --- a/pkg/tsdb/loki/types.go +++ b/pkg/tsdb/loki/types.go @@ -1,27 +1,30 @@ package loki -import "time" +import ( + "time" -type QueryType string -type SupportingQueryType string + "github.com/grafana/grafana/pkg/tsdb/loki/kinds/dataquery" +) + +type QueryType = dataquery.LokiQueryType +type SupportingQueryType = dataquery.SupportingQueryType +type Direction = dataquery.LokiQueryDirection const ( - QueryTypeRange QueryType = "range" - QueryTypeInstant QueryType = "instant" + QueryTypeRange = dataquery.LokiQueryTypeRange + QueryTypeInstant = dataquery.LokiQueryTypeInstant ) const ( - SupportingQueryLogsVolume SupportingQueryType = "logsVolume" - SupportingQueryLogsSample SupportingQueryType = "logsSample" - SupportingQueryDataSample SupportingQueryType = "dataSample" + SupportingQueryLogsVolume = dataquery.SupportingQueryTypeLogsVolume + SupportingQueryLogsSample = dataquery.SupportingQueryTypeLogsSample + SupportingQueryDataSample = dataquery.SupportingQueryTypeDataSample SupportingQueryNone SupportingQueryType = "none" ) -type Direction string - const ( - DirectionBackward Direction = "backward" - DirectionForward Direction = "forward" + DirectionBackward = dataquery.LokiQueryDirectionBackward + DirectionForward = dataquery.LokiQueryDirectionForward ) type lokiQuery struct { diff --git a/public/app/plugins/datasource/loki/dataquery.cue b/public/app/plugins/datasource/loki/dataquery.cue new file mode 100644 index 00000000000..c327d4f44e4 --- /dev/null +++ b/public/app/plugins/datasource/loki/dataquery.cue @@ -0,0 +1,61 @@ +// Copyright 2023 Grafana Labs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grafanaplugin + +import ( + "github.com/grafana/grafana/packages/grafana-schema/src/common" + "github.com/grafana/grafana/pkg/plugins/pfs" +) + +// This file (with its sibling .cue files) implements pfs.GrafanaPlugin +pfs.GrafanaPlugin + +composableKinds: DataQuery: { + maturity: "experimental" + + lineage: { + seqs: [ + { + schemas: [ + { + common.DataQuery + + // The LogQL query. + expr: string + // Used to override the name of the series. + legendFormat?: string + // Used to limit the number of log rows returned. + maxLines?: int64 + // Used to scale the interval value. + resolution?: int64 + editorMode?: #QueryEditorMode + // @deprecated, now use queryType. + range?: bool + // @deprecated, now use queryType. + instant?: bool + + #QueryEditorMode: "code" | "builder" @cuetsy(kind="enum") + + #LokiQueryType: "range" | "instant" | "stream" @cuetsy(kind="enum") + + #SupportingQueryType: "logsVolume" | "logsSample" | "dataSample" @cuetsy(kind="enum") + + #LokiQueryDirection: "forward" | "backward" @cuetsy(kind="enum") + }, + ] + }, + ] + } +} diff --git a/public/app/plugins/datasource/loki/dataquery.gen.ts b/public/app/plugins/datasource/loki/dataquery.gen.ts new file mode 100644 index 00000000000..aab59830ff4 --- /dev/null +++ b/public/app/plugins/datasource/loki/dataquery.gen.ts @@ -0,0 +1,63 @@ +// Code generated - EDITING IS FUTILE. DO NOT EDIT. +// +// Generated by: +// public/app/plugins/gen.go +// Using jennies: +// TSTypesJenny +// PluginTSTypesJenny +// +// Run 'make gen-cue' from repository root to regenerate. + +import * as common from '@grafana/schema'; + +export const DataQueryModelVersion = Object.freeze([0, 0]); + +export enum QueryEditorMode { + Builder = 'builder', + Code = 'code', +} + +export enum LokiQueryType { + Instant = 'instant', + Range = 'range', + Stream = 'stream', +} + +export enum SupportingQueryType { + DataSample = 'dataSample', + LogsSample = 'logsSample', + LogsVolume = 'logsVolume', +} + +export enum LokiQueryDirection { + Backward = 'backward', + Forward = 'forward', +} + +export interface Loki extends common.DataQuery { + editorMode?: QueryEditorMode; + /** + * The LogQL query. + */ + expr: string; + /** + * @deprecated, now use queryType. + */ + instant?: boolean; + /** + * Used to override the name of the series. + */ + legendFormat?: string; + /** + * Used to limit the number of log rows returned. + */ + maxLines?: number; + /** + * @deprecated, now use queryType. + */ + range?: boolean; + /** + * Used to scale the interval value. + */ + resolution?: number; +} diff --git a/public/app/plugins/datasource/loki/types.ts b/public/app/plugins/datasource/loki/types.ts index ec4650b12b7..30a1c7160b7 100644 --- a/public/app/plugins/datasource/loki/types.ts +++ b/public/app/plugins/datasource/loki/types.ts @@ -1,6 +1,8 @@ import { DataQuery, DataSourceJsonData, QueryResultMeta, ScopedVars } from '@grafana/data'; -import { QueryEditorMode } from '../prometheus/querybuilder/shared/types'; +import { Loki as LokiQueryFromSchema, LokiQueryType, SupportingQueryType, LokiQueryDirection } from './dataquery.gen'; + +export { LokiQueryDirection, LokiQueryType, SupportingQueryType }; export interface LokiInstantQueryRequest { query: string; @@ -24,31 +26,15 @@ export enum LokiResultType { Matrix = 'matrix', } -export enum LokiQueryType { - Range = 'range', - Instant = 'instant', - Stream = 'stream', -} - -export enum LokiQueryDirection { - Backward = 'backward', - Forward = 'forward', -} - -export interface LokiQuery extends DataQuery { - queryType?: LokiQueryType; - expr: string; +export interface LokiQuery extends LokiQueryFromSchema { direction?: LokiQueryDirection; - legendFormat?: string; - maxLines?: number; - resolution?: number; /** Used only to identify supporting queries, e.g. logs volume, logs sample and data sample */ supportingQueryType?: SupportingQueryType; - /* @deprecated now use queryType */ - range?: boolean; - /* @deprecated now use queryType */ - instant?: boolean; - editorMode?: QueryEditorMode; + // CUE autogenerates `queryType` as `?string`, as that's how it is defined + // in the parent-interface (in DataQuery). + // the temporary fix (until this gets improved in the codegen), is to + // override it here + queryType?: LokiQueryType; } export interface LokiOptions extends DataSourceJsonData { @@ -161,12 +147,6 @@ export interface QueryStats { entries: number; } -export enum SupportingQueryType { - LogsVolume = 'logsVolume', - LogsSample = 'logsSample', - DataSample = 'dataSample', -} - export interface ContextFilter { enabled: boolean; label: string;