From 114c426f341caf88a21907872e99a2d68d80f9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Bedi?= Date: Fri, 19 Feb 2021 15:38:16 +0100 Subject: [PATCH] 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 --- .../docker/blocks/zipkin/docker-compose.yaml | 20 ++++++++- .../datasource/zipkin/datasource.test.ts | 43 +++++++++++-------- .../plugins/datasource/zipkin/datasource.ts | 32 +++++++------- 3 files changed, 59 insertions(+), 36 deletions(-) diff --git a/devenv/docker/blocks/zipkin/docker-compose.yaml b/devenv/docker/blocks/zipkin/docker-compose.yaml index 55f8792df4f..f887cb4afe7 100644 --- a/devenv/docker/blocks/zipkin/docker-compose.yaml +++ b/devenv/docker/blocks/zipkin/docker-compose.yaml @@ -1,5 +1,21 @@ -# There is no data generator for this so easiest way to get some data here is run this example app -# https://github.com/openzipkin/zipkin-js-example/tree/master/web + # Generate traffic by hitting http://localhost:8081 + 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: image: openzipkin/zipkin:latest ports: diff --git a/public/app/plugins/datasource/zipkin/datasource.test.ts b/public/app/plugins/datasource/zipkin/datasource.test.ts index bd0ccd9a493..ac3767c7fc1 100644 --- a/public/app/plugins/datasource/zipkin/datasource.test.ts +++ b/public/app/plugins/datasource/zipkin/datasource.test.ts @@ -1,27 +1,36 @@ -import { ZipkinDatasource, ZipkinQuery } from './datasource'; -import { DataQueryRequest, DataSourceInstanceSettings } from '@grafana/data'; -import { BackendSrv, BackendSrvRequest, setBackendSrv } from '@grafana/runtime'; +import { DataSourceInstanceSettings } from '@grafana/data'; +import { backendSrv } from 'app/core/services/backend_srv'; +import { of } from 'rxjs'; +import { createFetchResponse } from 'test/helpers/createFetchResponse'; +import { ZipkinDatasource } from './datasource'; import { jaegerTrace, zipkinResponse } from './utils/testData'; +jest.mock('@grafana/runtime', () => ({ + ...((jest.requireActual('@grafana/runtime') as unknown) as object), + getBackendSrv: () => backendSrv, +})); + describe('ZipkinDatasource', () => { describe('query', () => { it('runs query', async () => { - setupBackendSrv({ url: '/api/datasources/proxy/1/api/v2/trace/12345', response: zipkinResponse }); + setupBackendSrv(zipkinResponse); const ds = new ZipkinDatasource(defaultSettings); - const response = await ds.query({ targets: [{ query: '12345' }] } as DataQueryRequest).toPromise(); - expect(response.data[0].fields[0].values.get(0)).toEqual(jaegerTrace); + await expect(ds.query({ targets: [{ query: '12345' }] } as any)).toEmitValuesWith((val) => { + expect(val[0].data[0].fields[0].values.get(0)).toEqual(jaegerTrace); + }); }); 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 response = await ds.query({ targets: [{ query: 'a/b' }] } as DataQueryRequest).toPromise(); - expect(response.data[0].fields[0].values.get(0)).toEqual(jaegerTrace); + await expect(ds.query({ targets: [{ query: 'a/b' }] } as any)).toEmitValuesWith((val) => { + expect(val[0].data[0].fields[0].values.get(0)).toEqual(jaegerTrace); + }); }); }); describe('metadataRequest', () => { 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 response = await ds.metadataRequest('/api/v2/services'); expect(response).toEqual(['service 1', 'service 2']); @@ -29,15 +38,11 @@ describe('ZipkinDatasource', () => { }); }); -function setupBackendSrv({ url, response }: { url: string; response: T }): void { - setBackendSrv({ - datasourceRequest(options: BackendSrvRequest): Promise { - if (options.url === url) { - return Promise.resolve({ data: response }); - } - throw new Error(`Unexpected url ${options.url}`); - }, - } as BackendSrv); +function setupBackendSrv(response: any) { + const defaultMock = () => of(createFetchResponse(response)); + + const fetchMock = jest.spyOn(backendSrv, 'fetch'); + fetchMock.mockImplementation(defaultMock); } const defaultSettings: DataSourceInstanceSettings = { diff --git a/public/app/plugins/datasource/zipkin/datasource.ts b/public/app/plugins/datasource/zipkin/datasource.ts index aac1abf6ab9..a8bd41ee2b7 100644 --- a/public/app/plugins/datasource/zipkin/datasource.ts +++ b/public/app/plugins/datasource/zipkin/datasource.ts @@ -1,16 +1,16 @@ import { - MutableDataFrame, - DataSourceApi, - DataSourceInstanceSettings, + DataQuery, DataQueryRequest, DataQueryResponse, - DataQuery, + DataSourceApi, + DataSourceInstanceSettings, FieldType, + MutableDataFrame, } from '@grafana/data'; -import { from, Observable, of } from 'rxjs'; -import { serializeParams } from '../../../core/utils/fetch'; -import { getBackendSrv, BackendSrvRequest } from '@grafana/runtime'; +import { BackendSrvRequest, FetchResponse, getBackendSrv } from '@grafana/runtime'; +import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; +import { serializeParams } from '../../../core/utils/fetch'; import { apiPrefix } from './constants'; import { ZipkinSpan } from './types'; import { transformResponse } from './utils/transforms'; @@ -40,26 +40,28 @@ export class ZipkinDatasource extends DataSourceApi { return res.data; } - async testDatasource(): Promise { + async testDatasource(): Promise<{ status: string; message: string }> { 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; } - private request(apiUrl: string, data?: any, options?: Partial): Observable<{ data: T }> { - // Hack for proxying metadata requests - const baseUrl = `/api/datasources/proxy/${this.instanceSettings.id}`; + private request( + apiUrl: string, + data?: any, + options?: Partial + ): Observable> { const params = data ? serializeParams(data) : ''; - const url = `${baseUrl}${apiUrl}${params.length ? `?${params}` : ''}`; + const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`; const req = { ...options, url, }; - return from(getBackendSrv().datasourceRequest(req)); + return getBackendSrv().fetch(req); } }