diff --git a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.test.js b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.test.js index 9c2b55911e..add7b31592 100644 --- a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.test.js +++ b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.test.js @@ -67,14 +67,13 @@ describe('drawNode', () => { }); describe('renderNode()', () => { - const dataKey = 'data-key'; - const dataValue = 'data-value'; + const lenA = 3; + const lenB = 7; const key = 'vertex key'; const vertex = { data: { - data: { - [dataKey]: dataValue, - }, + a: new Array(lenA), + b: new Array(lenB), operation, service, }, @@ -83,7 +82,8 @@ describe('drawNode', () => { it('extracts values from vertex.data', () => { const node = renderNode(vertex); - expect(node.props[dataKey]).toBe(dataValue); + expect(node.props.a).toBe(lenA); + expect(node.props.b).toBe(lenB); expect(node.props.operation).toBe(operation); expect(node.props.service).toBe(service); }); diff --git a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.tsx b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.tsx index eff23ddffc..1d1dd700dd 100644 --- a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.tsx +++ b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/renderNode.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Uber Technologies, Inc. +// Copyright (c) 2018-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,8 +19,8 @@ import { TLayoutVertex } from '@jaegertracing/plexus/lib/types'; import EmphasizedNode from '../../common/EmphasizedNode'; import CopyIcon from '../../common/CopyIcon'; -import { DiffCounts } from '../../../model/trace-dag/types'; -import TDagVertex from '../../../model/trace-dag/types/TDagVertex'; +import { TDiffCounts } from '../../../model/trace-dag/types'; +import TDagPlexusVertex from '../../../model/trace-dag/types/TDagPlexusVertex'; import './renderNode.css'; @@ -86,9 +86,11 @@ export class DiffNode extends React.PureComponent { } } -export default function renderNode(vertex: TDagVertex) { - const { data, operation, service } = vertex.data; - return ; +export default function renderNode(vertex: TDagPlexusVertex) { + const { a, b, operation, service } = vertex.data; + const lenA = a ? a.length : 0; + const lenB = b ? b.length : 0; + return ; } export function getNodeEmphasisRenderer(keys: Set) { diff --git a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/traceDiffGraphUtils.tsx b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/traceDiffGraphUtils.tsx index ecc0eeb99e..47486fbd96 100644 --- a/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/traceDiffGraphUtils.tsx +++ b/packages/jaeger-ui/src/components/TraceDiff/TraceDiffGraph/traceDiffGraphUtils.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Uber Technologies, Inc. +// Copyright (c) 2019-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,12 +19,15 @@ import memoizeOne from 'memoize-one'; import convPlexus from '../../../model/trace-dag/convPlexus'; import TraceDag from '../../../model/trace-dag/TraceDag'; -import { DiffCounts } from '../../../model/trace-dag/types'; -import TDagVertex from '../../../model/trace-dag/types/TDagVertex'; +import { TDenseSpanMembers, TDiffCounts } from '../../../model/trace-dag/types'; +import TDagPlexusVertex from '../../../model/trace-dag/types/TDagPlexusVertex'; import { Trace } from '../../../types/trace'; import filterSpans from '../../../utils/filter-spans'; -function getUiFindVertexKeysFn(uiFind: string, vertices: TDagVertex[]): Set { +function getUiFindVertexKeysFn( + uiFind: string, + vertices: TDagPlexusVertex[] +): Set { if (!uiFind) return new Set(); const newVertexKeys: Set = new Set(); vertices.forEach(({ key, data: { members } }) => { @@ -41,7 +44,7 @@ function getEdgesAndVerticesFn(aData: Trace, bData: Trace) { const aTraceDag = TraceDag.newFromTrace(aData); const bTraceDag = TraceDag.newFromTrace(bData); const diffDag = TraceDag.diff(aTraceDag, bTraceDag); - return convPlexus(diffDag.nodesMap); + return convPlexus(diffDag.nodesMap); } export const getEdgesAndVertices = memoizeOne(getEdgesAndVerticesFn); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceGraph/OpNode.tsx b/packages/jaeger-ui/src/components/TracePage/TraceGraph/OpNode.tsx index c18d0361e3..0c0c99254e 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceGraph/OpNode.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceGraph/OpNode.tsx @@ -18,7 +18,8 @@ import { TLayoutVertex } from '@jaegertracing/plexus/lib/types'; import { TSumSpan } from './types'; import CopyIcon from '../../common/CopyIcon'; -import TDagVertex from '../../../model/trace-dag/types/TDagVertex'; +import { TDenseSpanMembers } from '../../../model/trace-dag/types'; +import TDagPlexusVertex from '../../../model/trace-dag/types/TDagPlexusVertex'; import colorGenerator from '../../../utils/color-generator'; import './OpNode.css'; @@ -126,14 +127,13 @@ export default class OpNode extends React.PureComponent { } export function getNodeRenderer(mode: string) { - return function drawNode(vertex: TDagVertex) { - const { data, operation, service } = vertex.data; - return ; + return function drawNode(vertex: TDagPlexusVertex) { + return ; }; } export function getNodeFindEmphasisRenderer(uiFindVertexKeys: Set | null | undefined) { - return function renderFindEmphasis(lv: TLayoutVertex>) { + return function renderFindEmphasis(lv: TLayoutVertex>) { if (!uiFindVertexKeys || !uiFindVertexKeys.has(lv.vertex.key)) { return null; } @@ -141,7 +141,7 @@ export function getNodeFindEmphasisRenderer(uiFindVertexKeys: Set | null }; } -export function renderNodeVectorBorder(lv: TLayoutVertex>) { +export function renderNodeVectorBorder(lv: TLayoutVertex>) { return ( { return (
- > + > minimap zoom className="TraceGraph--dag" diff --git a/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.test.js b/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.test.js index e00c89a956..5663ff51d4 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.test.js +++ b/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.test.js @@ -20,7 +20,7 @@ const testTrace = require('./testTrace.json'); const transformedTrace = transformTraceData(testTrace); function assertData(nodes, service, operation, count, errors, time, percent, selfTime) { - const d = nodes.find(({ data: n }) => n.service === service && n.operation === operation).data.data; + const d = nodes.find(({ data: n }) => n.service === service && n.operation === operation).data; expect(d).toBeDefined(); expect(d.count).toBe(count); expect(d.errors).toBe(errors); diff --git a/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.tsx b/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.tsx index a32bea1cc8..2921fd3c83 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceGraph/calculateTraceDagEV.tsx @@ -17,7 +17,8 @@ import DRange from 'drange'; import { TEdge } from '@jaegertracing/plexus/lib/types'; import convPlexus from '../../../model/trace-dag/convPlexus'; import TraceDag from '../../../model/trace-dag/TraceDag'; -import DagNode from '../../../model/trace-dag/DagNode'; +import TDagNode from '../../../model/trace-dag/types/TDagNode'; +import { TDenseSpanMembers } from '../../../model/trace-dag/types'; import { Trace, Span, KeyValuePair } from '../../../types/trace'; import { TSumSpan, TEv } from './types'; @@ -33,12 +34,15 @@ export function isError(tags: Array) { return false; } -function extendFollowsFrom(edges: TEdge[], nodes: DagNode[]) { +function mapFollowsFrom( + edges: TEdge[], + nodes: TDagNode[] +): TEdge<{ followsFrom: boolean }>[] { return edges.map(e => { let hasChildOf = true; if (typeof e.to === 'number') { - const n = nodes[e.to]; - hasChildOf = n.members.some( + const node = nodes[e.to]; + hasChildOf = node.members.some( m => m.span.references && m.span.references.some(r => r.refType === 'CHILD_OF') ); } @@ -72,21 +76,14 @@ function getChildOfDrange(parentID: string, trace: Trace) { return childrenDrange; } -export function calculateTraceDag(trace: Trace): TraceDag { - const traceDag: TraceDag = new TraceDag(); - traceDag._initFromTrace(trace, { - count: 0, - errors: 0, - time: 0, - percent: 0, - selfTime: 0, - percentSelfTime: 0, - }); +export function calculateTraceDag(trace: Trace): TraceDag { + const baseDag = TraceDag.newFromTrace(trace); + const dag = new TraceDag(); - traceDag.nodesMap.forEach(n => { - const ntime = n.members.reduce((p, m) => p + m.span.duration, 0); - const numErrors = n.members.reduce((p, m) => (p + isError(m.span.tags) ? 1 : 0), 0); - const childDurationsDRange = n.members.reduce((p, m) => { + baseDag.nodesMap.forEach(node => { + const ntime = node.members.reduce((p, m) => p + m.span.duration, 0); + const numErrors = node.members.reduce((p, m) => (p + isError(m.span.tags) ? 1 : 0), 0); + const childDurationsDRange = node.members.reduce((p, m) => { // Using DRange to handle overlapping spans (fork-join) const cdr = new DRange(m.span.startTime, m.span.startTime + m.span.duration).intersect( getChildOfDrange(m.span.spanID, trace) @@ -94,24 +91,23 @@ export function calculateTraceDag(trace: Trace): TraceDag { return p + cdr.length; }, 0); const stime = ntime - childDurationsDRange; - const nd = { - count: n.members.length, + dag.addNode(node.id, node.parentID, { + ...node, + count: node.members.length, errors: numErrors, time: ntime, percent: (100 / trace.duration) * ntime, selfTime: stime, percentSelfTime: (100 / ntime) * stime, - }; - // eslint-disable-next-line no-param-reassign - n.data = nd; + }); }); - return traceDag; + return dag; } export default function calculateTraceDagEV(trace: Trace): TEv { const traceDag = calculateTraceDag(trace); const nodes = [...traceDag.nodesMap.values()]; const ev = convPlexus(traceDag.nodesMap); - ev.edges = extendFollowsFrom(ev.edges, nodes); - return ev; + const edges = mapFollowsFrom(ev.edges, nodes); + return { ...ev, edges }; } diff --git a/packages/jaeger-ui/src/components/TracePage/TraceGraph/types.tsx b/packages/jaeger-ui/src/components/TracePage/TraceGraph/types.tsx index 3b2f6984fe..958cdd1eed 100644 --- a/packages/jaeger-ui/src/components/TracePage/TraceGraph/types.tsx +++ b/packages/jaeger-ui/src/components/TracePage/TraceGraph/types.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Uber Technologies, Inc. +// Copyright (c) 2019-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,18 +14,19 @@ import { TEdge } from '@jaegertracing/plexus/lib/types'; -import TDagVertex from '../../../model/trace-dag/types/TDagVertex'; +import { TDenseSpanMembers } from '../../../model/trace-dag/types'; +import TDagPlexusVertex from '../../../model/trace-dag/types/TDagPlexusVertex'; export type TSumSpan = { count: number; errors: number; - time: number; percent: number; - selfTime: number; percentSelfTime: number; + selfTime: number; + time: number; }; export type TEv = { - edges: TEdge[]; - vertices: TDagVertex[]; + edges: TEdge<{ followsFrom: boolean }>[]; + vertices: TDagPlexusVertex[]; }; diff --git a/packages/jaeger-ui/src/model/trace-dag/DagNode.tsx b/packages/jaeger-ui/src/model/trace-dag/DagNode.tsx deleted file mode 100644 index 8f06524a29..0000000000 --- a/packages/jaeger-ui/src/model/trace-dag/DagNode.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2018 Uber Technologies, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import { NodeID, DenseSpan } from './types'; -import { TNil } from '../../types'; - -export default class DagNode { - static getID(service: string, operation: string, hasChildren: boolean, parentID?: string | TNil): NodeID { - const name = `${service}\t${operation}${hasChildren ? '' : '\t__LEAF__'}`; - return parentID ? `${parentID}\v${name}` : name; - } - - service: string; - operation: string; - parentID: NodeID | TNil; - id: NodeID; - count: number; - members: DenseSpan[]; - children: Set; - data: T; - - constructor(service: string, operation: string, hasChildren: boolean, parentID: NodeID | TNil, data: T) { - this.service = service; - this.operation = operation; - this.parentID = parentID; - this.id = DagNode.getID(service, operation, hasChildren, parentID); - this.count = 0; - this.members = []; - this.children = new Set(); - this.data = data; - } - - addMember(member: DenseSpan) { - this.members.push(member); - } -} diff --git a/packages/jaeger-ui/src/model/trace-dag/DenseTrace.tsx b/packages/jaeger-ui/src/model/trace-dag/DenseTrace.tsx index 8f255e9365..4645d97db2 100644 --- a/packages/jaeger-ui/src/model/trace-dag/DenseTrace.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/DenseTrace.tsx @@ -13,11 +13,11 @@ // limitations under the License. import denseTransforms from './denseTransforms'; -import { DenseSpan } from './types'; +import { TDenseSpan } from './types'; import { Span, Trace } from '../../types/trace'; function convSpans(spans: Span[]) { - const map: Map = new Map(); + const map: Map = new Map(); const roots: Set = new Set(); const ids: string[] = []; spans.forEach(span => { @@ -63,7 +63,7 @@ function convSpans(spans: Span[]) { return { ids, map, roots }; } -function makeDense(spanIDs: string[], map: Map) { +function makeDense(spanIDs: string[], map: Map) { spanIDs.forEach(id => { const denseSpan = map.get(id); // make flow happy @@ -76,7 +76,7 @@ function makeDense(spanIDs: string[], map: Map) { export default class DenseTrace { trace: Trace; rootIDs: Set; - denseSpansMap: Map; + denseSpansMap: Map; constructor(trace: Trace) { this.trace = trace; diff --git a/packages/jaeger-ui/src/model/trace-dag/TraceDag.tsx b/packages/jaeger-ui/src/model/trace-dag/TraceDag.tsx index 089d297d59..a9db9542cd 100644 --- a/packages/jaeger-ui/src/model/trace-dag/TraceDag.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/TraceDag.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Uber Technologies, Inc. +// Copyright (c) 2018-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,100 +12,111 @@ // See the License for the specific language governing permissions and // limitations under the License. -import DagNode from './DagNode'; import DenseTrace from './DenseTrace'; -import { DiffCounts, NodeID } from './types'; -import { TNil } from '../../types'; +import { ancestralPathParentOrLeaf, TIdFactory } from './id-factories'; +import { TDenseSpan, TDiffCounts, NodeID, TDenseSpanMembers } from './types'; +import TDagNode from './types/TDagNode'; import { Trace } from '../../types/trace'; -export default class TraceDag { - static newFromTrace(trace: Trace) { - const dt: TraceDag = new TraceDag(); - dt._initFromTrace(trace, undefined); - return dt; +export default class TraceDag { + static newFromTrace(trace: Trace, idFactory: TIdFactory = ancestralPathParentOrLeaf) { + const dag: TraceDag = new TraceDag(); + const { denseSpansMap, rootIDs } = new DenseTrace(trace); + + function addDenseSpan(denseSpan: TDenseSpan | undefined, parentNodeID: NodeID | null) { + if (!denseSpan) { + // eslint-disable-next-line no-console + console.warn(`Missing dense span`); + return; + } + const { children, operation, service, skipToChild } = denseSpan; + let id: NodeID | null; + + if (!skipToChild) { + id = idFactory(denseSpan, parentNodeID); + const node = + dag.getNode(id) || + dag.addNode(id, parentNodeID, { + operation, + service, + members: [], + }); + node.members.push(denseSpan); + } else { + id = parentNodeID; + } + children.forEach(childId => addDenseSpan(denseSpansMap.get(childId), id)); + } + + rootIDs.forEach(rootId => addDenseSpan(denseSpansMap.get(rootId), null)); + return dag; } - static diff(a: TraceDag, b: TraceDag) { - const dt: TraceDag = new TraceDag(); - let key: 'a' | 'b' = 'a'; + static diff(a: TraceDag, b: TraceDag) { + const dag: TraceDag = new TraceDag(); - function pushDagNode(src: DagNode) { - const node = dt._getDagNode(src.service, src.operation, src.children.size > 0, src.parentID, { - a: 0, - b: 0, + function makeDiffNode(id: NodeID) { + const nodeA = a.nodesMap.get(id); + const nodeB = b.nodesMap.get(id); + const parentNodeID = (nodeA && nodeA.parentID) || (nodeB && nodeB.parentID) || null; + const members = [...(nodeA ? nodeA.members : []), ...(nodeB ? nodeB.members : [])]; + dag.addNode(id, parentNodeID, { + members, + a: nodeA ? nodeA.members : null, + b: nodeB ? nodeB.members : null, + operation: (nodeA && nodeA.operation) || (nodeB && nodeB.operation) || '__UNSET__', + service: (nodeA && nodeA.service) || (nodeB && nodeB.service) || '__UNSET__', }); - const { data } = node; - data[key] = src.count; - node.members.push(...src.members); - node.count = data.b - data.a; - if (!node.parentID) { - dt.rootIDs.add(node.id); - } } - key = 'a'; - [...a.nodesMap.values()].forEach(pushDagNode); - key = 'b'; - [...b.nodesMap.values()].forEach(pushDagNode); - return dt; + + const ids = new Set([...a.nodesMap.keys(), ...b.nodesMap.keys()]); + ids.forEach(makeDiffNode); + return dag; } - denseTrace: DenseTrace | null; - nodesMap: Map>; + nodesMap: Map>; rootIDs: Set; constructor() { - this.denseTrace = null; this.nodesMap = new Map(); this.rootIDs = new Set(); } - _initFromTrace(trace: Trace, data: T) { - this.denseTrace = new DenseTrace(trace); - [...this.denseTrace.rootIDs].forEach(id => this._addDenseSpan(id, null, data)); + hasNode(id: NodeID) { + return this.nodesMap.has(id); } - _getDagNode( - service: string, - operation: string, - hasChildren: boolean, - parentID: NodeID | TNil, - data: T - ): DagNode { - const nodeID = DagNode.getID(service, operation, hasChildren, parentID); - const existing = this.nodesMap.get(nodeID); - if (existing) { - return existing; - } - const node = new DagNode(service, operation, hasChildren, parentID, data); - this.nodesMap.set(nodeID, node); - if (!parentID) { - this.rootIDs.add(nodeID); - } else { - const parentDag = this.nodesMap.get(parentID); - if (parentDag) { - parentDag.children.add(nodeID); - } + getNode(id: NodeID) { + return this.nodesMap.get(id); + } + + mustGetNode(id: NodeID) { + const node = this.getNode(id); + if (!node) { + throw new Error(`Node not found: ${JSON.stringify(id)}`); } return node; } - _addDenseSpan(spanID: string, parentNodeID: NodeID | TNil, data: T) { - const denseSpan = this.denseTrace && this.denseTrace.denseSpansMap.get(spanID); - if (!denseSpan) { - // eslint-disable-next-line no-console - console.warn(`Missing dense span: ${spanID}`); - return; + addNode(id: NodeID, parentID: NodeID | null, data: TData) { + if (this.hasNode(id)) { + throw new Error(`Node already added: ${JSON.stringify(id)}`); } - const { children, operation, service, skipToChild } = denseSpan; - let nodeID: string | TNil = null; - if (!skipToChild) { - const node = this._getDagNode(service, operation, children.size > 0, parentNodeID, data); - node.count++; - node.addMember(denseSpan); - nodeID = node.id; + const node: TDagNode = { + ...data, + id, + parentID, + children: new Set(), + }; + this.nodesMap.set(id, node); + if (!parentID) { + this.rootIDs.add(id); } else { - nodeID = parentNodeID; + const parentNode = this.nodesMap.get(parentID); + if (parentNode) { + parentNode.children.add(id); + } } - [...children].forEach(id => this._addDenseSpan(id, nodeID, data)); + return node; } } diff --git a/packages/jaeger-ui/src/model/trace-dag/convPlexus.tsx b/packages/jaeger-ui/src/model/trace-dag/convPlexus.tsx index 3bd141e96d..fcc28e3fd2 100644 --- a/packages/jaeger-ui/src/model/trace-dag/convPlexus.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/convPlexus.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Uber Technologies, Inc. +// Copyright (c) 2018-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,12 +14,12 @@ import { TEdge } from '@jaegertracing/plexus/lib/types'; -import DagNode from './DagNode'; import { NodeID } from './types'; -import TDagVertex from './types/TDagVertex'; +import TDagNode from './types/TDagNode'; +import TDagPlexusVertex from './types/TDagPlexusVertex'; -export default function convPlexus(nodesMap: Map>) { - const vertices: TDagVertex[] = []; +export default function convPlexus(nodesMap: Map>) { + const vertices: TDagPlexusVertex[] = []; const edges: TEdge[] = []; const nodes = [...nodesMap.values()]; for (let i = 0; i < nodes.length; i++) { diff --git a/packages/jaeger-ui/src/model/trace-dag/denseTransforms.tsx b/packages/jaeger-ui/src/model/trace-dag/denseTransforms.tsx index b71feca684..4d196d4a31 100644 --- a/packages/jaeger-ui/src/model/trace-dag/denseTransforms.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/denseTransforms.tsx @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { DenseSpan } from './types'; +import { TDenseSpan } from './types'; import * as tagKeys from '../../constants/tag-keys'; // - if span @@ -21,7 +21,7 @@ import * as tagKeys from '../../constants/tag-keys'; // - has parent.operation startsWith self-tag peer.service // - has parent.operation endsWith self.operation // - set self.service = self-tag peer.service -function fixLeafService(denseSpan: DenseSpan, map: Map) { +function fixLeafService(denseSpan: TDenseSpan, map: Map) { const { children, operation, parentID, tags } = denseSpan; const parent = parentID != null && map.get(parentID); const kind = tags[tagKeys.SPAN_KIND]; @@ -42,7 +42,7 @@ function fixLeafService(denseSpan: DenseSpan, map: Map) { // - parent has one child (self) // - (parent.operation OR parent-tag peer.service) startsWith self.service // - set parent.skipToChild = true -function skipClient(denseSpan: DenseSpan, map: Map) { +function skipClient(denseSpan: TDenseSpan, map: Map) { const { parentID, service, tags } = denseSpan; const parent = parentID != null && map.get(parentID); if (!parent) { @@ -61,7 +61,7 @@ function skipClient(denseSpan: DenseSpan, map: Map) { // - has operation === tag http.method // - (parent.operation OR parent-tag peer.service) startsWith self.service // - fix self.operation -function fixHttpOperation(denseSpan: DenseSpan, map: Map) { +function fixHttpOperation(denseSpan: TDenseSpan, map: Map) { const { parentID, operation, service, tags } = denseSpan; const parent = parentID != null && map.get(parentID); if (!parent) { @@ -86,7 +86,7 @@ function fixHttpOperation(denseSpan: DenseSpan, map: Map) { // - has only one child // - parent.process === self.process // - set self.skipToChild = true -function skipAnnotationSpans(denseSpan: DenseSpan, map: Map) { +function skipAnnotationSpans(denseSpan: TDenseSpan, map: Map) { const { children, parentID, span } = denseSpan; if (children.size !== 1 || span.tags.length !== 0) { return; @@ -107,7 +107,7 @@ function skipAnnotationSpans(denseSpan: DenseSpan, map: Map) // - the child is a server span // - parent.span.processID === self.span.processID // - set parent.skipToChild = true -function skipClientSpans(denseSpan: DenseSpan, map: Map) { +function skipClientSpans(denseSpan: TDenseSpan, map: Map) { const { children, parentID, span, tags } = denseSpan; if (children.size !== 1 || tags[tagKeys.SPAN_KIND] !== 'client') { return; @@ -123,7 +123,7 @@ function skipClientSpans(denseSpan: DenseSpan, map: Map) { child.tags[tagKeys.SPAN_KIND] === 'client' && parent.span.processID === span.processID; } -export default function denseTransforms(denseSpan: DenseSpan, map: Map) { +export default function denseTransforms(denseSpan: TDenseSpan, map: Map) { fixLeafService(denseSpan, map); skipClient(denseSpan, map); fixHttpOperation(denseSpan, map); diff --git a/packages/jaeger-ui/src/model/trace-dag/id-factories.tsx b/packages/jaeger-ui/src/model/trace-dag/id-factories.tsx new file mode 100644 index 0000000000..06d92480ea --- /dev/null +++ b/packages/jaeger-ui/src/model/trace-dag/id-factories.tsx @@ -0,0 +1,23 @@ +// Copyright (c) 2020 The Jaeger Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { TDenseSpan, NodeID } from './types'; + +export type TIdFactory = (denseSpan: TDenseSpan, parentID: NodeID | null) => NodeID; + +export function ancestralPathParentOrLeaf(denseSpan: TDenseSpan, parentID: NodeID | null): NodeID { + const { children, operation, service } = denseSpan; + const name = `${service}\t${operation}${children.size ? '' : '\t__LEAF__'}`; + return parentID ? `${parentID}\v${name}` : name; +} diff --git a/packages/jaeger-ui/src/model/trace-dag/types/TDagNode.tsx b/packages/jaeger-ui/src/model/trace-dag/types/TDagNode.tsx new file mode 100644 index 0000000000..20e03142e9 --- /dev/null +++ b/packages/jaeger-ui/src/model/trace-dag/types/TDagNode.tsx @@ -0,0 +1,24 @@ +// Copyright (c) 2020 The Jaeger Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NodeID } from './index'; + +type TDagNode = TData & { + parentID: NodeID | null; + id: NodeID; + children: Set; +}; + +// eslint-disable-next-line no-undef +export default TDagNode; diff --git a/packages/jaeger-ui/src/model/trace-dag/types/TDagVertex.tsx b/packages/jaeger-ui/src/model/trace-dag/types/TDagPlexusVertex.tsx similarity index 75% rename from packages/jaeger-ui/src/model/trace-dag/types/TDagVertex.tsx rename to packages/jaeger-ui/src/model/trace-dag/types/TDagPlexusVertex.tsx index eef67aa73a..40b910ccb5 100644 --- a/packages/jaeger-ui/src/model/trace-dag/types/TDagVertex.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/types/TDagPlexusVertex.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Uber Technologies, Inc. +// Copyright (c) 2019-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,9 +14,9 @@ import { TVertex } from '@jaegertracing/plexus/lib/types'; -import DagNode from '../DagNode'; +import TDagNode from './TDagNode'; -type TDagVertex = TVertex<{ data: DagNode }>; +type TDagPlexusVertex = TVertex<{ data: TDagNode }>; // eslint-disable-next-line no-undef -export default TDagVertex; +export default TDagPlexusVertex; diff --git a/packages/jaeger-ui/src/model/trace-dag/types/index.tsx b/packages/jaeger-ui/src/model/trace-dag/types/index.tsx index f24660d487..fec8a1ad3b 100644 --- a/packages/jaeger-ui/src/model/trace-dag/types/index.tsx +++ b/packages/jaeger-ui/src/model/trace-dag/types/index.tsx @@ -1,4 +1,4 @@ -// Copyright (c) 2018 Uber Technologies, Inc. +// Copyright (c) 2018-2020 The Jaeger Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,12 +17,7 @@ import { TNil } from '../../../types'; export type NodeID = string; -export type DiffCounts = { - a: number; - b: number; -}; - -export type DenseSpan = { +export type TDenseSpan = { span: Span; id: string; service: string; @@ -32,3 +27,14 @@ export type DenseSpan = { skipToChild: boolean; children: Set; }; + +export type TDenseSpanMembers = { + members: TDenseSpan[]; + operation: string; + service: string; +}; + +export type TDiffCounts = TDenseSpanMembers & { + a: TDenseSpan[] | null; + b: TDenseSpan[] | null; +};