import { dateMath, DateTime, MutableDataFrame, DataSourceApi, DataSourceInstanceSettings, DataQueryRequest, DataQueryResponse, DataQuery, FieldType, } from '@grafana/data'; import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime'; import { Observable, from, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { serializeParams } from 'app/core/utils/fetch'; export type JaegerQuery = { query: string; } & DataQuery; export class JaegerDatasource extends DataSourceApi { constructor(private instanceSettings: DataSourceInstanceSettings) { super(instanceSettings); } async metadataRequest(url: string, params?: Record): Promise { const res = await this._request(url, params, { silent: true }).toPromise(); return res.data.data; } query(options: DataQueryRequest): Observable { // At this moment we expect only one target. In case we somehow change the UI to be able to show multiple // traces at one we need to change this. const id = options.targets[0]?.query; if (id) { // TODO: this api is internal, used in jaeger ui. Officially they have gRPC api that should be used. return this._request(`/api/traces/${id}`).pipe( map(response => { return { data: [ new MutableDataFrame({ fields: [ { name: 'trace', type: FieldType.trace, values: response?.data?.data || [], }, ], }), ], }; }) ); } else { return of({ data: [ new MutableDataFrame({ fields: [ { name: 'trace', type: FieldType.trace, values: [], }, ], }), ], }); } } async testDatasource(): Promise { return true; } getTimeRange(): { start: number; end: number } { const range = getTimeSrv().timeRange(); return { start: getTime(range.from, false), end: getTime(range.to, true), }; } getQueryDisplayText(query: JaegerQuery) { return query.query; } private _request(apiUrl: string, data?: any, options?: Partial): Observable> { // Hack for proxying metadata requests const baseUrl = `/api/datasources/proxy/${this.instanceSettings.id}`; const params = data ? serializeParams(data) : ''; const url = `${baseUrl}${apiUrl}${params.length ? `?${params}` : ''}`; const req = { ...options, url, }; return from(getBackendSrv().datasourceRequest(req)); } } function getTime(date: string | DateTime, roundUp: boolean) { if (typeof date === 'string') { date = dateMath.parse(date, roundUp)!; } return date.valueOf() * 1000; }