prometheus: enable new monaco-based query field (#41357)

* prometheus: enable new monaco-based query field

* updated test

* updated tests

* fix e2e tests

* updated comment
This commit is contained in:
Gábor Farkas 2021-11-08 14:20:48 +01:00 committed by GitHub
parent e31bd2df2f
commit 9d82111a1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 57 additions and 35 deletions

View File

@ -46,6 +46,14 @@ describe('Exemplars', () => {
e2e.components.DataSourcePicker.input().should('be.visible').click();
e2e().contains(dataSourceName).scrollIntoView().should('be.visible').click();
// we need to wait for the query-field being lazy-loaded, in two steps:
// 1. first we wait for the text 'Loading...' to appear
// 1. then we wait for the text 'Loading...' to disappear
const monacoLoadingText = 'Loading...';
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
e2e.components.TimePicker.openButton().click();
e2e.components.TimePicker.fromField().clear().type('2021-07-10 17:10:00');
e2e.components.TimePicker.toField().clear().type('2021-07-10 17:30:00');

View File

@ -13,7 +13,15 @@ e2e.scenario({
cy.contains('gdev-prometheus').scrollIntoView().should('be.visible').click();
const queryText = 'http_requests_total';
e2e.components.QueryField.container().should('be.visible').type(queryText).type('{backspace}');
// we need to wait for the query-field being lazy-loaded, in two steps:
// it is a two-step process:
// 1. first we wait for the text 'Loading...' to appear
// 1. then we wait for the text 'Loading...' to disappear
const monacoLoadingText = 'Loading...';
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
e2e.components.QueryField.container().type(queryText).type('{backspace}');
cy.contains(queryText.slice(0, -1)).should('be.visible');

View File

@ -50,7 +50,6 @@ export interface FeatureToggles {
tempoServiceGraph: boolean;
tempoSearch: boolean;
recordedQueries: boolean;
prometheusMonaco: boolean;
newNavigation: boolean;
fullRangeLogsVolume: boolean;
autoLoadFullRangeLogsVolume: boolean;

View File

@ -66,7 +66,6 @@ export class GrafanaBootConfig implements GrafanaConfig {
tempoServiceGraph: false,
tempoSearch: false,
recordedQueries: false,
prometheusMonaco: false,
newNavigation: false,
fullRangeLogsVolume: false,
autoLoadFullRangeLogsVolume: false,

View File

@ -6,6 +6,16 @@ import { PrometheusDatasource } from '../datasource';
import { PromQuery } from '../types';
import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
// the monaco-based editor uses lazy-loading and that does not work
// well with this test, and we do not need the monaco-related
// functionality in this test anyway, so we mock it out.
jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
const fakeQueryField = () => <div>prometheus query field</div>;
return {
MonacoQueryFieldWrapper: fakeQueryField,
};
});
const setup = (renderMethod: any, propOverrides?: object) => {
const datasourceMock: unknown = {
languageProvider: {

View File

@ -7,6 +7,16 @@ import { PrometheusDatasource } from '../datasource';
import { testIds as alertingTestIds } from './PromQueryEditorForAlerting';
import { testIds as regularTestIds } from './PromQueryEditor';
// the monaco-based editor uses lazy-loading and that does not work
// well with this test, and we do not need the monaco-related
// functionality in this test anyway, so we mock it out.
jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
const fakeQueryField = () => <div>prometheus query field</div>;
return {
MonacoQueryFieldWrapper: fakeQueryField,
};
});
function setup(app: CoreApp): RenderResult {
const dataSource = ({
createQuery: jest.fn((q) => q),

View File

@ -14,7 +14,6 @@ export function PromQueryEditorForAlerting(props: PromQueryEditorProps) {
history={[]}
range={range}
data={data}
placeholder="Enter a PromQL query"
data-testid={testIds.editor}
/>
);

View File

@ -7,6 +7,16 @@ import { DataSourceInstanceSettings, PanelData, LoadingState, DataFrame } from '
import { PromOptions } from '../types';
import { render, screen } from '@testing-library/react';
// the monaco-based editor uses lazy-loading and that does not work
// well with this test, and we do not need the monaco-related
// functionality in this test anyway, so we mock it out.
jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => {
const fakeQueryField = () => <div>prometheus query field</div>;
return {
MonacoQueryFieldWrapper: fakeQueryField,
};
});
describe('PromQueryField', () => {
beforeAll(() => {
// @ts-ignore

View File

@ -1,12 +1,10 @@
import React, { ReactNode } from 'react';
import { config } from '@grafana/runtime';
import { Plugin } from 'slate';
import {
SlatePrism,
TypeaheadInput,
TypeaheadOutput,
QueryField,
BracesPlugin,
DOMUtil,
SuggestionsState,
@ -73,7 +71,6 @@ export function willApplySuggestion(suggestion: string, { typeaheadContext, type
interface PromQueryFieldProps extends QueryEditorProps<PrometheusDatasource, PromQuery, PromOptions> {
ExtraFieldElement?: ReactNode;
placeholder?: string;
'data-testid'?: string;
}
@ -266,18 +263,14 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
datasource: { languageProvider },
query,
ExtraFieldElement,
placeholder = 'Enter a PromQL query (run with Shift+Enter)',
history = [],
} = this.props;
const { labelBrowserVisible, syntaxLoaded, hint } = this.state;
const cleanText = languageProvider ? languageProvider.cleanText : undefined;
const hasMetrics = languageProvider.metrics.length > 0;
const chooserText = getChooserText(datasource.lookupsDisabled, syntaxLoaded, hasMetrics);
const buttonDisabled = !(syntaxLoaded && hasMetrics);
const isMonacoEditorEnabled = config.featureToggles.prometheusMonaco;
return (
<LocalStorageValueProvider<string[]> storageKey={LAST_USED_LABELS_KEY} defaultValue={[]}>
{(lastUsedLabels, onLastUsedLabelsSave, onLastUsedLabelsDelete) => {
@ -297,30 +290,14 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
</button>
<div className="gf-form gf-form--grow flex-shrink-1 min-width-15">
{isMonacoEditorEnabled ? (
<MonacoQueryFieldWrapper
runQueryOnBlur={this.props.app !== CoreApp.Explore}
languageProvider={languageProvider}
history={history}
onChange={this.onChangeQuery}
onRunQuery={this.props.onRunQuery}
initialValue={query.expr ?? ''}
/>
) : (
<QueryField
additionalPlugins={this.plugins}
cleanText={cleanText}
query={query.expr}
onTypeahead={this.onTypeahead}
onWillApplySuggestion={willApplySuggestion}
onBlur={this.props.onBlur}
onChange={this.onChangeQuery}
onRunQuery={this.props.onRunQuery}
placeholder={placeholder}
portalOrigin="prometheus"
syntaxLoaded={syntaxLoaded}
/>
)}
<MonacoQueryFieldWrapper
runQueryOnBlur={this.props.app !== CoreApp.Explore}
languageProvider={languageProvider}
history={history}
onChange={this.onChangeQuery}
onRunQuery={this.props.onRunQuery}
initialValue={query.expr ?? ''}
/>
</div>
</div>
{labelBrowserVisible && (

View File

@ -4,6 +4,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { css } from '@emotion/css';
import { useLatest } from 'react-use';
import { promLanguageDefinition } from 'monaco-promql';
import { selectors } from '@grafana/e2e-selectors';
import { getCompletionProvider, getSuggestOptions } from './monaco-completion-provider';
import { Props } from './MonacoQueryFieldProps';
import { getOverrideServices } from './getOverrideServices';
@ -101,6 +102,7 @@ const MonacoQueryField = (props: Props) => {
return (
<div
aria-label={selectors.components.QueryField.container}
className={styles.container}
// NOTE: we will be setting inline-style-width/height on this element
ref={containerRef}