From cc90f9bb693e7fc4303a82d16c0b88bc85c22921 Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Thu, 2 Jun 2022 13:50:58 +0200 Subject: [PATCH] Prometheus/Loki: Add raw query and syntax highlight in explain mode (#50070) --- .../components/LokiQueryBuilderExplained.tsx | 21 ++++++++--- .../querybuilder/components/QueryPreview.tsx | 24 ++----------- .../components/PromQueryBuilderExplained.tsx | 20 ++++++++--- .../querybuilder/components/QueryPreview.tsx | 26 ++------------ .../shared/OperationExplainedBox.tsx | 15 ++++---- .../shared/OperationListExplained.tsx | 22 ++++++++++-- .../querybuilder/shared/RawQuery.tsx | 36 +++++++++++++++++++ 7 files changed, 101 insertions(+), 63 deletions(-) create mode 100644 public/app/plugins/datasource/prometheus/querybuilder/shared/RawQuery.tsx diff --git a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderExplained.tsx b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderExplained.tsx index 257ff64722c..236267c5163 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderExplained.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilderExplained.tsx @@ -3,25 +3,38 @@ import React from 'react'; import { Stack } from '@grafana/experimental'; import { OperationExplainedBox } from 'app/plugins/datasource/prometheus/querybuilder/shared/OperationExplainedBox'; import { OperationListExplained } from 'app/plugins/datasource/prometheus/querybuilder/shared/OperationListExplained'; +import { RawQuery } from 'app/plugins/datasource/prometheus/querybuilder/shared/RawQuery'; +import { lokiGrammar } from '../../syntax'; import { lokiQueryModeller } from '../LokiQueryModeller'; import { buildVisualQueryFromString } from '../parsing'; import { LokiVisualQuery } from '../types'; export interface Props { query: string; - nested?: boolean; } -export const LokiQueryBuilderExplained = React.memo(({ query, nested }) => { +export const LokiQueryBuilderExplained = React.memo(({ query }) => { const visQuery = buildVisualQueryFromString(query || '').query; + const lang = { grammar: lokiGrammar, name: 'lokiql' }; return ( - + + + + } + > Fetch all log lines matching label filters. - stepNumber={2} queryModeller={lokiQueryModeller} query={visQuery} /> + + stepNumber={2} + queryModeller={lokiQueryModeller} + query={visQuery} + lang={lang} + /> ); }); diff --git a/public/app/plugins/datasource/loki/querybuilder/components/QueryPreview.tsx b/public/app/plugins/datasource/loki/querybuilder/components/QueryPreview.tsx index e7726df257c..64e5fe16d91 100644 --- a/public/app/plugins/datasource/loki/querybuilder/components/QueryPreview.tsx +++ b/public/app/plugins/datasource/loki/querybuilder/components/QueryPreview.tsx @@ -1,11 +1,8 @@ -import { css, cx } from '@emotion/css'; -import Prism from 'prismjs'; import React from 'react'; -import { GrafanaTheme2 } from '@grafana/data'; import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/experimental'; -import { useTheme2 } from '@grafana/ui'; +import { RawQuery } from '../../../prometheus/querybuilder/shared/RawQuery'; import { lokiGrammar } from '../../syntax'; export interface Props { @@ -13,30 +10,13 @@ export interface Props { } export function QueryPreview({ query }: Props) { - const theme = useTheme2(); - const styles = getStyles(theme); - const highlighted = Prism.highlight(query, lokiGrammar, 'lokiql'); - return ( -
+ ); } - -const getStyles = (theme: GrafanaTheme2) => { - return { - editorField: css({ - fontFamily: theme.typography.fontFamilyMonospace, - fontSize: theme.typography.bodySmall.fontSize, - }), - }; -}; diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderExplained.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderExplained.tsx index 422f4b3b231..80d223d1406 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderExplained.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderExplained.tsx @@ -2,29 +2,39 @@ import React from 'react'; import { Stack } from '@grafana/experimental'; +import promqlGrammar from '../../promql'; import { promQueryModeller } from '../PromQueryModeller'; import { buildVisualQueryFromString } from '../parsing'; import { OperationExplainedBox } from '../shared/OperationExplainedBox'; import { OperationListExplained } from '../shared/OperationListExplained'; +import { RawQuery } from '../shared/RawQuery'; import { PromVisualQuery } from '../types'; export interface Props { query: string; - nested?: boolean; } -export const PromQueryBuilderExplained = React.memo(({ query, nested }) => { +export const PromQueryBuilderExplained = React.memo(({ query }) => { const visQuery = buildVisualQueryFromString(query || '').query; + const lang = { grammar: promqlGrammar, name: 'promql' }; return ( - + + + + } > Fetch all series matching metric name and label filters. - stepNumber={2} queryModeller={promQueryModeller} query={visQuery} /> + + stepNumber={2} + queryModeller={promQueryModeller} + query={visQuery} + lang={lang} + /> ); }); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/QueryPreview.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/QueryPreview.tsx index 7ff6bfcb9f4..853185268ba 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/QueryPreview.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/QueryPreview.tsx @@ -1,42 +1,22 @@ -import { css, cx } from '@emotion/css'; -import Prism from 'prismjs'; import React from 'react'; -import { GrafanaTheme2 } from '@grafana/data'; import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/experimental'; -import { useTheme2 } from '@grafana/ui'; -import { promqlGrammar } from '../../promql'; +import promqlGrammar from '../../promql'; +import { RawQuery } from '../shared/RawQuery'; export interface Props { query: string; } export function QueryPreview({ query }: Props) { - const theme = useTheme2(); - const styles = getStyles(theme); - const highlighted = Prism.highlight(query, promqlGrammar, 'promql'); - return ( -
+ ); } - -const getStyles = (theme: GrafanaTheme2) => { - return { - editorField: css({ - fontFamily: theme.typography.fontFamilyMonospace, - fontSize: theme.typography.bodySmall.fontSize, - }), - }; -}; diff --git a/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationExplainedBox.tsx b/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationExplainedBox.tsx index 867c03b2cb2..302b4b7d744 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationExplainedBox.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationExplainedBox.tsx @@ -5,10 +5,10 @@ import { GrafanaTheme2, renderMarkdown } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; export interface Props { - title: string; + title?: React.ReactNode; children?: React.ReactNode; markdown?: string; - stepNumber: number; + stepNumber?: number; } export function OperationExplainedBox({ title, stepNumber, markdown, children }: Props) { @@ -16,11 +16,13 @@ export function OperationExplainedBox({ title, stepNumber, markdown, children }: return (
-
{stepNumber}
+ {stepNumber !== undefined &&
{stepNumber}
}
-
- {title} -
+ {title && ( +
+ {title} +
+ )}
{markdown &&
} {children} @@ -37,7 +39,6 @@ const getStyles = (theme: GrafanaTheme2) => { padding: theme.spacing(1), borderRadius: theme.shape.borderRadius(), position: 'relative', - marginBottom: theme.spacing(0.5), }), boxInner: css({ marginLeft: theme.spacing(4), diff --git a/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationListExplained.tsx b/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationListExplained.tsx index 1bae2ed76db..9e83131c174 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationListExplained.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationListExplained.tsx @@ -1,6 +1,8 @@ +import { Grammar } from 'prismjs'; import React from 'react'; import { OperationExplainedBox } from './OperationExplainedBox'; +import { RawQuery } from './RawQuery'; import { QueryWithOperations, VisualQueryModeller } from './types'; export interface Props { @@ -8,9 +10,18 @@ export interface Props { queryModeller: VisualQueryModeller; explainMode?: boolean; stepNumber: number; + lang: { + grammar: Grammar; + name: string; + }; } -export function OperationListExplained({ query, queryModeller, stepNumber }: Props) { +export function OperationListExplained({ + query, + queryModeller, + stepNumber, + lang, +}: Props) { return ( <> {query.operations.map((op, index) => { @@ -21,7 +32,14 @@ export function OperationListExplained({ query, q const title = def.renderer(op, def, ''); const body = def.explainHandler ? def.explainHandler(op, def) : def.documentation ?? 'no docs'; - return ; + return ( + } + markdown={body} + /> + ); })} ); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/shared/RawQuery.tsx b/public/app/plugins/datasource/prometheus/querybuilder/shared/RawQuery.tsx new file mode 100644 index 00000000000..57151312947 --- /dev/null +++ b/public/app/plugins/datasource/prometheus/querybuilder/shared/RawQuery.tsx @@ -0,0 +1,36 @@ +import { css, cx } from '@emotion/css'; +import Prism, { Grammar } from 'prismjs'; +import React from 'react'; + +import { GrafanaTheme2 } from '@grafana/data/src'; +import { useTheme2 } from '@grafana/ui/src'; + +export interface Props { + query: string; + lang: { + grammar: Grammar; + name: string; + }; +} +export function RawQuery({ query, lang }: Props) { + const theme = useTheme2(); + const styles = getStyles(theme); + const highlighted = Prism.highlight(query, lang.grammar, lang.name); + + return ( +
+ ); +} + +const getStyles = (theme: GrafanaTheme2) => { + return { + editorField: css({ + fontFamily: theme.typography.fontFamilyMonospace, + fontSize: theme.typography.bodySmall.fontSize, + }), + }; +};