123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- import {
- makeEventTransaction,
- makeSpan,
- makeTrace,
- makeTransaction,
- } from 'sentry/views/performance/newTraceDetails/traceModels/traceTreeTestUtils';
- import {isParentAutogroupedNode, isSiblingAutogroupedNode} from './../traceGuards';
- import {TraceTree} from './traceTree';
- const start = new Date('2024-02-29T00:00:00Z').getTime() / 1e3;
- const traceMetadata = {replay: null, meta: null};
- const singleTransactionTrace = makeTrace({
- transactions: [
- makeTransaction({
- start_timestamp: start,
- timestamp: start + 2,
- children: [],
- }),
- ],
- orphan_errors: [],
- });
- const siblingAutogroupSpans = [
- makeSpan({
- op: 'db',
- description: 'redis',
- start_timestamp: start,
- timestamp: start + 1,
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- start_timestamp: start,
- timestamp: start + 1,
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- start_timestamp: start,
- timestamp: start + 1,
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- start_timestamp: start,
- timestamp: start + 1,
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- start_timestamp: start,
- timestamp: start + 1,
- }),
- ];
- const parentAutogroupSpans = [
- makeSpan({op: 'db', description: 'redis', span_id: '0000'}),
- makeSpan({op: 'db', description: 'redis', span_id: '0001', parent_span_id: '0000'}),
- makeSpan({op: 'db', description: 'redis', span_id: '0002', parent_span_id: '0001'}),
- ];
- const parentAutogroupSpansWithChilden = [
- makeSpan({op: 'db', description: 'redis', span_id: '0000'}),
- makeSpan({op: 'db', description: 'redis', span_id: '0001', parent_span_id: '0000'}),
- makeSpan({op: 'db', description: 'redis', span_id: '0002', parent_span_id: '0001'}),
- makeSpan({op: 'http', description: 'request', span_id: '0003', parent_span_id: '0002'}),
- ];
- describe('autogrouping', () => {
- describe('parent autogrouping', () => {
- it('groups parent chain with same op', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- parentAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('assigns children to tail node', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- [
- makeSpan({op: 'db', description: 'redis', span_id: '0000'}),
- makeSpan({
- op: 'db',
- description: 'redis',
- span_id: '0001',
- parent_span_id: '0000',
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- span_id: '0002',
- parent_span_id: '0001',
- }),
- makeSpan({
- op: 'http.request',
- description: 'browser',
- span_id: '0003',
- parent_span_id: '0002',
- }),
- ],
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('autogrouped chain points to tail', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- [
- ...parentAutogroupSpans,
- makeSpan({
- op: 'http',
- description: 'request',
- parent_span_id: parentAutogroupSpans[parentAutogroupSpans.length - 1].span_id,
- }),
- ],
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('expanding parent autogroup renders head to tail chain', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- parentAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('collapsing parent autogroup removes its children', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- parentAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, false);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('can expand and collapse', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- [
- makeSpan({op: 'db', description: 'redis', span_id: '0000'}),
- makeSpan({
- op: 'db',
- description: 'redis',
- span_id: '0001',
- parent_span_id: '0000',
- }),
- makeSpan({
- op: 'db',
- description: 'redis',
- span_id: '0002',
- parent_span_id: '0001',
- }),
- makeSpan({
- op: 'http.request',
- description: 'browser',
- span_id: '0003',
- parent_span_id: '0002',
- }),
- ],
- makeEventTransaction()
- );
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- const initial = tree.build().serialize();
- // Expand autogroup part
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- // Collapse autogroup part
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, false);
- }
- });
- // Tree should be back to initial state
- expect(tree.build().serialize()).toEqual(initial);
- });
- it('autogroups siblings when they are children of a parent autogroup chain', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- [
- ...parentAutogroupSpans,
- ...[1, 2, 3, 4, 5].map(_i =>
- makeSpan({
- op: 'db',
- description: 'sql',
- start_timestamp: start,
- timestamp: start + 1,
- parent_span_id:
- parentAutogroupSpans[parentAutogroupSpans.length - 1].span_id,
- })
- ),
- ],
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('removes collapsed parent autogroup', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- parentAutogroupSpansWithChilden,
- makeEventTransaction()
- );
- const snapshot = tree.build().serialize();
- // Add sibling autogroup
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- expect(TraceTree.Find(tree.root, c => isParentAutogroupedNode(c))).not.toBeNull();
- // Remove it and assert that the tree is back to the original state
- TraceTree.RemoveDirectChildrenAutogroupNodes(tree.root);
- expect(TraceTree.Find(tree.root, c => isParentAutogroupedNode(c))).toBeNull();
- expect(tree.build().serialize()).toEqual(snapshot);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('removes expanded parent autogroup', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- parentAutogroupSpansWithChilden,
- makeEventTransaction()
- );
- const snapshot = tree.build().serialize();
- // Add sibling autogroup
- TraceTree.AutogroupDirectChildrenSpanNodes(tree.root);
- TraceTree.ForEachChild(tree.root, c => {
- if (isParentAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- expect(TraceTree.Find(tree.root, c => isParentAutogroupedNode(c))).not.toBeNull();
- // Remove it and assert that the tree is back to the original state
- TraceTree.RemoveDirectChildrenAutogroupNodes(tree.root);
- expect(TraceTree.Find(tree.root, c => isParentAutogroupedNode(c))).toBeNull();
- TraceTree.invalidate(tree.root, true);
- expect(tree.build().serialize()).toEqual(snapshot);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- });
- describe('sibling autogrouping', () => {
- it('groups spans with the same op and description', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- siblingAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('does not autogroup if count is less 5', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- siblingAutogroupSpans.slice(0, 4),
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('autogroups multiple consecutive groups', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- [
- ...siblingAutogroupSpans,
- ...siblingAutogroupSpans.map(s => ({...s, op: 'mysql'})),
- ],
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('expanding sibling autogroup renders its children', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- siblingAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- TraceTree.ForEachChild(tree.root, c => {
- if (isSiblingAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('collapsing sibling autogroup removes its children', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- siblingAutogroupSpans,
- makeEventTransaction()
- );
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- TraceTree.ForEachChild(tree.root, c => {
- if (isSiblingAutogroupedNode(c)) {
- tree.expand(c, true);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- TraceTree.ForEachChild(tree.root, c => {
- if (isSiblingAutogroupedNode(c)) {
- tree.expand(c, false);
- }
- });
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it('removes sibling autogroup', () => {
- const tree = TraceTree.FromTrace(singleTransactionTrace, traceMetadata);
- TraceTree.FromSpans(
- tree.root.children[0].children[0],
- siblingAutogroupSpans,
- makeEventTransaction()
- );
- const snapshot = tree.build().serialize();
- // Add sibling autogroup
- TraceTree.AutogroupSiblingSpanNodes(tree.root);
- expect(TraceTree.Find(tree.root, c => isSiblingAutogroupedNode(c))).not.toBeNull();
- // Remove it and assert that the tree is back to the original state
- TraceTree.RemoveSiblingAutogroupNodes(tree.root);
- expect(tree.build().serialize()).toEqual(snapshot);
- expect(tree.build().serialize()).toMatchSnapshot();
- });
- it.todo(
- 'collects errors, performance issues and profiles from sibling autogroup chain'
- );
- });
- });
|