Skip to content

Commit

Permalink
feat(dashboard): panel support inspecting query data and panel json
Browse files Browse the repository at this point in the history
  • Loading branch information
jsers committed Aug 11, 2023
1 parent 5022ee3 commit 30fb02a
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 36 deletions.
92 changes: 92 additions & 0 deletions src/pages/dashboard/Renderer/Inspect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useState, useEffect } from 'react';
import _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { Select, Tabs } from 'antd';
import CodeMirror from '@uiw/react-codemirror';
import { json } from '@codemirror/lang-json';
import { defaultHighlightStyle } from '@codemirror/highlight';
import { EditorView } from '@codemirror/view';
import './style.less';

interface Props {
query?: any[];
values: any;
}

export default function index(props: Props) {
const { t } = useTranslation('dashboard');
const { query, values } = props;
const multipleQuery = query && query?.length > 1;
const [queryType, setQueryType] = useState<any>(query?.[0]?.type);
const queryByType = _.find(query, { type: queryType });

useEffect(() => {
setQueryType(query?.[0]?.type);
}, [JSON.stringify(query)]);

return (
<Tabs className='dashboard-detail-inspect'>
<Tabs.TabPane tab={t('panel.inspect.query')} key='query'>
{multipleQuery && (
<Select
style={{ width: '100%', marginBottom: 10 }}
options={_.map(query, (item) => {
return {
label: item.type,
value: item.type,
};
})}
value={queryType}
onChange={(val) => {
setQueryType(val);
}}
/>
)}
<div style={{ height: multipleQuery ? 'calc(100% - 42px)' : '100%' }}>
<CodeMirror
height='100%'
theme='light'
basicSetup
editable
extensions={[
defaultHighlightStyle.fallback,
json(),
EditorView.lineWrapping,
EditorView.theme({
'&': {
backgroundColor: '#F6F6F6 !important',
},
'&.cm-editor.cm-focused': {
outline: 'unset',
},
}),
]}
value={queryByType ? JSON.stringify(queryByType, null, 2) : ''}
/>
</div>
</Tabs.TabPane>
<Tabs.TabPane tab={t('panel.inspect.json')} key='json'>
<CodeMirror
height='100%'
theme='light'
basicSetup
editable
extensions={[
defaultHighlightStyle.fallback,
json(),
EditorView.lineWrapping,
EditorView.theme({
'&': {
backgroundColor: '#F6F6F6 !important',
},
'&.cm-editor.cm-focused': {
outline: 'unset',
},
}),
]}
value={values ? JSON.stringify(values, null, 2) : ''}
/>
</Tabs.TabPane>
</Tabs>
);
}
6 changes: 6 additions & 0 deletions src/pages/dashboard/Renderer/Inspect/style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.dashboard-detail-inspect {
height: 100%;
.ant-tabs-content,.cm-theme-light {
height: 100%;
}
}
42 changes: 35 additions & 7 deletions src/pages/dashboard/Renderer/Renderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import _ from 'lodash';
import classNames from 'classnames';
import { useInViewport } from 'ahooks';
import { useTranslation } from 'react-i18next';
import { Dropdown, Menu, Tooltip, Space } from 'antd';
import { Dropdown, Menu, Tooltip, Space, Drawer } from 'antd';
import {
InfoCircleOutlined,
MoreOutlined,
Expand Down Expand Up @@ -47,6 +47,7 @@ import Markdown from '../../Editor/Components/Markdown';
import useQuery from '../datasource/useQuery';
import { IPanel } from '../../types';
import replaceFieldWithVariable from '../utils/replaceFieldWithVariable';
import Inspect from '../Inspect';
import './style.less';

interface IProps {
Expand All @@ -73,7 +74,8 @@ function index(props: IProps) {
const ref = useRef<HTMLDivElement>(null);
const bodyWrapRef = useRef<HTMLDivElement>(null);
const [inViewPort] = useInViewport(ref);
const { series, error, loading } = useQuery({
const [inspect, setInspect] = useState(false);
const { query, series, error, loading } = useQuery({
id,
dashboardId,
time,
Expand All @@ -84,6 +86,7 @@ function index(props: IProps) {
datasourceValue: values.datasourceValue || datasourceValue,
spanNulls: values.custom?.spanNulls,
scopedVars: values.scopedVars,
inspect,
});
const name = replaceFieldWithVariable(dashboardId, values.name, variableConfig, values.scopedVars);
const description = replaceFieldWithVariable(dashboardId, values.description, variableConfig, values.scopedVars);
Expand Down Expand Up @@ -207,7 +210,7 @@ function index(props: IProps) {
refreshFlag: _.uniqueId('refreshFlag_ '),
});
}}
key='0'
key='refresh_btn'
>
<div>
<SyncOutlined style={{ marginRight: 8 }} />
Expand All @@ -220,7 +223,7 @@ function index(props: IProps) {
setVisible(false);
if (onEditClick) onEditClick();
}}
key='1'
key='edit_btn'
>
<SettingOutlined style={{ marginRight: 8 }} />
{t('common:btn.edit')}
Expand All @@ -232,7 +235,7 @@ function index(props: IProps) {
setVisible(false);
if (onCloneClick) onCloneClick();
}}
key='2'
key='clone_btn'
>
<CopyOutlined style={{ marginRight: 8 }} />
{t('common:btn.clone')}
Expand All @@ -243,18 +246,32 @@ function index(props: IProps) {
setVisible(false);
if (onShareClick) onShareClick();
}}
key='3'
key='share_btn'
>
<ShareAltOutlined style={{ marginRight: 8 }} />
{t('share_btn')}
</Menu.Item>
<Menu.Item
onClick={() => {
setVisible(false);
setTime({
...time,
refreshFlag: _.uniqueId('refreshFlag_ '),
});
setInspect(true);
}}
key='inspect_btn'
>
<InfoCircleOutlined style={{ marginRight: 8 }} />
{t('inspect_btn')}
</Menu.Item>
{!values.repeatPanelId && (
<Menu.Item
onClick={() => {
setVisible(false);
if (onDeleteClick) onDeleteClick();
}}
key='4'
key='delete_btn'
>
<DeleteOutlined style={{ marginRight: 8 }} />
{t('common:btn.delete')}
Expand All @@ -278,6 +295,17 @@ function index(props: IProps) {
)}
</div>
</div>
<Drawer
title={t('panel.inspect.title')}
placement='right'
width={800}
onClose={() => {
setInspect(false);
}}
visible={inspect}
>
<Inspect query={query} values={values} />
</Drawer>
</div>
);
}
Expand Down
66 changes: 51 additions & 15 deletions src/pages/dashboard/Renderer/datasource/elasticsearch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import { flattenHits } from '@/pages/explorer/Elasticsearch/utils';

interface IOptions {
dashboardId: string;
datasourceCate: string;
datasourceValue: number;
id?: string;
time: IRawTimeRange;
targets: ITarget[];
variableConfig?: IVariable[];
inspect?: boolean;
}

/**
Expand All @@ -32,9 +32,14 @@ function isRawDataQuery(target: ITarget) {
return false;
}

export default async function elasticSearchQuery(options: IOptions) {
const { dashboardId, time, targets, datasourceCate, variableConfig } = options;
if (!time.start) return;
interface Result {
series: any[];
query?: any[];
}

export default async function elasticSearchQuery(options: IOptions): Promise<Result> {
const { dashboardId, time, targets, variableConfig } = options;
if (!time.start) return Promise.resolve({ series: [] });
const parsedRange = parseRange(time);
let start = moment(parsedRange.start).valueOf();
let end = moment(parsedRange.end).valueOf();
Expand Down Expand Up @@ -74,8 +79,9 @@ export default async function elasticSearchQuery(options: IOptions) {
});
}
});
let dsRes;
let dsPlayload = '';
if (!_.isEmpty(batchDsParams)) {
let payload = '';
let intervalkey = 'interval';
try {
const version = await getESVersion(datasourceValue);
Expand All @@ -92,31 +98,32 @@ export default async function elasticSearchQuery(options: IOptions) {
ignore_unavailable: true,
index: item.index,
});
payload += header + '\n';
payload += esQuery + '\n';
dsPlayload += header + '\n';
dsPlayload += esQuery + '\n';
});
const res = await getDsQuery(datasourceValue, payload);
series = _.map(processResponseToSeries(res, batchDsParams), (item) => {
dsRes = await getDsQuery(datasourceValue, dsPlayload);
series = _.map(processResponseToSeries(dsRes, batchDsParams), (item) => {
return {
id: _.uniqueId('series_'),
...item,
};
});
}
let logRes;
let logPlayload = '';
if (!_.isEmpty(batchLogParams)) {
let payload = '';
_.forEach(batchLogParams, (item) => {
const esQuery = JSON.stringify(getLogsQuery(item));
const header = JSON.stringify({
search_type: 'query_then_fetch',
ignore_unavailable: true,
index: item.index,
});
payload += header + '\n';
payload += esQuery + '\n';
logPlayload += header + '\n';
logPlayload += esQuery + '\n';
});
const res = await getDsQuery(datasourceValue, payload);
_.forEach(res, (item) => {
logRes = await getDsQuery(datasourceValue, logPlayload);
_.forEach(logRes, (item) => {
const { docs } = flattenHits(item?.hits?.hits);
_.forEach(docs, (doc: any) => {
series.push({
Expand All @@ -128,6 +135,35 @@ export default async function elasticSearchQuery(options: IOptions) {
});
});
}
const resolveData: Result = { series };
if (options.inspect) {
resolveData.query = [];
if (!_.isEmpty(batchDsParams)) {
resolveData.query.push({
type: 'TimeSeries',
request: {
url: `/api/n9e/proxy/${datasourceValue}/_msearch`,
method: 'POST',
data: dsPlayload,
},
response: dsRes,
});
}
if (!_.isEmpty(batchLogParams)) {
resolveData.query.push({
type: 'Logs',
request: {
url: `/api/n9e/proxy/${datasourceValue}/_msearch`,
method: 'POST',
data: logPlayload,
},
response: logRes,
});
}
}
return Promise.resolve(resolveData);
}
return series;
return Promise.resolve({
series: [],
});
}
Loading

0 comments on commit 30fb02a

Please sign in to comment.