mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 00:55:47 -06:00
168 lines
4.8 KiB
TypeScript
168 lines
4.8 KiB
TypeScript
import { catchError, from, Observable, of, switchMap } from 'rxjs';
|
|
|
|
import {
|
|
AnnotationQuery,
|
|
DataQuery,
|
|
DataQueryRequest,
|
|
DataQueryResponse,
|
|
TestDataSourceResponse,
|
|
DataSourceApi,
|
|
DataSourceJsonData,
|
|
DataSourcePluginMeta,
|
|
DataSourceRef,
|
|
toDataFrame,
|
|
} from '@grafana/data';
|
|
import { BackendDataSourceResponse, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
|
|
|
|
import { GrafanaQueryType } from '../../../plugins/datasource/grafana/types';
|
|
import { MIXED_DATASOURCE_NAME } from '../../../plugins/datasource/mixed/MixedDataSource';
|
|
import { GRAFANA_DATASOURCE_NAME } from '../../alerting/unified/utils/datasource';
|
|
|
|
export const PUBLIC_DATASOURCE = '-- Public --';
|
|
export const DEFAULT_INTERVAL = '1min';
|
|
|
|
export class PublicDashboardDataSource extends DataSourceApi<DataQuery, DataSourceJsonData, {}> {
|
|
constructor(datasource: DataSourceRef | string | DataSourceApi | null) {
|
|
let meta = {} as DataSourcePluginMeta;
|
|
if (PublicDashboardDataSource.isMixedDatasource(datasource)) {
|
|
meta.mixed = true;
|
|
}
|
|
|
|
super({
|
|
name: 'public-ds',
|
|
id: 0,
|
|
type: 'public-ds',
|
|
meta,
|
|
uid: PublicDashboardDataSource.resolveUid(datasource),
|
|
jsonData: {},
|
|
access: 'proxy',
|
|
readOnly: true,
|
|
});
|
|
|
|
this.interval = PublicDashboardDataSource.resolveInterval(datasource);
|
|
|
|
this.annotations = {
|
|
prepareQuery(anno: AnnotationQuery): DataQuery | undefined {
|
|
return { ...anno, queryType: GrafanaQueryType.Annotations, refId: 'anno' };
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get the datasource uid based on the many types a datasource can be.
|
|
*/
|
|
private static resolveUid(datasource: DataSourceRef | string | DataSourceApi | null): string {
|
|
if (typeof datasource === 'string') {
|
|
return datasource;
|
|
}
|
|
|
|
return datasource?.uid ?? PUBLIC_DATASOURCE;
|
|
}
|
|
|
|
private static isMixedDatasource(datasource: DataSourceRef | string | DataSourceApi | null): boolean {
|
|
if (typeof datasource === 'string' || datasource == null) {
|
|
return false;
|
|
}
|
|
|
|
return datasource?.uid === MIXED_DATASOURCE_NAME;
|
|
}
|
|
|
|
private static resolveInterval(datasource: DataSourceRef | string | DataSourceApi | null): string {
|
|
if (typeof datasource === 'string' || datasource == null) {
|
|
return DEFAULT_INTERVAL;
|
|
}
|
|
|
|
const interval = 'interval' in datasource ? datasource.interval : undefined;
|
|
|
|
return interval ?? DEFAULT_INTERVAL;
|
|
}
|
|
|
|
/**
|
|
* Ideally final -- any other implementation may not work as expected
|
|
*/
|
|
query(request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
|
|
const {
|
|
intervalMs,
|
|
maxDataPoints,
|
|
requestId,
|
|
publicDashboardAccessToken,
|
|
panelId,
|
|
queryCachingTTL,
|
|
range: { from: fromRange, to: toRange },
|
|
} = request;
|
|
let queries: DataQuery[];
|
|
|
|
// Return early if no queries exist
|
|
if (!request.targets.length) {
|
|
return of({ data: [] });
|
|
}
|
|
|
|
// Its an annotations query
|
|
// Currently, annotations requests come in one at a time, so there will only be one target
|
|
const target = request.targets[0];
|
|
if (target.queryType === GrafanaQueryType.Annotations) {
|
|
if (target?.datasource?.uid === GRAFANA_DATASOURCE_NAME) {
|
|
return from(this.getAnnotations(request));
|
|
}
|
|
return of({ data: [] });
|
|
}
|
|
|
|
// Its a datasource query
|
|
else {
|
|
const body = {
|
|
intervalMs,
|
|
maxDataPoints,
|
|
queryCachingTTL,
|
|
timeRange: {
|
|
from: fromRange.valueOf().toString(),
|
|
to: toRange.valueOf().toString(),
|
|
timezone: this.getBrowserTimezone(),
|
|
},
|
|
};
|
|
|
|
return getBackendSrv()
|
|
.fetch<BackendDataSourceResponse>({
|
|
url: `/api/public/dashboards/${publicDashboardAccessToken}/panels/${panelId}/query`,
|
|
method: 'POST',
|
|
data: body,
|
|
requestId,
|
|
})
|
|
.pipe(
|
|
switchMap((raw) => {
|
|
return of(toDataQueryResponse(raw, queries));
|
|
}),
|
|
catchError((err) => {
|
|
return of(toDataQueryResponse(err));
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
async getAnnotations(request: DataQueryRequest<DataQuery>): Promise<DataQueryResponse> {
|
|
const {
|
|
publicDashboardAccessToken: accessToken,
|
|
range: { to, from },
|
|
} = request;
|
|
|
|
const params = {
|
|
from: from.valueOf(),
|
|
to: to.valueOf(),
|
|
};
|
|
|
|
const annotations = accessToken
|
|
? await getBackendSrv().get(`/api/public/dashboards/${accessToken}/annotations`, params)
|
|
: [];
|
|
|
|
return { data: [toDataFrame(annotations)] };
|
|
}
|
|
|
|
testDatasource(): Promise<TestDataSourceResponse> {
|
|
return Promise.resolve({ message: '', status: '' });
|
|
}
|
|
|
|
// Try to get the browser timezone otherwise return blank
|
|
getBrowserTimezone(): string {
|
|
return window.Intl?.DateTimeFormat().resolvedOptions()?.timeZone || '';
|
|
}
|
|
}
|