Skip to content

Commit

Permalink
Merge pull request #466 from everett980/ddg-update-payload-format
Browse files Browse the repository at this point in the history
Consume new API format
  • Loading branch information
everett980 committed Oct 15, 2019
2 parents c5eaca5 + 8efe8ec commit 98530d6
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,30 @@ export default class DdgNodeContent extends React.PureComponent<TProps> {
const { vertexKey, getVisiblePathElems } = this.props;
const elems = getVisiblePathElems(vertexKey);
if (elems) {
const ids: Set<string> = new Set();
const urlIds: Set<string> = new Set();
let currLength = MIN_LENGTH;
for (let i = 0; i < elems.length; i++) {
const id = elems[i].memberOf.traceID;
if (ids.has(id)) {
continue;
}
// Keep track of the length, then break if it is too long, to avoid opening a tab with a URL that the
// backend cannot process, even if there are more traceIDs
currLength += PARAM_NAME_LENGTH + id.length;
if (currLength > MAX_LENGTH) {
break;
}
ids.add(id);
if (ids.size >= MAX_LINKED_TRACES) {
break;
// Because there is a limit on traceIDs, attempt to get some from each elem rather than all from one.
const allIDs = elems.map(({ memberOf: m }) => m.traceIDs.slice());
while (allIDs.length) {
const ids = allIDs.shift();
if (ids && ids.length) {
const id = ids.pop();
if (id && !urlIds.has(id)) {
// Keep track of the length, then break if it is too long, to avoid opening a tab with a URL that
// the backend cannot process, even if there are more traceIDs
currLength += PARAM_NAME_LENGTH + id.length;
if (currLength > MAX_LENGTH) {
break;
}
urlIds.add(id);
if (urlIds.size >= MAX_LINKED_TRACES) {
break;
}
}
allIDs.push(ids);
}
}
window.open(getSearchUrl({ traceID: Array.from(ids) }), '_blank');
window.open(getSearchUrl({ traceID: Array.from(urlIds) }), '_blank');
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import * as codec from '../../../../model/ddg/visibility-codec';
import HopsSelector from '.';

describe('HopsSelector', () => {
const { distanceToPathElems } = transformDdgData([longSimplePath, simplePath].map(wrap), focalPayloadElem);
const { distanceToPathElems: shortPathElems } = transformDdgData([shortPath].map(wrap), focalPayloadElem);
const { distanceToPathElems } = transformDdgData(wrap([longSimplePath, simplePath]), focalPayloadElem);
const { distanceToPathElems: shortPathElems } = transformDdgData(wrap([shortPath]), focalPayloadElem);

describe('without distanceToPathElems', () => {
it('renders empty div', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import GraphModel from './index';
import transformDdgData from '../transformDdgData';
import { wrap } from '../sample-paths.test.resources';
import { EDdgDensity } from '../types';

function makePayloadEntry(pairStr) {
Expand All @@ -30,12 +31,12 @@ const payload = `
`
.trim()
.split('\n')
.map(line => ({
path: line
.map(line =>
line
.trim()
.split(/\s+/g)
.map(makePayloadEntry),
}));
.map(makePayloadEntry)
);

const testTable = [
// showOp, density, number of expected vertices
Expand All @@ -52,7 +53,7 @@ const testTable = [
];

describe('getPathElemHasher()', () => {
const ddgModel = transformDdgData(payload, makePayloadEntry('focal:focal'));
const ddgModel = transformDdgData(wrap(payload), makePayloadEntry('focal:focal'));

describe('creates vertices based on density and showOp', () => {
it.each(testTable)('showOp: %p \t density: %p', (showOp, density, verticesCount) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/jaeger-ui/src/model/ddg/GraphModel/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { EDdgDensity } from '../types';
import { encode } from '../visibility-codec';

describe('GraphModel', () => {
const convergentModel = transformDdgData(convergentPaths.map(wrap), focalPayloadElem);
const doubleFocalModel = transformDdgData([doubleFocalPath, simplePath].map(wrap), focalPayloadElem);
const simpleModel = transformDdgData([simplePath].map(wrap), focalPayloadElem);
const convergentModel = transformDdgData(wrap(convergentPaths), focalPayloadElem);
const doubleFocalModel = transformDdgData(wrap([doubleFocalPath, simplePath]), focalPayloadElem);
const simpleModel = transformDdgData(wrap([simplePath]), focalPayloadElem);

/**
* This function takes in a Graph and validates the structure based on the expected vertices.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,6 @@ export const convergentPaths = [
[firstPayloadElem, focalPayloadElem, divergentPayloadElem, afterPayloadElem, lastPayloadElem],
];

export const wrap = path => ({ path });
export const wrap = paths => ({
dependencies: paths.map(path => ({ path, attributes: [] })),
});
38 changes: 30 additions & 8 deletions packages/jaeger-ui/src/model/ddg/transformDdgData.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('transform ddg data', () => {
? { service: focalPayloadElem.service }
: focalPayloadElem;
const { paths, services, visIdxToPathElem } = transformDdgData(
payload.map(testResources.wrap),
testResources.wrap(payload),
focalPayloadElemArgument
);

Expand Down Expand Up @@ -124,11 +124,11 @@ describe('transform ddg data', () => {
almostDoubleFocalPath,
} = testResources;
const { visIdxToPathElem: presortedPathsVisIdxToPathElem } = transformDdgData(
[simplePath, doubleFocalPath, almostDoubleFocalPath, longSimplePath].map(testResources.wrap),
testResources.wrap([simplePath, doubleFocalPath, almostDoubleFocalPath, longSimplePath]),
focalPayloadElem
);
const { visIdxToPathElem: unsortedPathsVisIdxToPathElem } = transformDdgData(
[longSimplePath, almostDoubleFocalPath, simplePath, doubleFocalPath].map(testResources.wrap),
testResources.wrap([longSimplePath, almostDoubleFocalPath, simplePath, doubleFocalPath]),
focalPayloadElem
);

Expand Down Expand Up @@ -166,21 +166,43 @@ describe('transform ddg data', () => {
it('throws an error if a path lacks the focalPayloadElem', () => {
const { simplePath, noFocalPath, doubleFocalPath, focalPayloadElem } = testResources;
expect(() =>
transformDdgData([simplePath, noFocalPath, doubleFocalPath].map(testResources.wrap), focalPayloadElem)
).toThrowError();
transformDdgData(testResources.wrap([simplePath, noFocalPath, doubleFocalPath]), focalPayloadElem)
).toThrowError(/focalNode/);
});

it('creates equal hashes iff paths are equivalent', () => {
const { focalPayloadElem, doubleFocalPath, longSimplePath, simplePath, wrap } = testResources;
const simpleModel = transformDdgData([simplePath, longSimplePath].map(wrap), focalPayloadElem);
const reverseModel = transformDdgData([longSimplePath, simplePath].map(wrap), focalPayloadElem);
const simpleModel = transformDdgData(wrap([simplePath, longSimplePath]), focalPayloadElem);
const reverseModel = transformDdgData(wrap([longSimplePath, simplePath]), focalPayloadElem);

expect(reverseModel).not.toEqual(simpleModel);
expect(reverseModel).not.toBe(simpleModel);
expect(reverseModel.hash).toBe(simpleModel.hash);

const diffModel = transformDdgData([doubleFocalPath].map(wrap), focalPayloadElem);
const diffModel = transformDdgData(wrap([doubleFocalPath]), focalPayloadElem);

expect(diffModel.hash).not.toBe(simpleModel.hash);
});

it('adds traceIDs to paths from attributes', () => {
const { focalPayloadElem, doubleFocalPath, simplePath, wrap } = testResources;
const payload = wrap([simplePath, doubleFocalPath]);
payload.dependencies.forEach((dependency, i) => {
// eslint-disable-next-line no-param-reassign
dependency.attributes = [
{
key: 'exemplar_trace_id',
value: `trace ${i} a`,
},
{
key: 'exemplar_trace_id',
value: `trace ${i} b`,
},
];
});
const model = transformDdgData(payload, focalPayloadElem);
model.paths.forEach((path, i) => {
expect(path.traceIDs).toEqual([`trace ${i} a`, `trace ${i} b`]);
});
});
});
22 changes: 17 additions & 5 deletions packages/jaeger-ui/src/model/ddg/transformDdgData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,26 @@ import {

const stringifyEntry = ({ service, operation }: TDdgPayloadEntry) => `${service}\v${operation}`;

// TODO: Everett Tech Debt: Fix KeyValuePair types
function group(arg: { key: string; value: any }[]): Record<string, any[]> {
const result: Record<string, any[]> = {};
arg.forEach(({ key, value }) => {
if (!result[key]) result[key] = [];
result[key].push(value);
});
return result;
}

export default function transformDdgData(
payload: TDdgPayload,
{ dependencies }: TDdgPayload,
{ service: focalService, operation: focalOperation }: { service: string; operation?: string }
): TDdgModel {
const serviceMap: TDdgServiceMap = new Map();
const distanceToPathElems: TDdgDistanceToPathElems = new Map();
const pathCompareValues: Map<TDdgPayloadEntry[], string> = new Map();
const hashArg: string[] = [];

const paths = payload
const paths = dependencies
.sort(({ path: a }, { path: b }) => {
let aCompareValue = pathCompareValues.get(a);
if (!aCompareValue) {
Expand All @@ -51,13 +61,15 @@ export default function transformDdgData(
if (aCompareValue < bCompareValue) return -1;
return 0;
})
// eslint-disable-next-line camelcase
.map(({ path: payloadPath, trace_id }) => {
.map(({ path: payloadPath, attributes }) => {
// Default value necessary as sort is not called if there is only one path
hashArg.push(pathCompareValues.get(payloadPath) || payloadPath.map(stringifyEntry).join());

// eslint-disable-next-line camelcase
const { exemplar_trace_id: traceIDs } = group(attributes);

// Path with stand-in values is necessary for assigning PathElem.memberOf
const path: TDdgPath = { focalIdx: -1, members: [], traceID: trace_id };
const path: TDdgPath = { focalIdx: -1, members: [], traceIDs };

path.members = payloadPath.map(({ operation: operationName, service: serviceName }, i) => {
// Ensure pathElem.service exists, else create it
Expand Down
14 changes: 10 additions & 4 deletions packages/jaeger-ui/src/model/ddg/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,15 @@ export type TDdgPayloadEntry = {
};

export type TDdgPayload = {
path: TDdgPayloadEntry[];
trace_id: string; // eslint-disable-line camelcase
}[];
dependencies: {
path: TDdgPayloadEntry[];
// TODO: Everett Tech Debt: Fix KeyValuePair types
attributes: {
key: 'exemplar_trace_id'; // eslint-disable-line camelcase
value: string;
}[];
}[];
};

export type TDdgService = {
name: string;
Expand All @@ -71,7 +77,7 @@ export type TDdgServiceMap = Map<string, TDdgService>;
export type TDdgPath = {
focalIdx: number;
members: PathElem[];
traceID: string;
traceIDs: string[];
};

export type TDdgDistanceToPathElems = Map<number, PathElem[]>;
Expand Down
4 changes: 2 additions & 2 deletions packages/jaeger-ui/src/model/ddg/visibility-codec.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ describe('visibility-codec', () => {
});

describe('encodeDistance', () => {
const ddgModel = transformDdgData([longSimplePath, simplePath].map(wrap), focalPayloadElem);
const shortModel = transformDdgData([shortPath].map(wrap), focalPayloadElem);
const ddgModel = transformDdgData(wrap([longSimplePath, simplePath]), focalPayloadElem);
const shortModel = transformDdgData(wrap([shortPath]), focalPayloadElem);

/**
* Creates a visibility encoding containing all indices between two specified hops, inclusive, except
Expand Down
1 change: 1 addition & 0 deletions packages/jaeger-ui/src/types/trace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* All timestamps are in microseconds
*/

// TODO: Everett Tech Debt: Fix KeyValuePair types
export type KeyValuePair = {
key: string;
value: any;
Expand Down

0 comments on commit 98530d6

Please sign in to comment.