From b392bba74567fca5bb06fbb21d0f6f8d3f7b5d77 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 16 Sep 2019 07:17:34 +0200 Subject: [PATCH] Loki: Updated cheat sheet with new filter syntax (#18947) * Loki: Updated cheat sheet with new filter syntax - updated cheat sheet with new filter syntax - added user-specific examples from the user's label set - added link to LogQL docs - separated styles for examples (clickable) and expressions * Review feedback --- packages/grafana-ui/src/types/datasource.ts | 1 + public/app/features/explore/Explore.tsx | 6 +- .../loki/components/LokiCheatSheet.tsx | 138 +++++++++++++----- .../loki/components/LokiStartPage.tsx | 13 -- .../datasource/loki/language_provider.ts | 14 +- public/app/plugins/datasource/loki/module.ts | 4 +- .../prometheus/components/PromCheatSheet.tsx | 7 +- .../prometheus/components/PromStart.tsx | 13 -- .../plugins/datasource/prometheus/module.ts | 4 +- public/sass/pages/_explore.scss | 2 +- 10 files changed, 126 insertions(+), 76 deletions(-) delete mode 100644 public/app/plugins/datasource/loki/components/LokiStartPage.tsx delete mode 100644 public/app/plugins/datasource/prometheus/components/PromStart.tsx diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 44b60e4f335..b80543f4e73 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -299,6 +299,7 @@ export interface ExploreQueryFieldProps< } export interface ExploreStartPageProps { + datasource?: DataSourceApi; onClickExample: (query: DataQuery) => void; } diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index 96b4f4d6a2b..3adcd5221d0 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -286,7 +286,11 @@ export class Explore extends React.PureComponent { return (
- {showingStartPage && } + {showingStartPage && ( +
+ +
+ )} {!showingStartPage && ( <> {mode === ExploreMode.Metrics && ( diff --git a/public/app/plugins/datasource/loki/components/LokiCheatSheet.tsx b/public/app/plugins/datasource/loki/components/LokiCheatSheet.tsx index 35df8959e9d..c6b9b314bc3 100644 --- a/public/app/plugins/datasource/loki/components/LokiCheatSheet.tsx +++ b/public/app/plugins/datasource/loki/components/LokiCheatSheet.tsx @@ -1,43 +1,101 @@ -import React from 'react'; +import React, { PureComponent } from 'react'; +import { shuffle } from 'lodash'; +import { ExploreStartPageProps, DataQuery } from '@grafana/ui'; +import LokiLanguageProvider from '../language_provider'; -const CHEAT_SHEET_ITEMS = [ - { - title: 'See your logs', - label: 'Start by selecting a log stream from the Log labels selector.', - }, - { - title: 'Logs from a "job"', - expression: '{job="default/prometheus"}', - label: 'Returns all log lines emitted by instances of this job.', - }, - { - title: 'Combine stream selectors', - expression: '{app="cassandra",namespace="prod"}', - label: 'Returns all log lines from streams that have both labels.', - }, - { - title: 'Search for text', - expression: '{app="cassandra"} (duration|latency)\\s*(=|is|of)\\s*[\\d\\.]+', - label: 'Add a regular expression after the selector to filter for.', - }, -]; +const DEFAULT_EXAMPLES = ['{job="default/prometheus"}']; +const PREFERRED_LABELS = ['job', 'app', 'k8s_app']; +const EXAMPLES_LIMIT = 5; -export default (props: any) => ( -
-

Loki Cheat Sheet

- {CHEAT_SHEET_ITEMS.map(item => ( -
-
{item.title}
- {item.expression && ( -
props.onClickExample({ refId: 'A', expr: item.expression })} - > - {item.expression} -
- )} -
{item.label}
+export default class LokiCheatSheet extends PureComponent { + userLabelTimer: NodeJS.Timeout; + state = { + userExamples: DEFAULT_EXAMPLES, + }; + + componentDidMount() { + this.scheduleUserLabelChecking(); + } + + componentWillUnmount() { + clearTimeout(this.userLabelTimer); + } + + scheduleUserLabelChecking() { + this.userLabelTimer = setTimeout(this.checkUserLabels, 1000); + } + + checkUserLabels = async () => { + // Set example from user labels + const provider: LokiLanguageProvider = this.props.datasource.languageProvider; + if (provider.started) { + const labels = provider.getLabelKeys() || []; + const preferredLabel = PREFERRED_LABELS.find(l => labels.includes(l)); + if (preferredLabel) { + const values = await provider.getLabelValues(preferredLabel); + const userExamples = shuffle(values) + .slice(0, EXAMPLES_LIMIT) + .map(value => `{${preferredLabel}="${value}"}`); + this.setState({ userExamples }); + } + } else { + this.scheduleUserLabelChecking(); + } + }; + + renderExpression(expr: string) { + const { onClickExample } = this.props; + + return ( +
onClickExample({ refId: 'A', expr } as DataQuery)} + > + {expr}
- ))} -
-); + ); + } + + render() { + const { userExamples } = this.state; + + return ( +
+

Loki Cheat Sheet

+
+
See your logs
+
Start by selecting a log stream from the Log labels selector.
+
+ Alternatively, you can write a stream selector into the query field: +
+ {this.renderExpression('{job="default/prometheus"}')} + {userExamples !== DEFAULT_EXAMPLES && userExamples.length > 0 ? ( +
+
Here are some example streams from your logs:
+ {userExamples.map(example => this.renderExpression(example))} +
+ ) : null} +
+
+
Combine stream selectors
+ {this.renderExpression('{app="cassandra",namespace="prod"}')} +
Returns all log lines from streams that have both labels.
+
+ +
+
Filtering for search terms.
+ {this.renderExpression('{app="cassandra"} |~ "(duration|latency)s*(=|is|of)s*[d.]+"')} + {this.renderExpression('{app="cassandra"} |= "exact match"')} + {this.renderExpression('{app="cassandra"} != "do not match"')} +
+ + LogQL + {' '} + supports exact and regular expression filters. +
+
+
+ ); + } +} diff --git a/public/app/plugins/datasource/loki/components/LokiStartPage.tsx b/public/app/plugins/datasource/loki/components/LokiStartPage.tsx deleted file mode 100644 index 62063a790ec..00000000000 --- a/public/app/plugins/datasource/loki/components/LokiStartPage.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { PureComponent } from 'react'; -import LokiCheatSheet from './LokiCheatSheet'; -import { ExploreStartPageProps } from '@grafana/ui'; - -export default class LokiStartPage extends PureComponent { - render() { - return ( -
- -
- ); - } -} diff --git a/public/app/plugins/datasource/loki/language_provider.ts b/public/app/plugins/datasource/loki/language_provider.ts index 36c5eb11860..44ba031255f 100644 --- a/public/app/plugins/datasource/loki/language_provider.ts +++ b/public/app/plugins/datasource/loki/language_provider.ts @@ -86,11 +86,23 @@ export default class LokiLanguageProvider extends LanguageProvider { */ start = () => { if (!this.startTask) { - this.startTask = this.fetchLogLabels(this.initialRange); + this.startTask = this.fetchLogLabels(this.initialRange).then(() => { + this.started = true; + return []; + }); } return this.startTask; }; + getLabelKeys(): string[] { + return this.labelKeys[EMPTY_SELECTOR]; + } + + async getLabelValues(key: string): Promise { + await this.fetchLabelValues(key, this.initialRange); + return this.labelValues[EMPTY_SELECTOR][key]; + } + /** * Return suggestions based on input that can be then plugged into a typeahead dropdown. * Keep this DOM-free for testing diff --git a/public/app/plugins/datasource/loki/module.ts b/public/app/plugins/datasource/loki/module.ts index b1b5bb46370..652a596e371 100644 --- a/public/app/plugins/datasource/loki/module.ts +++ b/public/app/plugins/datasource/loki/module.ts @@ -1,6 +1,6 @@ import Datasource from './datasource'; -import LokiStartPage from './components/LokiStartPage'; +import LokiCheatSheet from './components/LokiCheatSheet'; import LokiQueryField from './components/LokiQueryField'; import LokiQueryEditor from './components/LokiQueryEditor'; import { LokiAnnotationsQueryCtrl } from './LokiAnnotationsQueryCtrl'; @@ -14,6 +14,6 @@ export { LokiQueryEditor as QueryEditor, LokiConfigCtrl as ConfigCtrl, LokiQueryField as ExploreQueryField, - LokiStartPage as ExploreStartPage, + LokiCheatSheet as ExploreStartPage, LokiAnnotationsQueryCtrl as AnnotationsQueryCtrl, }; diff --git a/public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx b/public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx index f3b3dcb7f83..e6aebfb7805 100644 --- a/public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { ExploreStartPageProps, DataQuery } from '@grafana/ui'; const CHEAT_SHEET_ITEMS = [ { @@ -19,15 +20,15 @@ const CHEAT_SHEET_ITEMS = [ }, ]; -export default (props: any) => ( +export default (props: ExploreStartPageProps) => (

PromQL Cheat Sheet

{CHEAT_SHEET_ITEMS.map(item => (
{item.title}
props.onClickExample({ refId: 'A', expr: item.expression })} + className="cheat-sheet-item__example" + onClick={e => props.onClickExample({ refId: 'A', expr: item.expression } as DataQuery)} > {item.expression}
diff --git a/public/app/plugins/datasource/prometheus/components/PromStart.tsx b/public/app/plugins/datasource/prometheus/components/PromStart.tsx deleted file mode 100644 index de545e826e3..00000000000 --- a/public/app/plugins/datasource/prometheus/components/PromStart.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { PureComponent } from 'react'; -import PromCheatSheet from './PromCheatSheet'; -import { ExploreStartPageProps } from '@grafana/ui'; - -export default class PromStart extends PureComponent { - render() { - return ( -
- -
- ); - } -} diff --git a/public/app/plugins/datasource/prometheus/module.ts b/public/app/plugins/datasource/prometheus/module.ts index 0922ce0d3f6..5250868e7ec 100644 --- a/public/app/plugins/datasource/prometheus/module.ts +++ b/public/app/plugins/datasource/prometheus/module.ts @@ -2,7 +2,7 @@ import { PrometheusDatasource } from './datasource'; import { PromQueryEditor } from './components/PromQueryEditor'; import { PrometheusConfigCtrl } from './config_ctrl'; -import PrometheusStartPage from './components/PromStart'; +import PromCheatSheet from './components/PromCheatSheet'; import PromQueryField from './components/PromQueryField'; class PrometheusAnnotationsQueryCtrl { @@ -15,5 +15,5 @@ export { PrometheusConfigCtrl as ConfigCtrl, PrometheusAnnotationsQueryCtrl as AnnotationsQueryCtrl, PromQueryField as ExploreQueryField, - PrometheusStartPage as ExploreStartPage, + PromCheatSheet as ExploreStartPage, }; diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index 0018eaa7db3..df924a14bde 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -345,7 +345,7 @@ font-size: $font-size-h3; } -.cheat-sheet-item__expression { +.cheat-sheet-item__example { margin: $space-xs 0; cursor: pointer; }