mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Add default editor configuration (#61510)
* Add default editor option in Prometheus configuration * Small readability improvement
This commit is contained in:
parent
24ef778f4d
commit
6dcc94ecb2
@ -6320,8 +6320,7 @@ exports[`better eslint`] = {
|
||||
],
|
||||
"public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.test.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/prometheus/querybuilder/shared/LabelFilterItem.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
|
||||
import { useUpdateDatasource } from '../../../../features/datasources/state';
|
||||
import { PromApplication, PromBuildInfoResponse } from '../../../../types/unified-alerting-dto';
|
||||
import { QueryEditorMode } from '../querybuilder/shared/types';
|
||||
import { PromOptions } from '../types';
|
||||
|
||||
import { ExemplarsSettings } from './ExemplarsSettings';
|
||||
@ -33,6 +34,11 @@ const httpOptions = [
|
||||
{ value: 'GET', label: 'GET' },
|
||||
];
|
||||
|
||||
const editorOptions = [
|
||||
{ value: QueryEditorMode.Builder, label: 'Builder' },
|
||||
{ value: QueryEditorMode.Code, label: 'Code' },
|
||||
];
|
||||
|
||||
type PrometheusSelectItemsType = Array<{ value: PromApplication; label: PromApplication }>;
|
||||
|
||||
const prometheusFlavorSelectItems: PrometheusSelectItemsType = [
|
||||
@ -136,7 +142,8 @@ export const PromSettings = (props: Props) => {
|
||||
// This update call is typed as void, but it returns a response which we need
|
||||
const onUpdate = useUpdateDatasource();
|
||||
|
||||
// We are explicitly adding httpMethod so it is correctly displayed in dropdown. This way, it is more predictable for users.
|
||||
// We are explicitly adding httpMethod so, it is correctly displayed in dropdown.
|
||||
// This way, it is more predictable for users.
|
||||
if (!options.jsonData.httpMethod) {
|
||||
options.jsonData.httpMethod = 'POST';
|
||||
}
|
||||
@ -292,6 +299,23 @@ export const PromSettings = (props: Props) => {
|
||||
/>
|
||||
</InlineField>
|
||||
</div>
|
||||
<div className="gf-form">
|
||||
<FormField
|
||||
label="Default Editor"
|
||||
labelWidth={14}
|
||||
inputEl={
|
||||
<Select
|
||||
aria-label={`Default Editor (Code or Builder)`}
|
||||
options={editorOptions}
|
||||
value={editorOptions.find((o) => o.value === options.jsonData.defaultEditor)}
|
||||
onChange={onChangeHandler('defaultEditor', options, onOptionsChange)}
|
||||
width={20}
|
||||
disabled={options.readOnly}
|
||||
/>
|
||||
}
|
||||
tooltip={`Set default editor option (builder/code) for all users of this datasource. If no option was selected, the default editor will be the "builder". If they switch to other option rather than the specified with this setting on the panel we always show the selected editor for that user.`}
|
||||
/>
|
||||
</div>
|
||||
<div className="gf-form-inline">
|
||||
<div className="gf-form max-width-30">
|
||||
<FormField
|
||||
|
@ -50,6 +50,7 @@ import { expandRecordingRules } from './language_utils';
|
||||
import { renderLegendFormat } from './legend';
|
||||
import PrometheusMetricFindQuery from './metric_find_query';
|
||||
import { getInitHints, getQueryHints } from './query_hints';
|
||||
import { QueryEditorMode } from './querybuilder/shared/types';
|
||||
import { getOriginalMetricName, transform, transformV2 } from './result_transformer';
|
||||
import { trackQuery } from './tracking';
|
||||
import {
|
||||
@ -92,6 +93,7 @@ export class PrometheusDatasource
|
||||
customQueryParameters: any;
|
||||
datasourceConfigurationPrometheusFlavor?: PromApplication;
|
||||
datasourceConfigurationPrometheusVersion?: string;
|
||||
defaultEditor?: QueryEditorMode;
|
||||
exemplarsAvailable: boolean;
|
||||
subType: PromApplication;
|
||||
rulerEnabled: boolean;
|
||||
@ -126,6 +128,7 @@ export class PrometheusDatasource
|
||||
this.customQueryParameters = new URLSearchParams(instanceSettings.jsonData.customQueryParameters);
|
||||
this.datasourceConfigurationPrometheusFlavor = instanceSettings.jsonData.prometheusType;
|
||||
this.datasourceConfigurationPrometheusVersion = instanceSettings.jsonData.prometheusVersion;
|
||||
this.defaultEditor = instanceSettings.jsonData.defaultEditor;
|
||||
this.variables = new PrometheusVariableSupport(this, this.templateSrv, this.timeSrv);
|
||||
this.exemplarsAvailable = true;
|
||||
|
||||
|
@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
|
||||
import { cloneDeep, defaultsDeep } from 'lodash';
|
||||
import React from 'react';
|
||||
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { CoreApp, PluginMeta, PluginType } from '@grafana/data';
|
||||
|
||||
import { PromQueryEditorProps } from '../../components/types';
|
||||
import { PrometheusDatasource } from '../../datasource';
|
||||
@ -48,8 +48,30 @@ const defaultQuery = {
|
||||
expr: 'metric{label1="foo", label2="bar"}',
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
datasource: new PrometheusDatasource(
|
||||
const defaultMeta: PluginMeta = {
|
||||
id: '',
|
||||
name: '',
|
||||
type: PluginType.datasource,
|
||||
info: {
|
||||
author: {
|
||||
name: 'tester',
|
||||
},
|
||||
description: 'testing',
|
||||
links: [],
|
||||
logos: {
|
||||
large: '',
|
||||
small: '',
|
||||
},
|
||||
screenshots: [],
|
||||
updated: '',
|
||||
version: '',
|
||||
},
|
||||
module: '',
|
||||
baseUrl: '',
|
||||
};
|
||||
|
||||
const getDefaultDatasource = (jsonDataOverrides = {}) =>
|
||||
new PrometheusDatasource(
|
||||
{
|
||||
id: 1,
|
||||
uid: '',
|
||||
@ -57,14 +79,17 @@ const defaultProps = {
|
||||
name: 'prom-test',
|
||||
access: 'proxy',
|
||||
url: '',
|
||||
jsonData: {},
|
||||
meta: {} as any,
|
||||
jsonData: jsonDataOverrides,
|
||||
meta: defaultMeta,
|
||||
readOnly: false,
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
new EmptyLanguageProviderMock() as unknown as PromQlLanguageProvider
|
||||
),
|
||||
);
|
||||
|
||||
const defaultProps = {
|
||||
datasource: getDefaultDatasource(),
|
||||
query: defaultQuery,
|
||||
onRunQuery: () => {},
|
||||
onChange: () => {},
|
||||
@ -77,6 +102,16 @@ describe('PromQueryEditorSelector', () => {
|
||||
expectCodeEditor();
|
||||
});
|
||||
|
||||
it('shows code editor if no expr and nothing else since defaultEditor is code', async () => {
|
||||
renderWithDatasourceDefaultEditorMode(QueryEditorMode.Code);
|
||||
expectCodeEditor();
|
||||
});
|
||||
|
||||
it('shows builder if no expr and nothing else since defaultEditor is builder', async () => {
|
||||
renderWithDatasourceDefaultEditorMode(QueryEditorMode.Builder);
|
||||
expectBuilder();
|
||||
});
|
||||
|
||||
it('shows code editor when code mode is set', async () => {
|
||||
renderWithMode(QueryEditorMode.Code);
|
||||
expectCodeEditor();
|
||||
@ -168,6 +203,22 @@ function renderWithMode(mode: QueryEditorMode) {
|
||||
return renderWithProps({ editorMode: mode } as any);
|
||||
}
|
||||
|
||||
function renderWithDatasourceDefaultEditorMode(mode: QueryEditorMode) {
|
||||
const props = {
|
||||
...defaultProps,
|
||||
datasource: getDefaultDatasource({
|
||||
defaultEditor: mode,
|
||||
}),
|
||||
query: {
|
||||
refId: 'B',
|
||||
expr: '',
|
||||
},
|
||||
onRunQuery: () => {},
|
||||
onChange: () => {},
|
||||
};
|
||||
render(<PromQueryEditorSelector {...props} />);
|
||||
}
|
||||
|
||||
function renderWithProps(overrides?: Partial<PromQuery>, componentProps: Partial<PromQueryEditorProps> = {}) {
|
||||
const query = defaultsDeep(overrides ?? {}, cloneDeep(defaultQuery));
|
||||
const onChange = jest.fn();
|
||||
|
@ -34,12 +34,18 @@ export const INTERVAL_FACTOR_OPTIONS: Array<SelectableValue<number>> = map([1, 2
|
||||
type Props = PromQueryEditorProps;
|
||||
|
||||
export const PromQueryEditorSelector = React.memo<Props>((props) => {
|
||||
const { onChange, onRunQuery, data, app } = props;
|
||||
const {
|
||||
onChange,
|
||||
onRunQuery,
|
||||
data,
|
||||
app,
|
||||
datasource: { defaultEditor },
|
||||
} = props;
|
||||
const [parseModalOpen, setParseModalOpen] = useState(false);
|
||||
const [dataIsStale, setDataIsStale] = useState(false);
|
||||
const { flag: explain, setFlag: setExplain } = useFlag(promQueryEditorExplainKey);
|
||||
|
||||
const query = getQueryWithDefaults(props.query, app);
|
||||
const query = getQueryWithDefaults(props.query, app, defaultEditor);
|
||||
// This should be filled in from the defaults by now.
|
||||
const editorMode = query.editorMode!;
|
||||
|
||||
|
@ -49,4 +49,14 @@ describe('getQueryWithDefaults(', () => {
|
||||
QueryEditorMode.Code
|
||||
);
|
||||
});
|
||||
|
||||
it('should return default editor mode when it is provided', () => {
|
||||
expect(getQueryWithDefaults({ refId: 'A' } as PromQuery, CoreApp.Dashboard, QueryEditorMode.Code)).toEqual({
|
||||
editorMode: 'code',
|
||||
expr: '',
|
||||
legendFormat: '__auto',
|
||||
range: true,
|
||||
refId: 'A',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ export function changeEditorMode(query: PromQuery, editorMode: QueryEditorMode,
|
||||
onChange({ ...query, editorMode });
|
||||
}
|
||||
|
||||
function getDefaultEditorMode(expr: string) {
|
||||
function getDefaultEditorMode(expr: string, defaultEditor: QueryEditorMode = QueryEditorMode.Builder): QueryEditorMode {
|
||||
// If we already have an expression default to code view
|
||||
if (expr != null && expr !== '') {
|
||||
return QueryEditorMode.Code;
|
||||
@ -28,18 +28,22 @@ function getDefaultEditorMode(expr: string) {
|
||||
case QueryEditorMode.Code:
|
||||
return value;
|
||||
default:
|
||||
return QueryEditorMode.Builder;
|
||||
return defaultEditor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns query with defaults, and boolean true/false depending on change was required
|
||||
*/
|
||||
export function getQueryWithDefaults(query: PromQuery, app: CoreApp | undefined): PromQuery {
|
||||
export function getQueryWithDefaults(
|
||||
query: PromQuery,
|
||||
app: CoreApp | undefined,
|
||||
defaultEditor?: QueryEditorMode
|
||||
): PromQuery {
|
||||
let result = query;
|
||||
|
||||
if (!query.editorMode) {
|
||||
result = { ...query, editorMode: getDefaultEditorMode(query.expr) };
|
||||
result = { ...query, editorMode: getDefaultEditorMode(query.expr, defaultEditor) };
|
||||
}
|
||||
|
||||
if (query.expr == null) {
|
||||
|
@ -35,6 +35,7 @@ export interface PromOptions extends DataSourceJsonData {
|
||||
prometheusType?: PromApplication;
|
||||
prometheusVersion?: string;
|
||||
enableSecureSocksProxy?: boolean;
|
||||
defaultEditor?: QueryEditorMode;
|
||||
}
|
||||
|
||||
export type ExemplarTraceIdDestination = {
|
||||
@ -116,6 +117,7 @@ export type PromValue = [number, any];
|
||||
|
||||
export interface PromMetric {
|
||||
__name__?: string;
|
||||
|
||||
[index: string]: any;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user