From acb7b7726ec038d0ae152e94e3ac1f176c97a8d4 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Sat, 6 Mar 2021 23:45:50 -0700 Subject: [PATCH 1/2] [KQL] Remove number parsing (#93658) * [KQL] Remove number parsing * Update test snapshots --- .../es_query/kuery/ast/_generated_/kuery.js | 3 +- .../common/es_query/kuery/ast/ast.test.ts | 37 +++++++++---------- .../data/common/es_query/kuery/ast/kuery.peg | 3 +- .../search/aggs/buckets/filters.test.ts | 4 +- .../detection_engine/get_query_filter.test.ts | 12 +++--- .../components/timeline/helpers.test.tsx | 16 ++++---- .../server/lib/alerts/status_check.test.ts | 8 ++-- 7 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/plugins/data/common/es_query/kuery/ast/_generated_/kuery.js b/src/plugins/data/common/es_query/kuery/ast/_generated_/kuery.js index e8c9c3b4e9cc3..19de4ad4230fb 100644 --- a/src/plugins/data/common/es_query/kuery/ast/_generated_/kuery.js +++ b/src/plugins/data/common/es_query/kuery/ast/_generated_/kuery.js @@ -228,8 +228,7 @@ module.exports = (function() { if (sequence === 'true') return buildLiteralNode(true); if (sequence === 'false') return buildLiteralNode(false); if (chars.includes(wildcardSymbol)) return buildWildcardNode(sequence); - const isNumberPattern = /^(-?[1-9]+\d*([.]\d+)?)$|^(-?0[.]\d*[1-9]+)$|^0$|^0.0$|^[.]\d{1,}$/ - return buildLiteralNode(isNumberPattern.test(sequence) ? Number(sequence) : sequence); + return buildLiteralNode(sequence); }, peg$c52 = { type: "any", description: "any character" }, peg$c53 = "*", diff --git a/src/plugins/data/common/es_query/kuery/ast/ast.test.ts b/src/plugins/data/common/es_query/kuery/ast/ast.test.ts index f43049542f9de..34e91787c6320 100644 --- a/src/plugins/data/common/es_query/kuery/ast/ast.test.ts +++ b/src/plugins/data/common/es_query/kuery/ast/ast.test.ts @@ -168,10 +168,10 @@ describe('kuery AST API', () => { test('should support exclusive range operators', () => { const expected = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode('range', 'bytes', { - gt: 1000, + gt: '1000', }), nodeTypes.function.buildNode('range', 'bytes', { - lt: 8000, + lt: '8000', }), ]); const actual = fromKueryExpression('bytes > 1000 and bytes < 8000'); @@ -181,10 +181,10 @@ describe('kuery AST API', () => { test('should support inclusive range operators', () => { const expected = nodeTypes.function.buildNode('and', [ nodeTypes.function.buildNode('range', 'bytes', { - gte: 1000, + gte: '1000', }), nodeTypes.function.buildNode('range', 'bytes', { - lte: 8000, + lte: '8000', }), ]); const actual = fromKueryExpression('bytes >= 1000 and bytes <= 8000'); @@ -279,25 +279,24 @@ describe('kuery AST API', () => { const stringLiteral = nodeTypes.literal.buildNode('foo'); const booleanFalseLiteral = nodeTypes.literal.buildNode(false); const booleanTrueLiteral = nodeTypes.literal.buildNode(true); - const numberLiteral = nodeTypes.literal.buildNode(42); expect(fromLiteralExpression('foo')).toEqual(stringLiteral); expect(fromLiteralExpression('true')).toEqual(booleanTrueLiteral); expect(fromLiteralExpression('false')).toEqual(booleanFalseLiteral); - expect(fromLiteralExpression('42')).toEqual(numberLiteral); - - expect(fromLiteralExpression('.3').value).toEqual(0.3); - expect(fromLiteralExpression('.36').value).toEqual(0.36); - expect(fromLiteralExpression('.00001').value).toEqual(0.00001); - expect(fromLiteralExpression('3').value).toEqual(3); - expect(fromLiteralExpression('-4').value).toEqual(-4); - expect(fromLiteralExpression('0').value).toEqual(0); - expect(fromLiteralExpression('0.0').value).toEqual(0); - expect(fromLiteralExpression('2.0').value).toEqual(2.0); - expect(fromLiteralExpression('0.8').value).toEqual(0.8); - expect(fromLiteralExpression('790.9').value).toEqual(790.9); - expect(fromLiteralExpression('0.0001').value).toEqual(0.0001); - expect(fromLiteralExpression('96565646732345').value).toEqual(96565646732345); + + expect(fromLiteralExpression('.3').value).toEqual('.3'); + expect(fromLiteralExpression('.36').value).toEqual('.36'); + expect(fromLiteralExpression('.00001').value).toEqual('.00001'); + expect(fromLiteralExpression('3').value).toEqual('3'); + expect(fromLiteralExpression('-4').value).toEqual('-4'); + expect(fromLiteralExpression('0').value).toEqual('0'); + expect(fromLiteralExpression('0.0').value).toEqual('0.0'); + expect(fromLiteralExpression('2.0').value).toEqual('2.0'); + expect(fromLiteralExpression('0.8').value).toEqual('0.8'); + expect(fromLiteralExpression('790.9').value).toEqual('790.9'); + expect(fromLiteralExpression('0.0001').value).toEqual('0.0001'); + expect(fromLiteralExpression('96565646732345').value).toEqual('96565646732345'); + expect(fromLiteralExpression('070').value).toEqual('070'); expect(fromLiteralExpression('..4').value).toEqual('..4'); expect(fromLiteralExpression('.3text').value).toEqual('.3text'); diff --git a/src/plugins/data/common/es_query/kuery/ast/kuery.peg b/src/plugins/data/common/es_query/kuery/ast/kuery.peg index 6407107e5ee65..fa5e8d240a9c4 100644 --- a/src/plugins/data/common/es_query/kuery/ast/kuery.peg +++ b/src/plugins/data/common/es_query/kuery/ast/kuery.peg @@ -251,8 +251,7 @@ UnquotedLiteral if (sequence === 'true') return buildLiteralNode(true); if (sequence === 'false') return buildLiteralNode(false); if (chars.includes(wildcardSymbol)) return buildWildcardNode(sequence); - const isNumberPattern = /^(-?[1-9]+\d*([.]\d+)?)$|^(-?0[.]\d*[1-9]+)$|^0$|^0.0$|^[.]\d{1,}$/ - return buildLiteralNode(isNumberPattern.test(sequence) ? Number(sequence) : sequence); + return buildLiteralNode(sequence); } UnquotedCharacter diff --git a/src/plugins/data/common/search/aggs/buckets/filters.test.ts b/src/plugins/data/common/search/aggs/buckets/filters.test.ts index 14b8d95f195ed..4e5ab8cf71c13 100644 --- a/src/plugins/data/common/search/aggs/buckets/filters.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/filters.test.ts @@ -153,7 +153,7 @@ describe('Filters Agg', () => { "should": Array [ Object { "match": Object { - "field": 200, + "field": "200", }, }, ], @@ -171,7 +171,7 @@ describe('Filters Agg', () => { Object { "range": Object { "field": Object { - "gt": 500, + "gt": "500", }, }, }, diff --git a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts index 2a7bc6238e5d9..3c04e2b0da9c3 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.test.ts @@ -1028,7 +1028,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610182, + "suricata.eve.alert.signature_id": "2610182", }, }, ], @@ -1040,7 +1040,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610183, + "suricata.eve.alert.signature_id": "2610183", }, }, ], @@ -1052,7 +1052,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610184, + "suricata.eve.alert.signature_id": "2610184", }, }, ], @@ -1064,7 +1064,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610185, + "suricata.eve.alert.signature_id": "2610185", }, }, ], @@ -1076,7 +1076,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610186, + "suricata.eve.alert.signature_id": "2610186", }, }, ], @@ -1088,7 +1088,7 @@ describe('get_filter', () => { "should": Array [ Object { "match": Object { - "suricata.eve.alert.signature_id": 2610187, + "suricata.eve.alert.signature_id": "2610187", }, }, ], diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.test.tsx index 8e03a56c1aa9b..0438acdfe44d4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.test.tsx @@ -332,8 +332,8 @@ describe('Combined Queries', () => { kqlQuery: { query: '', language: 'kuery' }, kqlMode: 'search', })!; - expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232}}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}' + expect(filterQuery).toMatchInlineSnapshot( + `"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"range\\":{\\"@timestamp\\":{\\"gte\\":\\"1521848183232\\",\\"lte\\":\\"1521848183232\\"}}}],\\"minimum_should_match\\":1}}],\\"should\\":[],\\"must_not\\":[]}}"` ); }); @@ -350,8 +350,8 @@ describe('Combined Queries', () => { kqlQuery: { query: '', language: 'kuery' }, kqlMode: 'search', })!; - expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232}}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}' + expect(filterQuery).toMatchInlineSnapshot( + `"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"range\\":{\\"@timestamp\\":{\\"gte\\":\\"1521848183232\\",\\"lte\\":\\"1521848183232\\"}}}],\\"minimum_should_match\\":1}}],\\"should\\":[],\\"must_not\\":[]}}"` ); }); @@ -368,8 +368,8 @@ describe('Combined Queries', () => { kqlQuery: { query: '', language: 'kuery' }, kqlMode: 'search', })!; - expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}' + expect(filterQuery).toMatchInlineSnapshot( + `"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"event.end\\":\\"1521848183232\\"}}],\\"minimum_should_match\\":1}}],\\"should\\":[],\\"must_not\\":[]}}"` ); }); @@ -386,8 +386,8 @@ describe('Combined Queries', () => { kqlQuery: { query: '', language: 'kuery' }, kqlMode: 'search', })!; - expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}' + expect(filterQuery).toMatchInlineSnapshot( + `"{\\"bool\\":{\\"must\\":[],\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"event.end\\":\\"1521848183232\\"}}],\\"minimum_should_match\\":1}}],\\"should\\":[],\\"must_not\\":[]}}"` ); }); diff --git a/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts b/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts index 4fac71a53a1dc..12db6eeff8fcf 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/status_check.test.ts @@ -354,7 +354,7 @@ describe('status check alert', () => { "should": Array [ Object { "match": Object { - "url.port": 12349, + "url.port": "12349", }, }, ], @@ -366,7 +366,7 @@ describe('status check alert', () => { "should": Array [ Object { "match": Object { - "url.port": 5601, + "url.port": "5601", }, }, ], @@ -378,7 +378,7 @@ describe('status check alert', () => { "should": Array [ Object { "match": Object { - "url.port": 443, + "url.port": "443", }, }, ], @@ -735,7 +735,7 @@ describe('status check alert', () => { expect(mockAvailability.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { - "filters": "{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":12349}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":5601}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":443}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"observer.geo.name\\":\\"harrisburg\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"monitor.type\\":\\"http\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"unsecured\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"containers\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"tags\\":\\"org:google\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}", + "filters": "{\\"bool\\":{\\"filter\\":[{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":\\"12349\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":\\"5601\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"url.port\\":\\"443\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"observer.geo.name\\":\\"harrisburg\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"monitor.type\\":\\"http\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"unsecured\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match\\":{\\"tags\\":\\"containers\\"}}],\\"minimum_should_match\\":1}},{\\"bool\\":{\\"should\\":[{\\"match_phrase\\":{\\"tags\\":\\"org:google\\"}}],\\"minimum_should_match\\":1}}],\\"minimum_should_match\\":1}}]}}", "range": 35, "rangeUnit": "d", "threshold": "99.34", From e2abb03ad03d27dcbe0a36964ea78a4361c038da Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Sun, 7 Mar 2021 07:52:38 +0100 Subject: [PATCH 2/2] [APM] Color by span type when there's only one service (#90424) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../Marks/get_error_marks.test.ts | 16 +- .../Marks/get_error_marks.ts | 14 +- .../WaterfallContainer/ServiceLegends.tsx | 46 -- .../Waterfall/WaterfallItem.tsx | 16 +- .../Waterfall/accordion_waterfall.tsx | 13 +- .../WaterfallContainer/Waterfall/index.tsx | 8 +- .../waterfall_helpers.test.ts.snap | 413 +++++++++++++++++- .../waterfall_helpers.test.ts | 38 +- .../waterfall_helpers/waterfall_helpers.ts | 148 ++++--- .../WaterfallContainer/WaterfallLegends.tsx | 57 +++ .../WaterfallContainer/index.tsx | 57 ++- 11 files changed, 666 insertions(+), 160 deletions(-) delete mode 100644 x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/ServiceLegends.tsx create mode 100644 x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallLegends.tsx diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.test.ts b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.test.ts index 3f286a0d2b8c3..62507efc64401 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.test.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.test.ts @@ -11,7 +11,7 @@ import { getErrorMarks } from './get_error_marks'; describe('getErrorMarks', () => { describe('returns empty array', () => { it('when items are missing', () => { - expect(getErrorMarks([], {})).toEqual([]); + expect(getErrorMarks([])).toEqual([]); }); }); @@ -22,17 +22,17 @@ describe('getErrorMarks', () => { offset: 10, skew: 5, doc: { error: { id: 1 }, service: { name: 'opbeans-java' } }, + color: 'red', } as unknown, { docType: 'error', offset: 50, skew: 0, doc: { error: { id: 2 }, service: { name: 'opbeans-node' } }, + color: 'blue', } as unknown, ] as IWaterfallError[]; - expect( - getErrorMarks(items, { 'opbeans-java': 'red', 'opbeans-node': 'blue' }) - ).toEqual([ + expect(getErrorMarks(items)).toEqual([ { type: 'errorMark', offset: 15, @@ -59,22 +59,24 @@ describe('getErrorMarks', () => { offset: 10, skew: 5, doc: { error: { id: 1 }, service: { name: 'opbeans-java' } }, + color: '', } as unknown, { docType: 'error', offset: 50, skew: 0, doc: { error: { id: 2 }, service: { name: 'opbeans-node' } }, + color: '', } as unknown, ] as IWaterfallError[]; - expect(getErrorMarks(items, {})).toEqual([ + expect(getErrorMarks(items)).toEqual([ { type: 'errorMark', offset: 15, verticalLine: false, id: 1, error: { error: { id: 1 }, service: { name: 'opbeans-java' } }, - serviceColor: undefined, + serviceColor: '', }, { type: 'errorMark', @@ -82,7 +84,7 @@ describe('getErrorMarks', () => { verticalLine: false, id: 2, error: { error: { id: 2 }, service: { name: 'opbeans-node' } }, - serviceColor: undefined, + serviceColor: '', }, ]); }); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.ts b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.ts index e87b47edc226b..1012c3dfa6fd1 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Marks/get_error_marks.ts @@ -7,22 +7,16 @@ import { isEmpty } from 'lodash'; import { ErrorRaw } from '../../../../../../../typings/es_schemas/raw/error_raw'; -import { - IWaterfallError, - IServiceColors, -} from '../Waterfall/waterfall_helpers/waterfall_helpers'; +import { IWaterfallError } from '../Waterfall/waterfall_helpers/waterfall_helpers'; import { Mark } from '.'; export interface ErrorMark extends Mark { type: 'errorMark'; error: ErrorRaw; - serviceColor?: string; + serviceColor: string; } -export const getErrorMarks = ( - errorItems: IWaterfallError[], - serviceColors: IServiceColors -): ErrorMark[] => { +export const getErrorMarks = (errorItems: IWaterfallError[]): ErrorMark[] => { if (isEmpty(errorItems)) { return []; } @@ -33,6 +27,6 @@ export const getErrorMarks = ( verticalLine: false, id: error.doc.error.id, error: error.doc, - serviceColor: serviceColors[error.doc.service.name], + serviceColor: error.color, })); }; diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/ServiceLegends.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/ServiceLegends.tsx deleted file mode 100644 index ab3773b2cac2e..0000000000000 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/ServiceLegends.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; -import { px, unit } from '../../../../../style/variables'; -import { Legend } from '../../../../shared/charts/Legend'; -import { IServiceColors } from './Waterfall/waterfall_helpers/waterfall_helpers'; - -const Legends = euiStyled.div` - display: flex; - - > * { - margin-right: ${px(unit)}; - &:last-child { - margin-right: 0; - } - } -`; - -interface Props { - serviceColors: IServiceColors; -} - -export function ServiceLegends({ serviceColors }: Props) { - return ( - - - - {i18n.translate('xpack.apm.transactionDetails.servicesTitle', { - defaultMessage: 'Services', - })} - - - {Object.entries(serviceColors).map(([label, color]) => ( - - ))} - - ); -} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx index 7000f389e3d0e..f3e1547c4b8b8 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/WaterfallItem.tsx @@ -14,7 +14,7 @@ import { asDuration } from '../../../../../../../common/utils/formatters'; import { isRumAgentName } from '../../../../../../../common/agent_name'; import { px, unit, units } from '../../../../../../style/variables'; import { ErrorCount } from '../../ErrorCount'; -import { IWaterfallItem } from './waterfall_helpers/waterfall_helpers'; +import { IWaterfallSpanOrTransaction } from './waterfall_helpers/waterfall_helpers'; import { ErrorOverviewLink } from '../../../../../shared/Links/apm/ErrorOverviewLink'; import { TRACE_ID } from '../../../../../../../common/elasticsearch_fieldnames'; import { SyncBadge } from './SyncBadge'; @@ -75,14 +75,14 @@ const ItemText = euiStyled.span` interface IWaterfallItemProps { timelineMargins: Margins; totalDuration?: number; - item: IWaterfallItem; + item: IWaterfallSpanOrTransaction; color: string; isSelected: boolean; errorCount: number; onClick: () => unknown; } -function PrefixIcon({ item }: { item: IWaterfallItem }) { +function PrefixIcon({ item }: { item: IWaterfallSpanOrTransaction }) { switch (item.docType) { case 'span': { // icon for database spans @@ -110,7 +110,7 @@ function PrefixIcon({ item }: { item: IWaterfallItem }) { interface SpanActionToolTipProps { children: ReactNode; - item?: IWaterfallItem; + item?: IWaterfallSpanOrTransaction; } function SpanActionToolTip({ item, children }: SpanActionToolTipProps) { @@ -124,7 +124,7 @@ function SpanActionToolTip({ item, children }: SpanActionToolTipProps) { return <>{children}; } -function Duration({ item }: { item: IWaterfallItem }) { +function Duration({ item }: { item: IWaterfallSpanOrTransaction }) { return ( {asDuration(item.duration)} @@ -132,7 +132,7 @@ function Duration({ item }: { item: IWaterfallItem }) { ); } -function HttpStatusCode({ item }: { item: IWaterfallItem }) { +function HttpStatusCode({ item }: { item: IWaterfallSpanOrTransaction }) { // http status code for transactions of type 'request' const httpStatusCode = item.docType === 'transaction' && item.doc.transaction.type === 'request' @@ -146,7 +146,7 @@ function HttpStatusCode({ item }: { item: IWaterfallItem }) { return {httpStatusCode}; } -function NameLabel({ item }: { item: IWaterfallItem }) { +function NameLabel({ item }: { item: IWaterfallSpanOrTransaction }) { switch (item.docType) { case 'span': return {item.doc.span.name}; @@ -156,8 +156,6 @@ function NameLabel({ item }: { item: IWaterfallItem }) {
{item.doc.transaction.name}
); - default: - return null; } } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx index 8d50074d814eb..baced34ad3e56 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx @@ -14,22 +14,21 @@ import { Margins } from '../../../../../shared/charts/Timeline'; import { WaterfallItem } from './WaterfallItem'; import { IWaterfall, - IWaterfallItem, + IWaterfallSpanOrTransaction, } from './waterfall_helpers/waterfall_helpers'; interface AccordionWaterfallProps { isOpen: boolean; - item: IWaterfallItem; + item: IWaterfallSpanOrTransaction; level: number; - serviceColors: IWaterfall['serviceColors']; duration: IWaterfall['duration']; waterfallItemId?: string; location: Location; errorsPerTransaction: IWaterfall['errorsPerTransaction']; - childrenByParentId: Record; + childrenByParentId: Record; onToggleEntryTransaction?: () => void; timelineMargins: Margins; - onClickWaterfallItem: (item: IWaterfallItem) => void; + onClickWaterfallItem: (item: IWaterfallSpanOrTransaction) => void; } const StyledAccordion = euiStyled(EuiAccordion).withConfig({ @@ -98,7 +97,6 @@ export function AccordionWaterfall(props: AccordionWaterfallProps) { const { item, level, - serviceColors, duration, childrenByParentId, waterfallItemId, @@ -134,7 +132,7 @@ export function AccordionWaterfall(props: AccordionWaterfallProps) { + childrenByParentId: Record ) { const { entryWaterfallTransaction } = waterfall; if (!entryWaterfallTransaction) { @@ -95,7 +96,6 @@ export function Waterfall({ isOpen={isAccordionOpen} item={entryWaterfallTransaction} level={0} - serviceColors={serviceColors} waterfallItemId={waterfallItemId} location={location} errorsPerTransaction={waterfall.errorsPerTransaction} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap index 204c5e9ae6da2..8905162daada2 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap @@ -5,6 +5,7 @@ Object { "childrenByParentId": Object { "mySpanIdA": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -35,8 +36,13 @@ Object { "docType": "span", "duration": 481, "id": "mySpanIdB", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 41627, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -67,8 +73,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -103,8 +114,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -135,8 +151,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -161,6 +182,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -179,6 +204,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -209,8 +235,13 @@ Object { "docType": "span", "duration": 532, "id": "mySpanIdC", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 43899, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -241,8 +272,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -277,8 +313,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -309,8 +350,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -335,6 +381,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -355,6 +405,7 @@ Object { ], "mySpanIdD": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -389,8 +440,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -421,8 +477,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -447,6 +508,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -461,6 +526,7 @@ Object { ], "myTransactionId1": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -491,8 +557,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -517,6 +588,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -528,6 +603,7 @@ Object { ], "myTransactionId2": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -558,8 +634,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -594,8 +675,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -626,8 +712,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -652,6 +743,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -669,6 +764,7 @@ Object { ], "root": Array [ Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -693,6 +789,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -702,6 +802,7 @@ Object { }, "duration": 49660, "entryWaterfallTransaction": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -726,6 +827,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -733,6 +838,7 @@ Object { }, "errorItems": Array [ Object { + "color": "", "doc": Object { "agent": Object { "name": "ruby", @@ -765,10 +871,10 @@ Object { }, }, "docType": "error", - "duration": 0, "id": "error1", "offset": 25994, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -793,6 +899,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -809,6 +919,7 @@ Object { }, "items": Array [ Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -833,12 +944,17 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -869,8 +985,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -895,6 +1016,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -904,6 +1029,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -938,8 +1064,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -970,8 +1101,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -996,6 +1132,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -1008,6 +1148,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1038,8 +1179,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1074,8 +1220,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -1106,8 +1257,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -1132,6 +1288,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -1147,6 +1307,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -1177,8 +1338,13 @@ Object { "docType": "span", "duration": 481, "id": "mySpanIdB", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 41627, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1209,8 +1375,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1245,8 +1416,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -1277,8 +1453,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -1303,6 +1484,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -1321,6 +1506,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -1351,8 +1537,13 @@ Object { "docType": "span", "duration": 532, "id": "mySpanIdC", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 43899, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1383,8 +1574,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 40498, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1419,8 +1615,13 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 39298, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId1", @@ -1451,8 +1652,13 @@ Object { "docType": "span", "duration": 47557, "id": "mySpanIdD", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": undefined, + }, "offset": 1754, "parent": Object { + "color": "", "doc": Object { "processor": Object { "event": "transaction", @@ -1477,6 +1683,10 @@ Object { "docType": "transaction", "duration": 49660, "id": "myTransactionId1", + "legendValues": Object { + "serviceName": "opbeans-node", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": undefined, @@ -1495,6 +1705,28 @@ Object { "skew": 0, }, ], + "legends": Array [ + Object { + "color": "#54B399", + "type": "serviceName", + "value": "opbeans-node", + }, + Object { + "color": "#6092C0", + "type": "serviceName", + "value": "opbeans-ruby", + }, + Object { + "color": "#54B399", + "type": "spanType", + "value": "", + }, + Object { + "color": "#6092C0", + "type": "spanType", + "value": undefined, + }, + ], "rootTransaction": Object { "processor": Object { "event": "transaction", @@ -1516,10 +1748,6 @@ Object { "name": "GET /api", }, }, - "serviceColors": Object { - "opbeans-node": "#6092c0", - "opbeans-ruby": "#54b399", - }, } `; @@ -1528,6 +1756,7 @@ Object { "childrenByParentId": Object { "mySpanIdA": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -1558,8 +1787,13 @@ Object { "docType": "span", "duration": 481, "id": "mySpanIdB", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 2329, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1590,8 +1824,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1626,6 +1865,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -1638,6 +1881,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -1668,8 +1912,13 @@ Object { "docType": "span", "duration": 532, "id": "mySpanIdC", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 4601, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1700,8 +1949,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1736,6 +1990,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -1750,6 +2008,7 @@ Object { ], "mySpanIdD": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1784,6 +2043,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -1792,6 +2055,7 @@ Object { ], "myTransactionId2": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1822,8 +2086,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1858,6 +2127,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -1870,6 +2143,7 @@ Object { }, "duration": 8634, "entryWaterfallTransaction": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1904,6 +2178,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -1917,6 +2195,7 @@ Object { }, "items": Array [ Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -1951,12 +2230,17 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -1987,8 +2271,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -2023,6 +2312,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -2032,6 +2325,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -2062,8 +2356,13 @@ Object { "docType": "span", "duration": 481, "id": "mySpanIdB", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 2329, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -2094,8 +2393,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -2130,6 +2434,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -2142,6 +2450,7 @@ Object { "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdA", @@ -2172,8 +2481,13 @@ Object { "docType": "span", "duration": 532, "id": "mySpanIdC", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 4601, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "myTransactionId2", @@ -2204,8 +2518,13 @@ Object { "docType": "span", "duration": 6161, "id": "mySpanIdA", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": undefined, + }, "offset": 1200, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "mySpanIdD", @@ -2240,6 +2559,10 @@ Object { "docType": "transaction", "duration": 8634, "id": "myTransactionId2", + "legendValues": Object { + "serviceName": "opbeans-ruby", + "spanType": "", + }, "offset": 0, "parent": undefined, "parentId": "mySpanIdD", @@ -2252,6 +2575,23 @@ Object { "skew": 0, }, ], + "legends": Array [ + Object { + "color": "#54B399", + "type": "serviceName", + "value": "opbeans-ruby", + }, + Object { + "color": "#54B399", + "type": "spanType", + "value": "", + }, + Object { + "color": "#6092C0", + "type": "spanType", + "value": undefined, + }, + ], "rootTransaction": Object { "processor": Object { "event": "transaction", @@ -2273,9 +2613,6 @@ Object { "name": "GET /api", }, }, - "serviceColors": Object { - "opbeans-ruby": "#6092c0", - }, } `; @@ -2335,6 +2672,7 @@ Array [ exports[`waterfall_helpers getWaterfallItems should order items correctly 1`] = ` Array [ Object { + "color": "", "doc": Object { "service": Object { "name": "opbeans-java", @@ -2350,11 +2688,16 @@ Array [ "docType": "transaction", "duration": 9480, "id": "a", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 0, "parent": undefined, "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "a", @@ -2376,8 +2719,13 @@ Array [ "docType": "span", "duration": 4694, "id": "b2", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 1000, "parent": Object { + "color": "", "doc": Object { "service": Object { "name": "opbeans-java", @@ -2393,6 +2741,10 @@ Array [ "docType": "transaction", "duration": 9480, "id": "a", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 0, "parent": undefined, "skew": 0, @@ -2401,6 +2753,7 @@ Array [ "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "a", @@ -2422,8 +2775,13 @@ Array [ "docType": "span", "duration": 4694, "id": "b", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 2000, "parent": Object { + "color": "", "doc": Object { "service": Object { "name": "opbeans-java", @@ -2439,6 +2797,10 @@ Array [ "docType": "transaction", "duration": 9480, "id": "a", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 0, "parent": undefined, "skew": 0, @@ -2447,6 +2809,7 @@ Array [ "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "b", @@ -2465,8 +2828,13 @@ Array [ "docType": "transaction", "duration": 3581, "id": "c", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 3000, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "a", @@ -2488,8 +2856,13 @@ Array [ "docType": "span", "duration": 4694, "id": "b", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 2000, "parent": Object { + "color": "", "doc": Object { "service": Object { "name": "opbeans-java", @@ -2505,6 +2878,10 @@ Array [ "docType": "transaction", "duration": 9480, "id": "a", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 0, "parent": undefined, "skew": 0, @@ -2516,6 +2893,7 @@ Array [ "skew": 0, }, Object { + "color": "", "doc": Object { "parent": Object { "id": "c", @@ -2537,8 +2915,13 @@ Array [ "docType": "span", "duration": 210, "id": "d", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 5000, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "b", @@ -2557,8 +2940,13 @@ Array [ "docType": "transaction", "duration": 3581, "id": "c", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 3000, "parent": Object { + "color": "", "doc": Object { "parent": Object { "id": "a", @@ -2580,8 +2968,13 @@ Array [ "docType": "span", "duration": 4694, "id": "b", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 2000, "parent": Object { + "color": "", "doc": Object { "service": Object { "name": "opbeans-java", @@ -2597,6 +2990,10 @@ Array [ "docType": "transaction", "duration": 9480, "id": "a", + "legendValues": Object { + "serviceName": "opbeans-java", + "spanType": "", + }, "offset": 0, "parent": undefined, "skew": 0, diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts index 1bc9ba877017d..34933a3a6f8ec 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.test.ts @@ -15,6 +15,7 @@ import { IWaterfallItem, IWaterfallTransaction, IWaterfallError, + IWaterfallSpanOrTransaction, } from './waterfall_helpers'; import { APMError } from '../../../../../../../../typings/es_schemas/ui/apm_error'; @@ -377,7 +378,12 @@ describe('waterfall_helpers', () => { describe('getWaterfallItems', () => { it('should order items correctly', () => { - const items: IWaterfallItem[] = [ + const legendValues = { + serviceName: 'opbeans-java', + spanType: '', + }; + + const items: IWaterfallSpanOrTransaction[] = [ { docType: 'span', doc: { @@ -397,6 +403,8 @@ describe('waterfall_helpers', () => { duration: 210, offset: 0, skew: 0, + legendValues, + color: '', }, { docType: 'span', @@ -417,6 +425,8 @@ describe('waterfall_helpers', () => { duration: 4694, offset: 0, skew: 0, + legendValues, + color: '', }, { docType: 'span', @@ -437,6 +447,8 @@ describe('waterfall_helpers', () => { duration: 4694, offset: 0, skew: 0, + legendValues, + color: '', }, { docType: 'transaction', @@ -451,6 +463,8 @@ describe('waterfall_helpers', () => { duration: 3581, offset: 0, skew: 0, + legendValues, + color: '', }, { docType: 'transaction', @@ -466,6 +480,8 @@ describe('waterfall_helpers', () => { duration: 9480, offset: 0, skew: 0, + legendValues, + color: '', }, ]; @@ -489,7 +505,7 @@ describe('waterfall_helpers', () => { transaction: { id: 'a' }, timestamp: { us: 10 }, } as unknown) as Transaction, - } as IWaterfallItem, + } as IWaterfallSpanOrTransaction, { docType: 'span', id: 'b', @@ -501,7 +517,7 @@ describe('waterfall_helpers', () => { parent: { id: 'a' }, timestamp: { us: 20 }, } as unknown) as Span, - } as IWaterfallItem, + } as IWaterfallSpanOrTransaction, ]; const childrenByParentId = groupBy(items, (hit) => hit.parentId ? hit.parentId : 'root' @@ -522,7 +538,7 @@ describe('waterfall_helpers', () => { timestamp: { us: 0 }, }, duration: 50, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; const parent = { docType: 'transaction', @@ -531,7 +547,7 @@ describe('waterfall_helpers', () => { }, duration: 100, skew: 5, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; expect(getClockSkew(child, parent)).toBe(130); }); @@ -543,7 +559,7 @@ describe('waterfall_helpers', () => { timestamp: { us: 250 }, }, duration: 50, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; const parent = { docType: 'transaction', @@ -552,7 +568,7 @@ describe('waterfall_helpers', () => { }, duration: 100, skew: 5, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; expect(getClockSkew(child, parent)).toBe(0); }); @@ -564,7 +580,7 @@ describe('waterfall_helpers', () => { timestamp: { us: 150 }, }, duration: 50, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; const parent = { docType: 'transaction', @@ -573,7 +589,7 @@ describe('waterfall_helpers', () => { }, duration: 100, skew: 5, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; expect(getClockSkew(child, parent)).toBe(0); }); @@ -590,7 +606,7 @@ describe('waterfall_helpers', () => { }, duration: 100, skew: 5, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; expect(getClockSkew(child, parent)).toBe(5); }); @@ -607,7 +623,7 @@ describe('waterfall_helpers', () => { }, duration: 100, skew: 5, - } as IWaterfallItem; + } as IWaterfallSpanOrTransaction; expect(getClockSkew(child, parent)).toBe(5); }); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts index 77a4a3372045f..9ace59fae6320 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers.ts @@ -5,17 +5,8 @@ * 2.0. */ -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { - first, - flatten, - groupBy, - isEmpty, - sortBy, - sum, - uniq, - zipObject, -} from 'lodash'; +import { euiPaletteColorBlind } from '@elastic/eui'; +import { first, flatten, groupBy, isEmpty, sortBy, sum, uniq } from 'lodash'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { TraceAPIResponse } from '../../../../../../../../server/lib/traces/get_trace'; import { APMError } from '../../../../../../../../typings/es_schemas/ui/apm_error'; @@ -23,11 +14,16 @@ import { Span } from '../../../../../../../../typings/es_schemas/ui/span'; import { Transaction } from '../../../../../../../../typings/es_schemas/ui/transaction'; interface IWaterfallGroup { - [key: string]: IWaterfallItem[]; + [key: string]: IWaterfallSpanOrTransaction[]; } const ROOT_ID = 'root'; +export enum WaterfallLegendType { + ServiceName = 'serviceName', + SpanType = 'spanType', +} + export interface IWaterfall { entryWaterfallTransaction?: IWaterfallTransaction; rootTransaction?: Transaction; @@ -37,46 +33,69 @@ export interface IWaterfall { */ duration: number; items: IWaterfallItem[]; - childrenByParentId: Record; + childrenByParentId: Record; errorsPerTransaction: TraceAPIResponse['errorsPerTransaction']; errorsCount: number; - serviceColors: IServiceColors; + legends: IWaterfallLegend[]; errorItems: IWaterfallError[]; } -interface IWaterfallItemBase { - docType: U; - doc: T; - - id: string; - - parent?: IWaterfallItem; - parentId?: string; - +interface IWaterfallSpanItemBase + extends IWaterfallItemBase { /** * Latency in us */ duration: number; + legendValues: Record; +} +interface IWaterfallItemBase { + doc: TDocument; + docType: TDoctype; + id: string; + parent?: IWaterfallSpanOrTransaction; + parentId?: string; + color: string; /** * offset from first item in us */ offset: number; - /** * skew from timestamp in us */ skew: number; } -export type IWaterfallTransaction = IWaterfallItemBase< +export type IWaterfallError = IWaterfallItemBase; + +export type IWaterfallTransaction = IWaterfallSpanItemBase< Transaction, 'transaction' >; -export type IWaterfallSpan = IWaterfallItemBase; -export type IWaterfallError = IWaterfallItemBase; -export type IWaterfallItem = IWaterfallTransaction | IWaterfallSpan; +export type IWaterfallSpan = IWaterfallSpanItemBase; + +export type IWaterfallSpanOrTransaction = + | IWaterfallTransaction + | IWaterfallSpan; + +export type IWaterfallItem = IWaterfallSpanOrTransaction | IWaterfallError; + +export interface IWaterfallLegend { + type: WaterfallLegendType; + value: string | undefined; + color: string; +} + +function getLegendValues(transactionOrSpan: Transaction | Span) { + return { + [WaterfallLegendType.ServiceName]: transactionOrSpan.service.name, + [WaterfallLegendType.SpanType]: + 'span' in transactionOrSpan + ? transactionOrSpan.span.subtype || transactionOrSpan.span.type + : '', + }; +} function getTransactionItem(transaction: Transaction): IWaterfallTransaction { return { @@ -87,6 +106,8 @@ function getTransactionItem(transaction: Transaction): IWaterfallTransaction { duration: transaction.transaction.duration.us, offset: 0, skew: 0, + legendValues: getLegendValues(transaction), + color: '', }; } @@ -99,6 +120,8 @@ function getSpanItem(span: Span): IWaterfallSpan { duration: span.span.duration.us, offset: 0, skew: 0, + legendValues: getLegendValues(span), + color: '', }; } @@ -110,7 +133,8 @@ function getErrorItem( const entryTimestamp = entryWaterfallTransaction?.doc.timestamp.us ?? 0; const parent = items.find( (waterfallItem) => waterfallItem.id === error.parent?.id - ); + ) as IWaterfallSpanOrTransaction | undefined; + const errorItem: IWaterfallError = { docType: 'error', doc: error, @@ -119,7 +143,7 @@ function getErrorItem( parentId: parent?.id, offset: error.timestamp.us - entryTimestamp, skew: 0, - duration: 0, + color: '', }; return { @@ -130,7 +154,7 @@ function getErrorItem( export function getClockSkew( item: IWaterfallItem | IWaterfallError, - parentItem?: IWaterfallItem + parentItem?: IWaterfallSpanOrTransaction ) { if (!parentItem) { return 0; @@ -168,9 +192,9 @@ export function getOrderedWaterfallItems( const visitedWaterfallItemSet = new Set(); function getSortedChildren( - item: IWaterfallItem, - parentItem?: IWaterfallItem - ): IWaterfallItem[] { + item: IWaterfallSpanOrTransaction, + parentItem?: IWaterfallSpanOrTransaction + ): IWaterfallSpanOrTransaction[] { if (visitedWaterfallItemSet.has(item)) { return []; } @@ -203,27 +227,39 @@ function getRootTransaction(childrenByParentId: IWaterfallGroup) { } } -export type IServiceColors = Record; +function getLegends(waterfallItems: IWaterfallItem[]) { + const onlyBaseSpanItems = waterfallItems.filter( + (item) => item.docType === 'span' || item.docType === 'transaction' + ) as IWaterfallSpanOrTransaction[]; + + const legends = [ + WaterfallLegendType.ServiceName, + WaterfallLegendType.SpanType, + ].flatMap((legendType) => { + const allLegendValues = uniq( + onlyBaseSpanItems.map((item) => item.legendValues[legendType]) + ); -function getServiceColors(waterfallItems: IWaterfallItem[]) { - const services = uniq(waterfallItems.map((item) => item.doc.service.name)); + const palette = euiPaletteColorBlind({ + rotations: Math.ceil(allLegendValues.length / 10), + }); - const assignedColors = [ - theme.euiColorVis1, - theme.euiColorVis0, - theme.euiColorVis3, - theme.euiColorVis2, - theme.euiColorVis6, - theme.euiColorVis7, - theme.euiColorVis5, - ]; + return allLegendValues.map((value, index) => ({ + type: legendType, + value, + color: palette[index], + })); + }); - return zipObject(services, assignedColors) as IServiceColors; + return legends; } const getWaterfallDuration = (waterfallItems: IWaterfallItem[]) => Math.max( - ...waterfallItems.map((item) => item.offset + item.skew + item.duration), + ...waterfallItems.map( + (item) => + item.offset + item.skew + ('duration' in item ? item.duration : 0) + ), 0 ); @@ -238,7 +274,7 @@ const getWaterfallItems = (items: TraceAPIResponse['trace']['items']) => } }); -function reparentSpans(waterfallItems: IWaterfallItem[]) { +function reparentSpans(waterfallItems: IWaterfallSpanOrTransaction[]) { // find children that needs to be re-parented and map them to their correct parent id const childIdToParentIdMapping = Object.fromEntries( flatten( @@ -266,7 +302,9 @@ function reparentSpans(waterfallItems: IWaterfallItem[]) { }); } -const getChildrenGroupedByParentId = (waterfallItems: IWaterfallItem[]) => +const getChildrenGroupedByParentId = ( + waterfallItems: IWaterfallSpanOrTransaction[] +) => groupBy(waterfallItems, (item) => (item.parentId ? item.parentId : ROOT_ID)); const getEntryWaterfallTransaction = ( @@ -329,13 +367,15 @@ export function getWaterfall( items: [], errorsPerTransaction, errorsCount: sum(Object.values(errorsPerTransaction)), - serviceColors: {}, + legends: [], errorItems: [], childrenByParentId: {}, }; } - const waterfallItems: IWaterfallItem[] = getWaterfallItems(trace.items); + const waterfallItems: IWaterfallSpanOrTransaction[] = getWaterfallItems( + trace.items + ); const childrenByParentId = getChildrenGroupedByParentId( reparentSpans(waterfallItems) @@ -358,7 +398,7 @@ export function getWaterfall( const rootTransaction = getRootTransaction(childrenByParentId); const duration = getWaterfallDuration(items); - const serviceColors = getServiceColors(items); + const legends = getLegends(items); return { entryWaterfallTransaction, @@ -367,7 +407,7 @@ export function getWaterfall( items, errorsPerTransaction, errorsCount: errorItems.length, - serviceColors, + legends, errorItems, childrenByParentId: getChildrenGroupedByParentId(items), }; diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallLegends.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallLegends.tsx new file mode 100644 index 0000000000000..d6f6de2d9179b --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallLegends.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup } from '@elastic/eui'; +import { EuiFlexItem } from '@elastic/eui'; +import { EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { Legend } from '../../../../shared/charts/Legend'; +import { + IWaterfallLegend, + WaterfallLegendType, +} from './Waterfall/waterfall_helpers/waterfall_helpers'; + +interface Props { + legends: IWaterfallLegend[]; + type: WaterfallLegendType; +} + +const LEGEND_LABELS = { + [WaterfallLegendType.ServiceName]: i18n.translate( + 'xpack.apm.transactionDetails.servicesTitle', + { + defaultMessage: 'Services', + } + ), + [WaterfallLegendType.SpanType]: i18n.translate( + 'xpack.apm.transactionDetails.spanTypeLegendTitle', + { + defaultMessage: 'Type', + } + ), +}; +export function WaterfallLegends({ legends, type }: Props) { + return ( + + + + {LEGEND_LABELS[type]} + + + + + {legends.map((legend) => ( + + + + ))} + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx index d813afa6c1e27..11de1ac85c434 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx @@ -7,10 +7,15 @@ import { Location } from 'history'; import React from 'react'; +import { keyBy } from 'lodash'; +import { useParams } from 'react-router-dom'; import { IUrlParams } from '../../../../../context/url_params_context/types'; -import { ServiceLegends } from './ServiceLegends'; -import { IWaterfall } from './Waterfall/waterfall_helpers/waterfall_helpers'; +import { + IWaterfall, + WaterfallLegendType, +} from './Waterfall/waterfall_helpers/waterfall_helpers'; import { Waterfall } from './Waterfall'; +import { WaterfallLegends } from './WaterfallLegends'; interface Props { urlParams: IUrlParams; @@ -25,13 +30,59 @@ export function WaterfallContainer({ waterfall, exceedsMax, }: Props) { + const { serviceName } = useParams<{ serviceName: string }>(); + if (!waterfall) { return null; } + const { legends, items } = waterfall; + + // Service colors are needed to color the dot in the error popover + const serviceLegends = legends.filter( + ({ type }) => type === WaterfallLegendType.ServiceName + ); + const serviceColors = serviceLegends.reduce((colorMap, legend) => { + return { + ...colorMap, + [legend.value!]: legend.color, + }; + }, {} as Record); + + // only color by span type if there are only events for one service + const colorBy = + serviceLegends.length > 1 + ? WaterfallLegendType.ServiceName + : WaterfallLegendType.SpanType; + + const displayedLegends = legends.filter((legend) => legend.type === colorBy); + + const legendsByValue = keyBy(displayedLegends, 'value'); + + // mutate items rather than rebuilding both items and childrenByParentId + items.forEach((item) => { + let color = ''; + if ('legendValues' in item) { + color = legendsByValue[item.legendValues[colorBy]].color; + } + + if (!color) { + // fall back to service color if there's no span.type, e.g. for transactions + color = serviceColors[item.doc.service.name]; + } + + item.color = color; + }); + + // default to serviceName if value is empty, e.g. for transactions (which don't + // have span.type or span.subtype) + const legendsWithFallbackLabel = displayedLegends.map((legend) => { + return { ...legend, value: !legend.value ? serviceName : legend.value }; + }); + return (
- +