mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: app specific query editors for Loki and Prometheus (#34365)
* Adding simplified version of query editor based on app flag. * cleaned up the absolute time range. * changing placeholder text. * updated snapshot. * added some tests. * adding loki query editor tests. * updating snapshots.
This commit is contained in:
@@ -3,18 +3,16 @@ import React, { PureComponent } from 'react';
|
||||
|
||||
// Types
|
||||
import { InlineFormLabel, LegacyForms, Select } from '@grafana/ui';
|
||||
import { QueryEditorProps, SelectableValue } from '@grafana/data';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
import { PromOptions, PromQuery } from '../types';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { PromQuery } from '../types';
|
||||
|
||||
import PromQueryField from './PromQueryField';
|
||||
import PromLink from './PromLink';
|
||||
import { PromExemplarField } from './PromExemplarField';
|
||||
import { PromQueryEditorProps } from './types';
|
||||
|
||||
const { Switch } = LegacyForms;
|
||||
|
||||
export type Props = QueryEditorProps<PrometheusDatasource, PromQuery, PromOptions>;
|
||||
|
||||
const FORMAT_OPTIONS: Array<SelectableValue<string>> = [
|
||||
{ label: 'Time series', value: 'time_series' },
|
||||
{ label: 'Table', value: 'table' },
|
||||
@@ -35,11 +33,11 @@ interface State {
|
||||
exemplar: boolean;
|
||||
}
|
||||
|
||||
export class PromQueryEditor extends PureComponent<Props, State> {
|
||||
export class PromQueryEditor extends PureComponent<PromQueryEditorProps, State> {
|
||||
// Query target to be modified and used for queries
|
||||
query: PromQuery;
|
||||
|
||||
constructor(props: Props) {
|
||||
constructor(props: PromQueryEditorProps) {
|
||||
super(props);
|
||||
// Use default query to prevent undefined input values
|
||||
const defaultQuery: Partial<PromQuery> = { expr: '', legendFormat: '', interval: '', exemplar: true };
|
||||
@@ -118,6 +116,7 @@ export class PromQueryEditor extends PureComponent<Props, State> {
|
||||
onChange={this.onFieldChange}
|
||||
history={[]}
|
||||
data={data}
|
||||
data-testid={testIds.editor}
|
||||
ExtraFieldElement={
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form">
|
||||
@@ -198,3 +197,7 @@ export class PromQueryEditor extends PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const testIds = {
|
||||
editor: 'prom-editor',
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import { render, RenderResult } from '@testing-library/react';
|
||||
import { PromQueryEditorByApp } from './PromQueryEditorByApp';
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { noop } from 'lodash';
|
||||
import { Observable } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
import { testIds as alertingTestIds } from './PromQueryEditorForAlerting';
|
||||
import { testIds as regularTestIds } from './PromQueryEditor';
|
||||
|
||||
function setup(app: CoreApp): RenderResult {
|
||||
const dataSource = ({
|
||||
createQuery: jest.fn((q) => q),
|
||||
getPrometheusTime: jest.fn((date, roundup) => 123),
|
||||
languageProvider: {
|
||||
start: () => Promise.resolve([]),
|
||||
syntax: () => {},
|
||||
getLabelKeys: () => [],
|
||||
metrics: [],
|
||||
},
|
||||
exemplarErrors: new Observable().pipe(first()),
|
||||
} as unknown) as PrometheusDatasource;
|
||||
|
||||
return render(
|
||||
<PromQueryEditorByApp
|
||||
app={app}
|
||||
onChange={noop}
|
||||
onRunQuery={noop}
|
||||
datasource={dataSource}
|
||||
query={{ refId: 'A', expr: '' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
describe('PromQueryEditorByApp', () => {
|
||||
it('should render simplified query editor for cloud alerting', () => {
|
||||
const { getByTestId, queryByTestId } = setup(CoreApp.CloudAlerting);
|
||||
|
||||
expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument();
|
||||
expect(queryByTestId(regularTestIds.editor)).toBeNull();
|
||||
});
|
||||
|
||||
it('should render regular query editor for unkown apps', () => {
|
||||
const { getByTestId, queryByTestId } = setup(CoreApp.Unknown);
|
||||
|
||||
expect(getByTestId(regularTestIds.editor)).toBeInTheDocument();
|
||||
expect(queryByTestId(alertingTestIds.editor)).toBeNull();
|
||||
});
|
||||
|
||||
it('should render regular query editor for explore', () => {
|
||||
const { getByTestId, queryByTestId } = setup(CoreApp.Explore);
|
||||
|
||||
expect(getByTestId(regularTestIds.editor)).toBeInTheDocument();
|
||||
expect(queryByTestId(alertingTestIds.editor)).toBeNull();
|
||||
});
|
||||
|
||||
it('should render regular query editor for dashboard', () => {
|
||||
const { getByTestId, queryByTestId } = setup(CoreApp.Dashboard);
|
||||
|
||||
expect(getByTestId(regularTestIds.editor)).toBeInTheDocument();
|
||||
expect(queryByTestId(alertingTestIds.editor)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import React, { memo } from 'react';
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { PromQueryEditorProps } from './types';
|
||||
import { PromQueryEditor } from './PromQueryEditor';
|
||||
import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting';
|
||||
|
||||
export function PromQueryEditorByApp(props: PromQueryEditorProps) {
|
||||
const { app } = props;
|
||||
|
||||
switch (app) {
|
||||
case CoreApp.CloudAlerting:
|
||||
return <PromQueryEditorForAlerting {...props} />;
|
||||
default:
|
||||
return <PromQueryEditor {...props} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default memo(PromQueryEditorByApp);
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import PromQueryField from './PromQueryField';
|
||||
import { PromQueryEditorProps } from './types';
|
||||
|
||||
export function PromQueryEditorForAlerting(props: PromQueryEditorProps) {
|
||||
const { datasource, query, range, data, onChange, onRunQuery } = props;
|
||||
|
||||
return (
|
||||
<PromQueryField
|
||||
datasource={datasource}
|
||||
query={query}
|
||||
onRunQuery={onRunQuery}
|
||||
onChange={onChange}
|
||||
history={[]}
|
||||
range={range}
|
||||
data={data}
|
||||
placeholder="Enter a PromQL query"
|
||||
data-testid={testIds.editor}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const testIds = {
|
||||
editor: 'prom-editor-cloud-alerting',
|
||||
};
|
||||
@@ -77,6 +77,8 @@ export function willApplySuggestion(suggestion: string, { typeaheadContext, type
|
||||
interface PromQueryFieldProps extends ExploreQueryFieldProps<PrometheusDatasource, PromQuery, PromOptions> {
|
||||
history: Array<HistoryItem<PromQuery>>;
|
||||
ExtraFieldElement?: ReactNode;
|
||||
placeholder?: string;
|
||||
'data-testid'?: string;
|
||||
}
|
||||
|
||||
interface PromQueryFieldState {
|
||||
@@ -271,7 +273,9 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
datasource: { languageProvider },
|
||||
query,
|
||||
ExtraFieldElement,
|
||||
placeholder = 'Enter a PromQL query (run with Shift+Enter)',
|
||||
} = this.props;
|
||||
|
||||
const { labelBrowserVisible, syntaxLoaded, hint } = this.state;
|
||||
const cleanText = languageProvider ? languageProvider.cleanText : undefined;
|
||||
const hasMetrics = languageProvider.metrics.length > 0;
|
||||
@@ -280,7 +284,10 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form-inline gf-form-inline--xs-view-flex-column flex-grow-1">
|
||||
<div
|
||||
className="gf-form-inline gf-form-inline--xs-view-flex-column flex-grow-1"
|
||||
data-testid={this.props['data-testid']}
|
||||
>
|
||||
<button
|
||||
className="gf-form-label query-keyword pointer"
|
||||
onClick={this.onClickChooserButton}
|
||||
@@ -300,7 +307,7 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
onBlur={this.props.onBlur}
|
||||
onChange={this.onChangeQuery}
|
||||
onRunQuery={this.props.onRunQuery}
|
||||
placeholder="Enter a PromQL query (run with Shift+Enter)"
|
||||
placeholder={placeholder}
|
||||
portalOrigin="prometheus"
|
||||
syntaxLoaded={syntaxLoaded}
|
||||
/>
|
||||
|
||||
@@ -178,6 +178,7 @@ exports[`Render PromQueryEditor with basic options should render 1`] = `
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
data-testid="prom-editor"
|
||||
datasource={
|
||||
Object {
|
||||
"createQuery": [MockFunction],
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { QueryEditorProps } from '@grafana/data';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
import { PromOptions, PromQuery } from '../types';
|
||||
|
||||
export type PromQueryEditorProps = QueryEditorProps<PrometheusDatasource, PromQuery, PromOptions>;
|
||||
Reference in New Issue
Block a user