mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Fix link to Prometheus graph in dashboard (#29543)
* Fix Promlink to have href after componentDidMount * Refactor to hooks and react testing library * Update * Update snapshot test
This commit is contained in:
parent
c2e81ab166
commit
3018c6a1b1
@ -1,58 +1,67 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { PanelData } from '@grafana/data';
|
||||||
|
import { PromQuery } from '../types';
|
||||||
|
import { PrometheusDatasource } from '../datasource';
|
||||||
import PromLink from './PromLink';
|
import PromLink from './PromLink';
|
||||||
|
|
||||||
const getPanelData = () => ({
|
const getPanelData = (panelDataOverrides?: Partial<PanelData>) => {
|
||||||
request: {
|
const panelData = {
|
||||||
targets: [
|
request: {
|
||||||
{ refId: 'A', datasource: 'prom1' },
|
targets: [
|
||||||
{ refId: 'B', datasource: 'prom2' },
|
{ refId: 'A', datasource: 'prom1' },
|
||||||
],
|
{ refId: 'B', datasource: 'prom2' },
|
||||||
range: {
|
],
|
||||||
to: {
|
range: {
|
||||||
utc: () => ({
|
to: {
|
||||||
format: jest.fn(),
|
utc: () => ({
|
||||||
}),
|
format: jest.fn(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
});
|
|
||||||
describe('PromLink component', () => {
|
return Object.assign(panelData, panelDataOverrides) as PanelData;
|
||||||
it('should show different link when there are 2 components with the same panel data', async () => {
|
};
|
||||||
const Comp = () => (
|
|
||||||
|
const getDataSource = (datasourceOverrides?: Partial<PrometheusDatasource>) => {
|
||||||
|
const datasource = {
|
||||||
|
getPrometheusTime: () => 123,
|
||||||
|
createQuery: () => ({ expr: 'up', step: 15 }),
|
||||||
|
directUrl: 'prom1',
|
||||||
|
};
|
||||||
|
|
||||||
|
return (Object.assign(datasource, datasourceOverrides) as unknown) as PrometheusDatasource;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('PromLink', () => {
|
||||||
|
it('should show correct link for 1 component', async () => {
|
||||||
|
render(
|
||||||
<div>
|
<div>
|
||||||
<PromLink
|
<PromLink datasource={getDataSource()} panelData={getPanelData()} query={{} as PromQuery} />
|
||||||
datasource={
|
|
||||||
{ getPrometheusTime: () => 123, createQuery: () => ({ expr: 'up', step: 15 }), directUrl: 'prom1' } as any
|
|
||||||
}
|
|
||||||
panelData={getPanelData() as any}
|
|
||||||
query={{} as any}
|
|
||||||
/>
|
|
||||||
<PromLink
|
|
||||||
datasource={
|
|
||||||
{ getPrometheusTime: () => 123, createQuery: () => ({ expr: 'up', step: 15 }), directUrl: 'prom2' } as any
|
|
||||||
}
|
|
||||||
panelData={getPanelData() as any}
|
|
||||||
query={{} as any}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const wrapper = mount(<Comp />);
|
expect(screen.getByText('Prometheus')).toHaveAttribute(
|
||||||
// Trigger componentDidUpdate
|
'href',
|
||||||
wrapper.setProps('s');
|
'prom1/graph?g0.expr=up&g0.range_input=0s&g0.end_input=undefined&g0.step_input=15&g0.tab=0'
|
||||||
await Promise.resolve();
|
);
|
||||||
|
});
|
||||||
expect(
|
it('should show different link when there are 2 components with the same panel data', () => {
|
||||||
wrapper
|
render(
|
||||||
.find('a')
|
<div>
|
||||||
.first()
|
<PromLink datasource={getDataSource()} panelData={getPanelData()} query={{} as PromQuery} />
|
||||||
.getDOMNode<HTMLAnchorElement>().href
|
<PromLink datasource={getDataSource({ directUrl: 'prom2' })} panelData={getPanelData()} query={{} as any} />
|
||||||
).toMatch('prom1');
|
</div>
|
||||||
expect(
|
);
|
||||||
wrapper
|
const promLinkButtons = screen.getAllByText('Prometheus');
|
||||||
.find('a')
|
expect(promLinkButtons[0]).toHaveAttribute(
|
||||||
.last()
|
'href',
|
||||||
.getDOMNode<HTMLAnchorElement>().href
|
'prom1/graph?g0.expr=up&g0.range_input=0s&g0.end_input=undefined&g0.step_input=15&g0.tab=0'
|
||||||
).toMatch('prom2');
|
);
|
||||||
|
expect(promLinkButtons[1]).toHaveAttribute(
|
||||||
|
'href',
|
||||||
|
'prom2/graph?g0.expr=up&g0.range_input=0s&g0.end_input=undefined&g0.step_input=15&g0.tab=0'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { Component } from 'react';
|
import React, { FC, useEffect, useState, memo } from 'react';
|
||||||
|
|
||||||
import { PrometheusDatasource } from '../datasource';
|
import { PrometheusDatasource } from '../datasource';
|
||||||
import { PromQuery } from '../types';
|
import { PromQuery } from '../types';
|
||||||
@ -11,62 +11,53 @@ interface Props {
|
|||||||
panelData?: PanelData;
|
panelData?: PanelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const PromLink: FC<Props> = ({ panelData, query, datasource }) => {
|
||||||
href: string;
|
const [href, setHref] = useState('');
|
||||||
}
|
|
||||||
|
|
||||||
export default class PromLink extends Component<Props, State> {
|
useEffect(() => {
|
||||||
state: State = { href: '' };
|
if (panelData) {
|
||||||
|
const getExternalLink = () => {
|
||||||
|
if (!panelData.request) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
async componentDidUpdate(prevProps: Props) {
|
const {
|
||||||
const { panelData } = this.props;
|
request: { range, interval },
|
||||||
|
} = panelData;
|
||||||
|
|
||||||
if (panelData && panelData.request && prevProps.panelData !== panelData) {
|
const start = datasource.getPrometheusTime(range.from, false);
|
||||||
const href = await this.getExternalLink(panelData);
|
const end = datasource.getPrometheusTime(range.to, true);
|
||||||
this.setState({ href });
|
const rangeDiff = Math.ceil(end - start);
|
||||||
|
const endTime = range.to.utc().format('YYYY-MM-DD HH:mm');
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
interval,
|
||||||
|
} as DataQueryRequest<PromQuery>;
|
||||||
|
|
||||||
|
const queryOptions = datasource.createQuery(query, options, start, end);
|
||||||
|
const expr = {
|
||||||
|
'g0.expr': queryOptions.expr,
|
||||||
|
'g0.range_input': rangeDiff + 's',
|
||||||
|
'g0.end_input': endTime,
|
||||||
|
'g0.step_input': queryOptions.step,
|
||||||
|
'g0.tab': 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const args = _.map(expr, (v: string, k: string) => {
|
||||||
|
return k + '=' + encodeURIComponent(v);
|
||||||
|
}).join('&');
|
||||||
|
return `${datasource.directUrl}/graph?${args}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
setHref(getExternalLink());
|
||||||
}
|
}
|
||||||
}
|
}, [panelData]);
|
||||||
|
|
||||||
async getExternalLink(panelData: PanelData): Promise<string> {
|
return (
|
||||||
const { query, datasource } = this.props;
|
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||||
const { request } = panelData;
|
Prometheus
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
if (!request) {
|
export default memo(PromLink);
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const range = request.range;
|
|
||||||
const start = datasource.getPrometheusTime(range.from, false);
|
|
||||||
const end = datasource.getPrometheusTime(range.to, true);
|
|
||||||
const rangeDiff = Math.ceil(end - start);
|
|
||||||
const endTime = range.to.utc().format('YYYY-MM-DD HH:mm');
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
interval: request.interval,
|
|
||||||
} as DataQueryRequest<PromQuery>;
|
|
||||||
|
|
||||||
const queryOptions = datasource.createQuery(query, options, start, end);
|
|
||||||
const expr = {
|
|
||||||
'g0.expr': queryOptions.expr,
|
|
||||||
'g0.range_input': rangeDiff + 's',
|
|
||||||
'g0.end_input': endTime,
|
|
||||||
'g0.step_input': queryOptions.step,
|
|
||||||
'g0.tab': 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const args = _.map(expr, (v: string, k: string) => {
|
|
||||||
return k + '=' + encodeURIComponent(v);
|
|
||||||
}).join('&');
|
|
||||||
return `${datasource.directUrl}/graph?${args}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { href } = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
|
||||||
Prometheus
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -164,7 +164,7 @@ exports[`Render PromQueryEditor with basic options should render 1`] = `
|
|||||||
tooltip="Link to Graph in Prometheus"
|
tooltip="Link to Graph in Prometheus"
|
||||||
width={10}
|
width={10}
|
||||||
>
|
>
|
||||||
<PromLink
|
<Memo(PromLink)
|
||||||
datasource={
|
datasource={
|
||||||
Object {
|
Object {
|
||||||
"createQuery": [MockFunction],
|
"createQuery": [MockFunction],
|
||||||
|
Loading…
Reference in New Issue
Block a user