diff --git a/packages/jaeger-ui/src/middlewares/fixtures/JaegerTrace.json b/packages/jaeger-ui/src/middlewares/fixtures/JaegerTrace.json new file mode 100644 index 0000000000..d769e25bf3 --- /dev/null +++ b/packages/jaeger-ui/src/middlewares/fixtures/JaegerTrace.json @@ -0,0 +1,344 @@ +{ + "data": [ + { + "traceID": "83a9efd15c1c98a977e0711cc93ee28b", + "spans": [ + { + "traceID": "83a9efd15c1c98a977e0711cc93ee28b", + "spanID": "e127af99e3b3e074", + "operationName": "okey-dokey-0", + "references": [ + { + "refType": "CHILD_OF", + "traceID": "83a9efd15c1c98a977e0711cc93ee28b", + "spanID": "909541b92cf05311" + } + ], + "startTime": 1706678909209712, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-client" + }, + { + "key": "span.kind", + "type": "string", + "value": "server" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + }, + { + "traceID": "83a9efd15c1c98a977e0711cc93ee28b", + "spanID": "909541b92cf05311", + "operationName": "lets-go", + "references": [], + "startTime": 1706678909209712, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-server" + }, + { + "key": "span.kind", + "type": "string", + "value": "client" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + } + ], + "processes": { + "p1": { + "serviceName": "telemetrygen", + "tags": [] + } + }, + "warnings": null + }, + { + "traceID": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spans": [ + { + "traceID": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spanID": "22155fa8edf115a6", + "operationName": "okey-dokey-0", + "references": [ + { + "refType": "CHILD_OF", + "traceID": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spanID": "91df847d72e34094" + } + ], + "startTime": 1706678909210005, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-client" + }, + { + "key": "span.kind", + "type": "string", + "value": "server" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + }, + { + "traceID": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spanID": "91df847d72e34094", + "operationName": "lets-go", + "references": [], + "startTime": 1706678909210005, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-server" + }, + { + "key": "span.kind", + "type": "string", + "value": "client" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + } + ], + "processes": { + "p1": { + "serviceName": "telemetrygen", + "tags": [] + } + }, + "warnings": null + }, + { + "traceID": "52e8b39b402eeafcad436a31c7d7cf94", + "spans": [ + { + "traceID": "52e8b39b402eeafcad436a31c7d7cf94", + "spanID": "77008e091d47750d", + "operationName": "okey-dokey-0", + "references": [ + { + "refType": "CHILD_OF", + "traceID": "52e8b39b402eeafcad436a31c7d7cf94", + "spanID": "2622076f65524852" + } + ], + "startTime": 1706678909210008, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-client" + }, + { + "key": "span.kind", + "type": "string", + "value": "server" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + }, + { + "traceID": "52e8b39b402eeafcad436a31c7d7cf94", + "spanID": "2622076f65524852", + "operationName": "lets-go", + "references": [], + "startTime": 1706678909210008, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-server" + }, + { + "key": "span.kind", + "type": "string", + "value": "client" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + } + ], + "processes": { + "p1": { + "serviceName": "telemetrygen", + "tags": [] + } + }, + "warnings": null + }, + { + "traceID": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spans": [ + { + "traceID": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spanID": "4879bcfa0cdd33a4", + "operationName": "okey-dokey-0", + "references": [ + { + "refType": "CHILD_OF", + "traceID": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spanID": "b95af47b0f3a7823" + } + ], + "startTime": 1706678909210014, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-client" + }, + { + "key": "span.kind", + "type": "string", + "value": "server" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + }, + { + "traceID": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spanID": "b95af47b0f3a7823", + "operationName": "lets-go", + "references": [], + "startTime": 1706678909210014, + "duration": 123, + "tags": [ + { + "key": "otel.library.name", + "type": "string", + "value": "telemetrygen" + }, + { + "key": "net.peer.ip", + "type": "string", + "value": "1.2.3.4" + }, + { + "key": "peer.service", + "type": "string", + "value": "telemetrygen-server" + }, + { + "key": "span.kind", + "type": "string", + "value": "client" + } + ], + "logs": [], + "processID": "p1", + "warnings": null + } + ], + "processes": { + "p1": { + "serviceName": "telemetrygen", + "tags": [] + } + }, + "warnings": null + } + ], + "total": 0, + "limit": 0, + "offset": 0, + "errors": null +} diff --git a/packages/jaeger-ui/src/middlewares/fixtures/OTLPTrace.json b/packages/jaeger-ui/src/middlewares/fixtures/OTLPTrace.json new file mode 100644 index 0000000000..bbf652f6d0 --- /dev/null +++ b/packages/jaeger-ui/src/middlewares/fixtures/OTLPTrace.json @@ -0,0 +1,218 @@ +{ + "resourceSpans": [ + { + "resource": { + "attributes": [ + { + "key": "service.name", + "value": { + "stringValue": "telemetrygen" + } + } + ] + }, + "scopeSpans": [ + { + "scope": { + "name": "telemetrygen" + }, + "spans": [ + { + "traceId": "83a9efd15c1c98a977e0711cc93ee28b", + "spanId": "e127af99e3b3e074", + "parentSpanId": "909541b92cf05311", + "name": "okey-dokey-0", + "kind": 2, + "startTimeUnixNano": "1706678909209712000", + "endTimeUnixNano": "1706678909209835000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-client" + } + } + ], + "status": {} + }, + { + "traceId": "83a9efd15c1c98a977e0711cc93ee28b", + "spanId": "909541b92cf05311", + "parentSpanId": "", + "name": "lets-go", + "kind": 3, + "startTimeUnixNano": "1706678909209712000", + "endTimeUnixNano": "1706678909209835000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-server" + } + } + ], + "status": {} + }, + { + "traceId": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spanId": "22155fa8edf115a6", + "parentSpanId": "91df847d72e34094", + "name": "okey-dokey-0", + "kind": 2, + "startTimeUnixNano": "1706678909210005000", + "endTimeUnixNano": "1706678909210128000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-client" + } + } + ], + "status": {} + }, + { + "traceId": "c75c2ec1065c70cbc7ed8d3e4b50c7d1", + "spanId": "91df847d72e34094", + "parentSpanId": "", + "name": "lets-go", + "kind": 3, + "startTimeUnixNano": "1706678909210005000", + "endTimeUnixNano": "1706678909210128000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-server" + } + } + ], + "status": {} + }, + { + "traceId": "52e8b39b402eeafcad436a31c7d7cf94", + "spanId": "77008e091d47750d", + "parentSpanId": "2622076f65524852", + "name": "okey-dokey-0", + "kind": 2, + "startTimeUnixNano": "1706678909210008000", + "endTimeUnixNano": "1706678909210131000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-client" + } + } + ], + "status": {} + }, + { + "traceId": "52e8b39b402eeafcad436a31c7d7cf94", + "spanId": "2622076f65524852", + "parentSpanId": "", + "name": "lets-go", + "kind": 3, + "startTimeUnixNano": "1706678909210008000", + "endTimeUnixNano": "1706678909210131000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-server" + } + } + ], + "status": {} + }, + { + "traceId": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spanId": "4879bcfa0cdd33a4", + "parentSpanId": "b95af47b0f3a7823", + "name": "okey-dokey-0", + "kind": 2, + "startTimeUnixNano": "1706678909210014000", + "endTimeUnixNano": "1706678909210137000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-client" + } + } + ], + "status": {} + }, + { + "traceId": "2f6e6d98f1972dfca3f619ca48ce28a7", + "spanId": "b95af47b0f3a7823", + "parentSpanId": "", + "name": "lets-go", + "kind": 3, + "startTimeUnixNano": "1706678909210014000", + "endTimeUnixNano": "1706678909210137000", + "attributes": [ + { + "key": "net.peer.ip", + "value": { + "stringValue": "1.2.3.4" + } + }, + { + "key": "peer.service", + "value": { + "stringValue": "telemetrygen-server" + } + } + ], + "status": {} + } + ] + } + ], + "schemaUrl": "https://opentelemetry.io/schemas/1.4.0" + } + ] +} diff --git a/packages/jaeger-ui/src/middlewares/index.js b/packages/jaeger-ui/src/middlewares/index.js index c93918fc30..40a401c2c4 100644 --- a/packages/jaeger-ui/src/middlewares/index.js +++ b/packages/jaeger-ui/src/middlewares/index.js @@ -47,7 +47,7 @@ export const historyUpdateMiddleware = store => next => action => { return next(action); }; -export const transformOTLPMiddleware = store => next => action => { +export const loadJsonTracesMiddleware = store => next => action => { if (action.type === String([`${loadJsonTraces}_FULFILLED`])) { // Check if action.payload is OTLP and make API call if so // We are allowed to change the action.payload here diff --git a/packages/jaeger-ui/src/middlewares/index.test.js b/packages/jaeger-ui/src/middlewares/index.test.js index 933102bea5..efa51fd810 100644 --- a/packages/jaeger-ui/src/middlewares/index.test.js +++ b/packages/jaeger-ui/src/middlewares/index.test.js @@ -24,9 +24,22 @@ jest.mock( ); import { change } from 'redux-form'; - +import fs from 'fs'; +import _ from 'lodash'; import * as jaegerMiddlewares from './index'; import { fetchServiceOperations } from '../actions/jaeger-api'; +import { loadJsonTraces } from '../actions/file-reader-api'; +import JaegerAPI from '../api/jaeger'; + +jest.spyOn(JaegerAPI, 'transformOTLP').mockImplementation(APICallRequest => { + const OTLPTrace = JSON.parse(fs.readFileSync('src/middlewares/fixtures/OTLPTrace.json', 'utf-8')); + const jaegerTrace = JSON.parse(fs.readFileSync('src/middlewares/fixtures/JaegerTrace.json', 'utf-8')); + if (_.isEqual(APICallRequest, OTLPTrace)) { + return Promise.resolve(jaegerTrace); + } + // This defines case where API call errors out even after detecting a `resourceSpan` in the request: + return Promise.reject(); +}); it('jaegerMiddlewares should contain the promise middleware', () => { expect(typeof jaegerMiddlewares.promise).toBe('function'); @@ -41,3 +54,32 @@ it('loadOperationsForServiceMiddleware fetches operations for services', () => { expect(dispatch).toHaveBeenCalledWith(fetchServiceOperations('yo')); expect(dispatch).toHaveBeenCalledWith(change('searchSideBar', 'operation', 'all')); }); + +it('loadJsonTracesMiddleware transformes traces from OTLP to jaeger by making an API call', async () => { + // Testing 3 paths in all : + // OTLP traces + // Jaeger traces + // Ivalid traces + const { loadJsonTracesMiddleware } = jaegerMiddlewares; + const dispatch = jest.fn(); + const next = jest.fn(); + + const OTLPFileAction = { + type: String([`${loadJsonTraces}_FULFILLED`]), + payload: JSON.parse(fs.readFileSync('src/middlewares/fixtures/OTLPTrace.json', 'utf-8')), + }; + + const JaegerAction = { + type: String([`${loadJsonTraces}_FULFILLED`]), + payload: JSON.parse(fs.readFileSync('src/middlewares/fixtures/JaegerTrace.json', 'utf-8')), + }; + + await loadJsonTracesMiddleware({ dispatch })(next)(OTLPFileAction); + expect(JaegerAPI.transformOTLP).toHaveBeenCalledWith(OTLPFileAction.payload); + expect(next).toHaveBeenCalledWith(JaegerAction); + jest.clearAllMocks(); + await loadJsonTracesMiddleware({ dispatch })(next)(JaegerAction); + expect(JaegerAPI.transformOTLP).not.toHaveBeenCalled(); + expect(next).toHaveBeenCalledWith(JaegerAction); + // Errored JSON are caught before any redux action is invoked +});