mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add data link from panel to cloudwatch console (#20061)
* Add data link from panel to cloudwatch console * Change conf variable name * Fixes according to pr feedback * Cleanup. Fix broken tests
This commit is contained in:
parent
a1e8157969
commit
69691fbd6e
@ -1,6 +1,6 @@
|
||||
import angular, { IQService } from 'angular';
|
||||
import _ from 'lodash';
|
||||
import { dateMath, ScopedVars } from '@grafana/data';
|
||||
import { dateMath, ScopedVars, toDataFrame, TimeRange } from '@grafana/data';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import { CloudWatchQuery } from './types';
|
||||
import { DataSourceApi, DataQueryRequest, DataSourceInstanceSettings } from '@grafana/ui';
|
||||
@ -92,7 +92,7 @@ export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery>
|
||||
queries: queries,
|
||||
};
|
||||
|
||||
return this.performTimeSeriesQuery(request);
|
||||
return this.performTimeSeriesQuery(request, options.range);
|
||||
}
|
||||
|
||||
getPeriod(target: any, options: any, now?: number) {
|
||||
@ -141,26 +141,75 @@ export default class CloudWatchDatasource extends DataSourceApi<CloudWatchQuery>
|
||||
return period;
|
||||
}
|
||||
|
||||
performTimeSeriesQuery(request: any) {
|
||||
buildCloudwatchConsoleUrl(
|
||||
{ region, namespace, metricName, dimensions, statistics, period }: CloudWatchQuery,
|
||||
start: string,
|
||||
end: string,
|
||||
title: string
|
||||
) {
|
||||
const conf = {
|
||||
view: 'timeSeries',
|
||||
stacked: false,
|
||||
title,
|
||||
start,
|
||||
end,
|
||||
region,
|
||||
metrics: [
|
||||
...statistics.map(stat => [
|
||||
namespace,
|
||||
metricName,
|
||||
...Object.entries(dimensions).reduce((acc, [key, value]) => [...acc, key, value], []),
|
||||
{
|
||||
stat,
|
||||
period,
|
||||
},
|
||||
]),
|
||||
],
|
||||
};
|
||||
|
||||
return `https://${region}.console.aws.amazon.com/cloudwatch/deeplink.js?region=${region}#metricsV2:graph=${encodeURIComponent(
|
||||
JSON.stringify(conf)
|
||||
)}`;
|
||||
}
|
||||
|
||||
performTimeSeriesQuery(request: any, { from, to }: TimeRange) {
|
||||
return this.awsRequest('/api/tsdb/query', request).then((res: any) => {
|
||||
const data = [];
|
||||
|
||||
if (res.results) {
|
||||
for (const query of request.queries) {
|
||||
const queryRes = res.results[query.refId];
|
||||
if (queryRes) {
|
||||
for (const series of queryRes.series) {
|
||||
const s = { target: series.name, datapoints: series.points } as any;
|
||||
if (queryRes.meta.unit) {
|
||||
s.unit = queryRes.meta.unit;
|
||||
}
|
||||
data.push(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res.results) {
|
||||
return { data: [] };
|
||||
}
|
||||
const dataFrames = Object.values(request.queries).reduce((acc: any, queryRequest: any) => {
|
||||
const queryResult = res.results[queryRequest.refId];
|
||||
if (!queryResult) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return { data: data };
|
||||
const link = this.buildCloudwatchConsoleUrl(
|
||||
queryRequest,
|
||||
from.toISOString(),
|
||||
to.toISOString(),
|
||||
`query${queryRequest.refId}`
|
||||
);
|
||||
|
||||
return [
|
||||
...acc,
|
||||
...queryResult.series.map(({ name, points, meta }: any) => {
|
||||
const series = { target: name, datapoints: points };
|
||||
const dataFrame = toDataFrame(meta && meta.unit ? { ...series, unit: meta.unit } : series);
|
||||
for (const field of dataFrame.fields) {
|
||||
field.config.links = [
|
||||
{
|
||||
url: link,
|
||||
title: 'View in CloudWatch console',
|
||||
targetBlank: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
return dataFrame;
|
||||
}),
|
||||
];
|
||||
}, []);
|
||||
|
||||
return { data: dataFrames };
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ describe('CloudWatchDatasource', () => {
|
||||
} as DataSourceInstanceSettings;
|
||||
|
||||
const templateSrv = new TemplateSrv();
|
||||
const start = 1483196400 * 1000;
|
||||
const defaultTimeRange = { from: new Date(start), to: new Date(start + 3600 * 1000) };
|
||||
|
||||
const timeSrv = {
|
||||
time: { from: 'now-1h', to: 'now' },
|
||||
@ -39,7 +41,7 @@ describe('CloudWatchDatasource', () => {
|
||||
let requestParams: { queries: CloudWatchQuery[] };
|
||||
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -110,7 +112,7 @@ describe('CloudWatchDatasource', () => {
|
||||
]);
|
||||
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -136,7 +138,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it.each(['pNN.NN', 'p9', 'p99.', 'p99.999'])('should cancel query for invalid extended statistics (%s)', stat => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -157,8 +159,8 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should return series list', done => {
|
||||
ctx.ds.query(query).then((result: any) => {
|
||||
expect(result.data[0].target).toBe(response.results.A.series[0].name);
|
||||
expect(result.data[0].datapoints[0][0]).toBe(response.results.A.series[0].points[0][0]);
|
||||
expect(result.data[0].name).toBe(response.results.A.series[0].name);
|
||||
expect(result.data[0].fields[0].values.buffer[0]).toBe(response.results.A.series[0].points[0][0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -187,7 +189,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should query for the datasource region if empty or "default"', done => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -213,7 +215,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
describe('When performing CloudWatch query for extended statistics', () => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -260,8 +262,8 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should return series list', done => {
|
||||
ctx.ds.query(query).then((result: any) => {
|
||||
expect(result.data[0].target).toBe(response.results.A.series[0].name);
|
||||
expect(result.data[0].datapoints[0][0]).toBe(response.results.A.series[0].points[0][0]);
|
||||
expect(result.data[0].name).toBe(response.results.A.series[0].name);
|
||||
expect(result.data[0].fields[0].values.buffer[0]).toBe(response.results.A.series[0].points[0][0]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -316,7 +318,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should generate the correct query for single template variable', done => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -341,7 +343,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should generate the correct query for multilple template variables', done => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -377,7 +379,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should generate the correct query for multilple template variables, lack scopedVars', done => {
|
||||
const query = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
@ -412,7 +414,7 @@ describe('CloudWatchDatasource', () => {
|
||||
|
||||
it('should generate the correct query for multilple template variables with expression', done => {
|
||||
const query: any = {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
range: defaultTimeRange,
|
||||
rangeRaw: { from: 1483228800, to: 1483232400 },
|
||||
targets: [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user