/usr/share/grafana/public/app/plugins/datasource/jaeger
import { lastValueFrom, of } from 'rxjs'; import { DataQueryRequest, DataSourceInstanceSettings, dateTime, FieldType, PluginMetaInfo, PluginType, ScopedVars, } from '@grafana/data'; import { BackendSrv, DataSourceWithBackend } from '@grafana/runtime'; import { JaegerDatasource, JaegerJsonData } from './datasource'; import mockJson from './mockJsonResponse.json'; import mockSearchResponse from './mockSearchResponse.json'; import mockTraceResponse from './mockTraceResponse.json'; import { JaegerQuery } from './types'; export const backendSrv = { fetch: jest.fn() } as unknown as BackendSrv; jest.mock('@grafana/runtime', () => ({ ...jest.requireActual('@grafana/runtime'), getBackendSrv: () => backendSrv, getTemplateSrv: () => ({ replace: (val: string, subs: ScopedVars): string => { return subs[val]?.value ?? val; }, containsTemplate: (val: string): boolean => { return val.includes('$'); }, }), })); describe('upload, search and trace query types', () => { it('should process valid JSON file uploads', async () => { const ds = new JaegerDatasource(defaultSettings); ds.uploadedJson = JSON.stringify(mockJson); const response = await lastValueFrom(ds.query({ ...defaultQuery, targets: [{ queryType: 'upload', refId: 'A' }] })); const field = response.data[0].fields[0]; expect(field.name).toBe('traceID'); expect(field.type).toBe(FieldType.string); expect(field.values.length).toBe(2); }); it('should reject invalid JSON file uploads', async () => { const ds = new JaegerDatasource(defaultSettings); ds.uploadedJson = JSON.stringify({ key: 'value', arr: [] }); const response = await lastValueFrom( ds.query({ targets: [{ queryType: 'upload', refId: 'A' }] } as DataQueryRequest<JaegerQuery>) ); expect(response.error?.message).toBe('The JSON file uploaded is not in a valid Jaeger format'); expect(response.data.length).toBe(0); }); it('should return search results when query type is search', async () => { setupQueryMock('search'); const ds = new JaegerDatasource(defaultSettings); const response = await lastValueFrom( ds.query({ ...defaultQuery, targets: [{ queryType: 'search', refId: 'a', service: 'jaeger-query', operation: '/api/services' }], }) ); expect(response.data[0].meta.preferredVisualisationType).toBe('table'); expect(response.data[0].fields[0].config.links).toHaveLength(1); expect(response.data[0].fields[0].name).toBe('traceID'); }); it('should return trace results when query type is trace', async () => { setupQueryMock('trace'); const ds = new JaegerDatasource(defaultSettings); const response = await lastValueFrom( ds.query({ ...defaultQuery, targets: [{ queryType: undefined, refId: 'a', query: '12345' }] }) ); expect(response.data[0].meta.preferredVisualisationType).toBe('trace'); expect(response.data[0].fields.length).toBe(7); }); }); describe('node graph functionality', () => { it('should include node graph frames when nodeGraph is enabled for trace queries', async () => { const settingsWithNodeGraph = { ...defaultSettings, jsonData: { ...defaultSettings.jsonData, nodeGraph: { enabled: true }, }, }; const ds = new JaegerDatasource(settingsWithNodeGraph); setupQueryMock('trace'); const response = await lastValueFrom( ds.query({ ...defaultQuery, targets: [ { query: '12345', refId: '1', }, ], }) ); expect(response.data.length).toBe(3); }); it('should exclude node graph frames when nodeGraph is disabled for trace queries', async () => { const settingsWithoutNodeGraph = { ...defaultSettings, jsonData: { ...defaultSettings.jsonData, nodeGraph: { enabled: false }, }, }; const ds = new JaegerDatasource(settingsWithoutNodeGraph); setupQueryMock('trace'); const response = await lastValueFrom( ds.query({ ...defaultQuery, targets: [ { query: '12345', refId: '1', }, ], }) ); expect(response.data.length).toBe(1); }); }); function setupQueryMock(type: 'trace' | 'search') { return jest.spyOn(DataSourceWithBackend.prototype, 'query').mockImplementation(() => { if (type === 'search') { return of(mockSearchResponse); } else { return of(mockTraceResponse); } }); } const defaultSettings: DataSourceInstanceSettings<JaegerJsonData> = { id: 0, uid: '0', type: 'tracing', name: 'jaeger', url: 'http://grafana.com', access: 'proxy', meta: { id: 'jaeger', name: 'jaeger', type: PluginType.datasource, info: {} as PluginMetaInfo, module: '', baseUrl: '', }, jsonData: { nodeGraph: { enabled: true, }, }, readOnly: false, }; const defaultQuery: DataQueryRequest<JaegerQuery> = { requestId: '1', interval: '0', intervalMs: 10, panelId: 0, scopedVars: {}, range: { from: dateTime().subtract(1, 'h'), to: dateTime(), raw: { from: '1h', to: 'now' }, }, timezone: 'browser', app: 'explore', startTime: 0, targets: [ { query: '12345', refId: '1', }, ], };
.
Edit
..
Edit
CHANGELOG.md
Edit
CheatSheet.tsx
Edit
README.md
Edit
components
Edit
configuration
Edit
datasource.test.ts
Edit
datasource.ts
Edit
dist
Edit
graphTransform.test.ts
Edit
graphTransform.ts
Edit
helpers
Edit
img
Edit
jest-setup.js
Edit
jest.config.js
Edit
mockJsonResponse.json
Edit
mockSearchResponse.json
Edit
mockTraceResponse.json
Edit
module.ts
Edit
package.json
Edit
plugin.json
Edit
project.json
Edit
responseTransform.test.ts
Edit
responseTransform.ts
Edit
testResponse.ts
Edit
tsconfig.json
Edit
types.ts
Edit
webpack.config.ts
Edit