Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support queries prettifying in query editor #101

Merged
merged 4 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"import/external-module-folders": ["node_modules", ".yarn"]
},
"rules": {
"indent": ["error", 2, { "SwitchCase": 1 }],
"react/prop-types": "off",
"@emotion/jsx-import": "error",
"object-curly-spacing": [2, "always"],
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## tip
* FEATURE: add datasource settings for limiting the number of metrics during discovery. The proper limits should protect users from slowing down the browser when datasource returns big amounts of discovered metrics in response. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/82).
* FEATURE: add a `prettify query` icon, which when clicked, formats the query. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/86).
* FEATURE: change the style of the buttons `WITH templates` and `Run in vmui` to icons.

* BUGFIX: correctly handle custom query parameters in annotation queries. See [this issue](https://github.com/VictoriaMetrics/grafana-datasource/issues/95)

Expand Down
53 changes: 53 additions & 0 deletions src/components/PrettifyQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { FC, useState, memo } from 'react';

import { IconButton } from "@grafana/ui";

import { PrometheusDatasource } from '../datasource';
import { PromQuery } from "../types";

interface Props {
datasource: PrometheusDatasource;
query: PromQuery;
onChange: (update: PromQuery) => void;
}

enum ResponseStatus {
Success = 'success',
Error = 'error'
}

const PrettifyQuery: FC<Props> = ({
datasource,
query,
onChange
}) => {
const [loading, setLoading] = useState(false)

const handleClickPrettify = async () => {
setLoading(true)
try {
const response = await datasource.prettifyRequest(query.expr)
const { data, status } = response
if (data?.status === ResponseStatus.Success) {
onChange({ ...query, expr: data.query });
} else {
console.error(`Error requesting /prettify-query, status: ${status}`)
}
} catch (e) {
console.error(e)
}
setLoading(false)
}

return (
<IconButton
key="run"
name={loading ? 'fa fa-spinner' : 'brackets-curly'}
tooltip={'Prettify query'}
disabled={loading}
onClick={handleClickPrettify}
/>
);
};

export default memo(PrettifyQuery);
27 changes: 13 additions & 14 deletions src/components/VmuiLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import React, { FC, useEffect, useState, memo } from 'react';

import { PanelData, ScopedVars, textUtil, rangeUtil } from '@grafana/data';
import { getBackendSrv } from "@grafana/runtime";
import { Button } from "@grafana/ui";
import { IconButton } from "@grafana/ui";

import { PrometheusDatasource } from '../datasource';
import { PromQuery } from '../types';
Expand Down Expand Up @@ -55,11 +55,11 @@ export const relativeTimeOptionsVMUI = [
}))

const VmuiLink: FC<Props> = ({
panelData,
query,
datasource,
dashboardUID,
}) => {
panelData,
query,
datasource,
dashboardUID,
}) => {
const [href, setHref] = useState('');

useEffect(() => {
Expand Down Expand Up @@ -132,14 +132,13 @@ const VmuiLink: FC<Props> = ({
}, [dashboardUID, datasource, panelData, query]);

return (
<a href={textUtil.sanitizeUrl(href)} target="_blank" rel="noopener noreferrer">
<Button
variant={'primary'}
size="sm"
icon={"external-link-alt"}
>
Run in vmui
</Button>
<a href={textUtil.sanitizeUrl(href)} target="_blank" rel="noopener noreferrer"
style={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
<IconButton
key="vmui"
name="external-link-alt"
tooltip="Run in vmui"
/>
</a>
);
};
Expand Down
14 changes: 6 additions & 8 deletions src/components/WithTemplateConfig/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC, useCallback, useEffect, useState } from 'react'

import { Badge, Button, Modal, useStyles2 } from "@grafana/ui";
import { Badge, Button, IconButton, Modal, useStyles2 } from "@grafana/ui";

import { PrometheusDatasource } from "../../datasource";

Expand Down Expand Up @@ -82,14 +82,12 @@ const WithTemplateConfig: FC<Props> = ({ template, setTemplate, dashboardUID, da

return (
<>
<Button
variant={'secondary'}
size="sm"
<IconButton
key="with_templates"
name="cog"
tooltip="WITH templates"
onClick={handleOpen}
icon={"cog"}
>
WITH templates
</Button>
/>
<Modal
title={`${dashboardFolder} / ${dashboardTitle} / WITH templates`}
isOpen={showTemplates}
Expand Down
18 changes: 18 additions & 0 deletions src/datasource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,24 @@ export class PrometheusDatasource
); // toPromise until we change getTagValues, getTagKeys to Observable
}

async prettifyRequest<T = any>(query: string) {
// If URL includes endpoint that supports POST and GET method, try to use configured method. This might fail as POST is supported only in v2.10+.
try {
return await lastValueFrom(
this._request<T>(`/api/datasources/proxy/${this.id}/prettify-query`, {}, {
method: 'GET',
hideFromInspector: true,
showErrorAlert: false,
params: {
query
}
})
);
} catch (err) {
throw err;
}
}

interpolateQueryExpr(value: string | string[] = [], variable: any) {
// if no multi or include all do not regexEscape
if (!variable.multi && !variable.includeAll) {
Expand Down
24 changes: 8 additions & 16 deletions src/querybuilder/components/PromQueryEditorSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react';

import { CoreApp, LoadingState } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { Button, ConfirmModal, Tooltip } from '@grafana/ui';
import { ConfirmModal, IconButton } from '@grafana/ui';

import PrettifyQuery from "../../components/PrettifyQuery";
import { EditorHeader, EditorRows, FlexItem, InlineSelect, Space } from '../../components/QueryEditor';
import VmuiLink from "../../components/VmuiLink";
import WithTemplateConfig from "../../components/WithTemplateConfig";
Expand Down Expand Up @@ -52,7 +53,6 @@ export const PromQueryEditorSelector = React.memo<Props>((props) => {
const { onChange, onRunQuery, data, app, datasource } = props;

const [parseModalOpen, setParseModalOpen] = useState(false);
const [dataIsStale, setDataIsStale] = useState(false);
const [trace, setTrace] = useState(false);
const [rawQuery, setRawQuery] = useState(false)
const { flag: explain, setFlag: setExplain } = useFlag(promQueryEditorExplainKey);
Expand Down Expand Up @@ -86,12 +86,7 @@ export const PromQueryEditorSelector = React.memo<Props>((props) => {
[onChange, query, app]
);

useEffect(() => {
setDataIsStale(false);
}, [data]);

const onChangeInternal = (query: PromQuery) => {
setDataIsStale(true);
onChange(query);
};

Expand Down Expand Up @@ -156,17 +151,14 @@ export const PromQueryEditorSelector = React.memo<Props>((props) => {
dashboardUID={dashboardUID}
datasource={datasource}
/>
<PrettifyQuery query={query} datasource={datasource} onChange={onChange}/>
<VmuiLink query={query} datasource={datasource} panelData={data} dashboardUID={dashboardUID}/>
{app !== CoreApp.Explore && (
<Tooltip content={"Run queries"}>
<Button
variant={dataIsStale ? 'primary' : 'secondary'}
size="sm"
onClick={onRunQuery}
icon={data?.state === LoadingState.Loading ? 'fa fa-spinner' : "play"}
disabled={data?.state === LoadingState.Loading}
/>
</Tooltip>
<IconButton
key="run"
name={data?.state === LoadingState.Loading ? 'fa fa-spinner' : "play"}
tooltip="Run queries"
/>
)}
<QueryEditorModeToggle mode={editorMode} onChange={onEditorModeChange}/>
</EditorHeader>
Expand Down
Loading