Commit 114c426f by Zoltán Bedi Committed by GitHub

Zipkin: Show success on test data source (#30829)

* Zipkin: Show success on test data source

Add zipkin example app to devenv
Migrate to fetch api in data source

* Add back return types for functions
parent 1380fe72
# There is no data generator for this so easiest way to get some data here is run this example app # Generate traffic by hitting http://localhost:8081
# https://github.com/openzipkin/zipkin-js-example/tree/master/web frontend-example:
image: ghcr.io/openzipkin/brave-example
entrypoint: start-frontend
ports:
- 8081:8081
depends_on:
backend-example:
condition: service_healthy
zipkin:
condition: service_started
# Serves the /api endpoint the frontend uses
backend-example:
image: ghcr.io/openzipkin/brave-example
entrypoint: start-backend
depends_on:
zipkin:
condition: service_started
zipkin: zipkin:
image: openzipkin/zipkin:latest image: openzipkin/zipkin:latest
ports: ports:
......
import { ZipkinDatasource, ZipkinQuery } from './datasource'; import { DataSourceInstanceSettings } from '@grafana/data';
import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/data'; import { backendSrv } from 'app/core/services/backend_srv';
import { BackendSrv, BackendSrvRequest, setBackendSrv } from '@grafana/runtime'; import { of } from 'rxjs';
import { createFetchResponse } from 'test/helpers/createFetchResponse';
import { ZipkinDatasource } from './datasource';
import { jaegerTrace, zipkinResponse } from './utils/testData'; import { jaegerTrace, zipkinResponse } from './utils/testData';
jest.mock('@grafana/runtime', () => ({
...((jest.requireActual('@grafana/runtime') as unknown) as object),
getBackendSrv: () => backendSrv,
}));
describe('ZipkinDatasource', () => { describe('ZipkinDatasource', () => {
describe('query', () => { describe('query', () => {
it('runs query', async () => { it('runs query', async () => {
setupBackendSrv({ url: '/api/datasources/proxy/1/api/v2/trace/12345', response: zipkinResponse }); setupBackendSrv(zipkinResponse);
const ds = new ZipkinDatasource(defaultSettings); const ds = new ZipkinDatasource(defaultSettings);
const response = await ds.query({ targets: [{ query: '12345' }] } as DataQueryRequest<ZipkinQuery>).toPromise(); await expect(ds.query({ targets: [{ query: '12345' }] } as any)).toEmitValuesWith((val) => {
expect(response.data[0].fields[0].values.get(0)).toEqual(jaegerTrace); expect(val[0].data[0].fields[0].values.get(0)).toEqual(jaegerTrace);
});
}); });
it('runs query with traceId that includes special characters', async () => { it('runs query with traceId that includes special characters', async () => {
setupBackendSrv({ url: '/api/datasources/proxy/1/api/v2/trace/a%2Fb', response: zipkinResponse }); setupBackendSrv(zipkinResponse);
const ds = new ZipkinDatasource(defaultSettings); const ds = new ZipkinDatasource(defaultSettings);
const response = await ds.query({ targets: [{ query: 'a/b' }] } as DataQueryRequest<ZipkinQuery>).toPromise(); await expect(ds.query({ targets: [{ query: 'a/b' }] } as any)).toEmitValuesWith((val) => {
expect(response.data[0].fields[0].values.get(0)).toEqual(jaegerTrace); expect(val[0].data[0].fields[0].values.get(0)).toEqual(jaegerTrace);
});
}); });
}); });
describe('metadataRequest', () => { describe('metadataRequest', () => {
it('runs query', async () => { it('runs query', async () => {
setupBackendSrv({ url: '/api/datasources/proxy/1/api/v2/services', response: ['service 1', 'service 2'] }); setupBackendSrv(['service 1', 'service 2']);
const ds = new ZipkinDatasource(defaultSettings); const ds = new ZipkinDatasource(defaultSettings);
const response = await ds.metadataRequest('/api/v2/services'); const response = await ds.metadataRequest('/api/v2/services');
expect(response).toEqual(['service 1', 'service 2']); expect(response).toEqual(['service 1', 'service 2']);
...@@ -29,15 +38,11 @@ describe('ZipkinDatasource', () => { ...@@ -29,15 +38,11 @@ describe('ZipkinDatasource', () => {
}); });
}); });
function setupBackendSrv<T>({ url, response }: { url: string; response: T }): void { function setupBackendSrv(response: any) {
setBackendSrv({ const defaultMock = () => of(createFetchResponse(response));
datasourceRequest(options: BackendSrvRequest): Promise<any> {
if (options.url === url) { const fetchMock = jest.spyOn(backendSrv, 'fetch');
return Promise.resolve({ data: response }); fetchMock.mockImplementation(defaultMock);
}
throw new Error(`Unexpected url ${options.url}`);
},
} as BackendSrv);
} }
const defaultSettings: DataSourceInstanceSettings = { const defaultSettings: DataSourceInstanceSettings = {
......
import { import {
MutableDataFrame, DataQuery,
DataSourceApi,
DataSourceInstanceSettings,
DataQueryRequest, DataQueryRequest,
DataQueryResponse, DataQueryResponse,
DataQuery, DataSourceApi,
DataSourceInstanceSettings,
FieldType, FieldType,
MutableDataFrame,
} from '@grafana/data'; } from '@grafana/data';
import { from, Observable, of } from 'rxjs'; import { BackendSrvRequest, FetchResponse, getBackendSrv } from '@grafana/runtime';
import { serializeParams } from '../../../core/utils/fetch'; import { Observable, of } from 'rxjs';
import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { serializeParams } from '../../../core/utils/fetch';
import { apiPrefix } from './constants'; import { apiPrefix } from './constants';
import { ZipkinSpan } from './types'; import { ZipkinSpan } from './types';
import { transformResponse } from './utils/transforms'; import { transformResponse } from './utils/transforms';
...@@ -40,26 +40,28 @@ export class ZipkinDatasource extends DataSourceApi<ZipkinQuery> { ...@@ -40,26 +40,28 @@ export class ZipkinDatasource extends DataSourceApi<ZipkinQuery> {
return res.data; return res.data;
} }
async testDatasource(): Promise<any> { async testDatasource(): Promise<{ status: string; message: string }> {
await this.metadataRequest(`${apiPrefix}/services`); await this.metadataRequest(`${apiPrefix}/services`);
return true; return { status: 'success', message: 'Data source is working' };
} }
getQueryDisplayText(query: ZipkinQuery) { getQueryDisplayText(query: ZipkinQuery): string {
return query.query; return query.query;
} }
private request<T = any>(apiUrl: string, data?: any, options?: Partial<BackendSrvRequest>): Observable<{ data: T }> { private request<T = any>(
// Hack for proxying metadata requests apiUrl: string,
const baseUrl = `/api/datasources/proxy/${this.instanceSettings.id}`; data?: any,
options?: Partial<BackendSrvRequest>
): Observable<FetchResponse<T>> {
const params = data ? serializeParams(data) : ''; const params = data ? serializeParams(data) : '';
const url = `${baseUrl}${apiUrl}${params.length ? `?${params}` : ''}`; const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`;
const req = { const req = {
...options, ...options,
url, url,
}; };
return from(getBackendSrv().datasourceRequest(req)); return getBackendSrv().fetch<T>(req);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment