From 149b2bae352c17654ffc86daa8234ffc428d5643 Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Fri, 29 Nov 2019 14:58:22 +0100 Subject: [PATCH 1/4] adding trace pagination --- .../__jest__/distribution.test.js | 54 -------- .../__test__/distribution.test.js | 62 +++++++++ .../TransactionDetails/Distribution/index.tsx | 52 ++++--- .../MaybeViewTraceLink.tsx | 87 ++++++++++++ .../WaterfallWithSummmary/index.tsx | 131 +++++++----------- .../app/TransactionDetails/index.tsx | 24 ++-- .../Histogram/__test__/Histogram.test.js | 16 ++- .../charts/Histogram/__test__/response.json | 32 +++-- .../hooks/useTransactionDistribution.ts | 15 +- .../distribution/get_buckets/fetcher.ts | 15 +- .../distribution/get_buckets/transform.ts | 18 ++- 11 files changed, 303 insertions(+), 203 deletions(-) delete mode 100644 x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__jest__/distribution.test.js create mode 100644 x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js create mode 100644 x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__jest__/distribution.test.js b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__jest__/distribution.test.js deleted file mode 100644 index 75338c669d0b3..0000000000000 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__jest__/distribution.test.js +++ /dev/null @@ -1,54 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getFormattedBuckets } from '../index'; - -describe('Distribution', () => { - it('getFormattedBuckets', () => { - const buckets = [ - { key: 0, count: 0 }, - { key: 20, count: 0 }, - { key: 40, count: 0 }, - { - key: 60, - count: 5, - sample: { - transactionId: 'someTransactionId' - } - }, - { - key: 80, - count: 100, - sample: { - transactionId: 'anotherTransactionId' - } - } - ]; - expect(getFormattedBuckets(buckets, 20)).toEqual([ - { x: 20, x0: 0, y: 0, style: { cursor: 'default' } }, - { x: 40, x0: 20, y: 0, style: { cursor: 'default' } }, - { x: 60, x0: 40, y: 0, style: { cursor: 'default' } }, - { - x: 80, - x0: 60, - y: 5, - sample: { - transactionId: 'someTransactionId' - }, - style: { cursor: 'pointer' } - }, - { - x: 100, - x0: 80, - y: 100, - sample: { - transactionId: 'anotherTransactionId' - }, - style: { cursor: 'pointer' } - } - ]); - }); -}); diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js new file mode 100644 index 0000000000000..eb42d19f3517e --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getFormattedBuckets } from '../index'; + +describe('Distribution', () => { + it('getFormattedBuckets', () => { + const buckets = [ + { key: 0, count: 0, samples: [] }, + { key: 20, count: 0, samples: [] }, + { key: 40, count: 0, samples: [] }, + { + key: 60, + count: 5, + samples: [ + { + transactionId: 'someTransactionId' + } + ] + }, + { + key: 80, + count: 100, + samples: [ + { + transactionId: 'anotherTransactionId' + } + ] + } + ]; + expect(getFormattedBuckets(buckets, 20)).toEqual([ + { x: 20, x0: 0, y: 0, style: { cursor: 'default' }, samples: [] }, + { x: 40, x0: 20, y: 0, style: { cursor: 'default' }, samples: [] }, + { x: 60, x0: 40, y: 0, style: { cursor: 'default' }, samples: [] }, + { + x: 80, + x0: 60, + y: 5, + style: { cursor: 'pointer' }, + samples: [ + { + transactionId: 'someTransactionId' + } + ] + }, + { + x: 100, + x0: 80, + y: 100, + style: { cursor: 'pointer' }, + samples: [ + { + transactionId: 'anotherTransactionId' + } + ] + } + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index c9e5175a10921..afded03a827c3 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -7,7 +7,13 @@ import { EuiIconTip, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import d3 from 'd3'; -import React, { FunctionComponent, useCallback } from 'react'; +import React, { + FunctionComponent, + useCallback, + Dispatch, + SetStateAction +} from 'react'; +import { isEmpty } from 'lodash'; import { TransactionDistributionAPIResponse } from '../../../../../server/lib/transactions/distribution'; import { IBucket } from '../../../../../server/lib/transactions/distribution/get_buckets/transform'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; @@ -20,7 +26,7 @@ import { history } from '../../../../utils/history'; import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt'; interface IChartPoint { - sample?: IBucket['sample']; + samples: IBucket['samples']; x0: number; x: number; y: number; @@ -35,13 +41,15 @@ export function getFormattedBuckets(buckets: IBucket[], bucketSize: number) { } return buckets.map( - ({ sample, count, key }): IChartPoint => { + ({ samples, count, key }): IChartPoint => { return { - sample, + samples, x0: key, x: key + bucketSize, y: count, - style: { cursor: count > 0 && sample ? 'pointer' : 'default' } + style: { + cursor: count > 0 && !isEmpty(samples) ? 'pointer' : 'default' + } }; } ); @@ -91,6 +99,7 @@ interface Props { distribution?: TransactionDistributionAPIResponse; urlParams: IUrlParams; isLoading: boolean; + onBucketSelected: Dispatch>; } export const TransactionDistribution: FunctionComponent = ( @@ -99,7 +108,8 @@ export const TransactionDistribution: FunctionComponent = ( const { distribution, urlParams: { transactionId, traceId, transactionType }, - isLoading + isLoading, + onBucketSelected } = props; const formatYShort = useCallback(getFormatYShort(transactionType), [ @@ -134,12 +144,15 @@ export const TransactionDistribution: FunctionComponent = ( const xMax = d3.max(buckets, d => d.x) || 0; const timeFormatter = getDurationFormatter(xMax); - const bucketIndex = buckets.findIndex( - bucket => - bucket.sample != null && - bucket.sample.transactionId === transactionId && - bucket.sample.traceId === traceId - ); + const bucketIndex = buckets.findIndex(bucket => { + const sampleFound = bucket.samples.findIndex( + sample => + sample.transactionId === transactionId && sample.traceId === traceId + ); + return sampleFound === -1 ? false : true; + }); + + onBucketSelected(bucketIndex); return (
@@ -175,13 +188,14 @@ export const TransactionDistribution: FunctionComponent = ( bucketSize={distribution.bucketSize} bucketIndex={bucketIndex} onClick={(bucket: IChartPoint) => { - if (bucket.sample && bucket.y > 0) { + if (!isEmpty(bucket.samples) && bucket.y > 0) { + const sample = bucket.samples[0]; history.push({ ...history.location, search: fromQuery({ ...toQuery(history.location.search), - transactionId: bucket.sample.transactionId, - traceId: bucket.sample.traceId + transactionId: sample.transactionId, + traceId: sample.traceId }) }); } @@ -190,16 +204,18 @@ export const TransactionDistribution: FunctionComponent = ( formatYShort={formatYShort} formatYLong={formatYLong} verticalLineHover={(bucket: IChartPoint) => - bucket.y > 0 && !bucket.sample + bucket.y > 0 && isEmpty(bucket.samples) + } + backgroundHover={(bucket: IChartPoint) => + bucket.y > 0 && !isEmpty(bucket.samples) } - backgroundHover={(bucket: IChartPoint) => bucket.y > 0 && bucket.sample} tooltipHeader={(bucket: IChartPoint) => { const xFormatted = timeFormatter(bucket.x); const x0Formatted = timeFormatter(bucket.x0); return `${x0Formatted.value} - ${xFormatted.value} ${xFormatted.unit}`; }} tooltipFooter={(bucket: IChartPoint) => - !bucket.sample && + isEmpty(bucket.samples) && i18n.translate( 'xpack.apm.transactionDetails.transactionsDurationDistributionChart.noSampleTooltip', { diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx new file mode 100644 index 0000000000000..39e52be34a415 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/Transaction'; +import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink'; +import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers'; + +export const MaybeViewTraceLink = ({ + transaction, + waterfall +}: { + transaction: ITransaction; + waterfall: IWaterfall; +}) => { + const viewFullTraceButtonLabel = i18n.translate( + 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', + { + defaultMessage: 'View full trace' + } + ); + + // the traceroot cannot be found, so we cannot link to it + if (!waterfall.traceRoot) { + return ( + + + + {viewFullTraceButtonLabel} + + + + ); + } + + const isRoot = + transaction.transaction.id === waterfall.traceRoot.transaction.id; + + // the user is already viewing the full trace, so don't link to it + if (isRoot) { + return ( + + + + {viewFullTraceButtonLabel} + + + + ); + + // the user is viewing a zoomed in version of the trace. Link to the full trace + } else { + const traceRoot = waterfall.traceRoot; + return ( + + + {viewFullTraceButtonLabel} + + + ); + } +}; diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx index fb37bf44c2f32..d0c0d16e84195 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx @@ -5,102 +5,43 @@ */ import { - EuiButton, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, - EuiToolTip, EuiEmptyPrompt, - EuiTitle + EuiTitle, + EuiPagination } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Location } from 'history'; -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { sum } from 'lodash'; -import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/Transaction'; +import styled from 'styled-components'; import { IUrlParams } from '../../../../context/UrlParamsContext/types'; -import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink'; import { TransactionActionMenu } from '../../../shared/TransactionActionMenu/TransactionActionMenu'; import { TransactionTabs } from './TransactionTabs'; import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers'; import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt'; import { TransactionSummary } from '../../../shared/Summary/TransactionSummary'; +import { IBucket } from '../../../../../server/lib/transactions/distribution/get_buckets/transform'; +import { history } from '../../../../utils/history'; +import { fromQuery, toQuery } from '../../../shared/Links/url_helpers'; +import { MaybeViewTraceLink } from './MaybeViewTraceLink'; -function MaybeViewTraceLink({ - transaction, - waterfall -}: { - transaction: ITransaction; - waterfall: IWaterfall; -}) { - const viewFullTraceButtonLabel = i18n.translate( - 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', - { - defaultMessage: 'View full trace' - } - ); +const PaginationContainer = styled.div` + margin-left: 4px; + display: flex; + align-items: center; - // the traceroot cannot be found, so we cannot link to it - if (!waterfall.traceRoot) { - return ( - - - - {viewFullTraceButtonLabel} - - - - ); + > span:first-of-type { + font-weight: 600; } - const isRoot = - transaction.transaction.id === waterfall.traceRoot.transaction.id; - - // the user is already viewing the full trace, so don't link to it - if (isRoot) { - return ( - - - - {viewFullTraceButtonLabel} - - - - ); - - // the user is viewing a zoomed in version of the trace. Link to the full trace - } else { - const traceRoot = waterfall.traceRoot; - return ( - - - {viewFullTraceButtonLabel} - - - ); + > span:last-of-type { + margin-right: 8px; } -} +`; interface Props { urlParams: IUrlParams; @@ -108,6 +49,7 @@ interface Props { waterfall: IWaterfall; exceedsMax: boolean; isLoading: boolean; + traceSamples: IBucket['samples']; } export const WaterfallWithSummmary: React.FC = ({ @@ -115,8 +57,28 @@ export const WaterfallWithSummmary: React.FC = ({ location, waterfall, exceedsMax, - isLoading + isLoading, + traceSamples }) => { + const [sampleActivePage, setSampleActivePage] = useState(0); + + useEffect(() => { + setSampleActivePage(0); + }, [traceSamples]); + + const goToSample = (index: number) => { + setSampleActivePage(index); + const sample = traceSamples[index]; + history.push({ + ...history.location, + search: fromQuery({ + ...toQuery(history.location.search), + transactionId: sample.transactionId, + traceId: sample.traceId + }) + }); + }; + const { entryTransaction } = waterfall; if (!entryTransaction) { const content = isLoading ? ( @@ -140,7 +102,7 @@ export const WaterfallWithSummmary: React.FC = ({ return ( - +
{i18n.translate('xpack.apm.transactionDetails.traceSampleTitle', { @@ -148,8 +110,19 @@ export const WaterfallWithSummmary: React.FC = ({ })}
+ {traceSamples && ( + + {sampleActivePage + 1} + /{traceSamples.length} + + + )}
- diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx index e4b2608343fac..092f10bc65156 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx @@ -13,7 +13,7 @@ import { EuiFlexItem } from '@elastic/eui'; import _ from 'lodash'; -import React, { useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution'; import { useWaterfall } from '../../../hooks/useWaterfall'; @@ -29,6 +29,7 @@ import { ChartsSyncContextProvider } from '../../../context/ChartsSyncContext'; import { useTrackPageview } from '../../../../../infra/public'; import { PROJECTION } from '../../../../common/projections/typings'; import { LocalUIFilters } from '../../shared/LocalUIFilters'; +import { HeightRetainer } from '../../shared/HeightRetainer'; export function TransactionDetails() { const location = useLocation(); @@ -60,6 +61,9 @@ export function TransactionDetails() { return config; }, [transactionName, transactionType, serviceName]); + const [selectedBucket, setSelectedBucket] = useState(-1); + const traceSamples = distributionData.buckets[selectedBucket]?.samples; + return (
@@ -93,18 +97,22 @@ export function TransactionDetails() { distribution={distributionData} isLoading={distributionStatus === FETCH_STATUS.LOADING} urlParams={urlParams} + onBucketSelected={setSelectedBucket} /> - + + +
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js index f76a27480137a..ec704d7405019 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/Histogram.test.js @@ -95,9 +95,11 @@ describe('Histogram', () => { it('should update state with "hoveredBucket"', () => { expect(wrapper.state()).toEqual({ hoveredBucket: { - sample: { - transactionId: '99c50a5b-44b4-4289-a3d1-a2815d128192' - }, + samples: [ + { + transactionId: '99c50a5b-44b4-4289-a3d1-a2815d128192' + } + ], style: { cursor: 'pointer' }, xCenter: 869010, x0: 811076, @@ -123,9 +125,11 @@ describe('Histogram', () => { it('should call onClick with bucket', () => { expect(onClick).toHaveBeenCalledWith({ - sample: { - transactionId: '99c50a5b-44b4-4289-a3d1-a2815d128192' - }, + samples: [ + { + transactionId: '99c50a5b-44b4-4289-a3d1-a2815d128192' + } + ], style: { cursor: 'pointer' }, xCenter: 869010, x0: 811076, diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json index f48213f72a983..302e105dfa997 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/response.json @@ -8,23 +8,29 @@ { "key": 579340, "count": 8, - "sample": { - "transactionId": "99437ee4-08d4-41f5-9b2b-93cc32ec3dfb" - } + "samples": [ + { + "transactionId": "99437ee4-08d4-41f5-9b2b-93cc32ec3dfb" + } + ] }, { "key": 695208, "count": 23, - "sample": { - "transactionId": "d327611b-e999-4942-a94f-c60208940180" - } + "samples": [ + { + "transactionId": "d327611b-e999-4942-a94f-c60208940180" + } + ] }, { "key": 811076, "count": 49, - "sample": { - "transactionId": "99c50a5b-44b4-4289-a3d1-a2815d128192" - } + "samples": [ + { + "transactionId": "99c50a5b-44b4-4289-a3d1-a2815d128192" + } + ] }, { "key": 926944, @@ -39,9 +45,11 @@ { "key": 1158680, "count": 13, - "sample": { - "transactionId": "8486d3e2-7f15-48df-aa37-6ee9955adbd2" - } + "samples": [ + { + "transactionId": "8486d3e2-7f15-48df-aa37-6ee9955adbd2" + } + ] }, { "key": 1274548, diff --git a/x-pack/legacy/plugins/apm/public/hooks/useTransactionDistribution.ts b/x-pack/legacy/plugins/apm/public/hooks/useTransactionDistribution.ts index 4c7e337212e55..e50ea7eab187f 100644 --- a/x-pack/legacy/plugins/apm/public/hooks/useTransactionDistribution.ts +++ b/x-pack/legacy/plugins/apm/public/hooks/useTransactionDistribution.ts @@ -49,19 +49,10 @@ export function useTransactionDistribution(urlParams: IUrlParams) { } }); } - // the histogram should not be refetched if the transactionId or traceId changes - // eslint-disable-next-line react-hooks/exhaustive-deps }, - [ - serviceName, - start, - end, - transactionType, - transactionName, - transactionId, - traceId, - uiFilters - ] + // the histogram should not be refetched if the transactionId or traceId changes + // eslint-disable-next-line react-hooks/exhaustive-deps + [serviceName, start, end, transactionType, transactionName, uiFilters] ); return { data, status, error }; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index 32fa65722869d..379884a677866 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -67,10 +67,17 @@ export async function bucketFetcher( } }, aggs: { - sample: { - top_hits: { - _source: [TRANSACTION_ID, TRANSACTION_SAMPLED, TRACE_ID], - size: 1 + samples: { + filter: { + term: { [TRANSACTION_SAMPLED]: true } + }, + aggs: { + items: { + top_hits: { + _source: [TRANSACTION_ID, TRACE_ID], + size: 10 + } + } } } } diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts index a16e08138b87f..2e703dfb19680 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts @@ -11,25 +11,23 @@ import { bucketFetcher } from './fetcher'; type DistributionBucketResponse = PromiseReturnType; export type IBucket = ReturnType; + function getBucket( bucket: Required< DistributionBucketResponse >['aggregations']['distribution']['buckets'][0] ) { - const sampleSource = bucket.sample.hits.hits[0]?._source as - | Transaction - | undefined; - - const isSampled = sampleSource?.transaction.sampled; - const sample = { - traceId: sampleSource?.trace.id, - transactionId: sampleSource?.transaction.id - }; + const samples = bucket.samples.items.hits.hits.map( + ({ _source }: { _source: Transaction }) => ({ + traceId: _source.trace.id, + transactionId: _source.transaction.id + }) + ); return { key: bucket.key, count: bucket.doc_count, - sample: isSampled ? sample : undefined + samples }; } From 91ec3792c7cda1ff69c530ea95ba8ab0ed89060a Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Fri, 29 Nov 2019 15:13:51 +0100 Subject: [PATCH 2/4] adding trace pagination --- .../app/TransactionDetails/Distribution/index.tsx | 9 ++------- .../lib/transactions/distribution/get_buckets/fetcher.ts | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index afded03a827c3..9e41243fe84b5 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -7,12 +7,7 @@ import { EuiIconTip, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import d3 from 'd3'; -import React, { - FunctionComponent, - useCallback, - Dispatch, - SetStateAction -} from 'react'; +import React, { FunctionComponent, useCallback } from 'react'; import { isEmpty } from 'lodash'; import { TransactionDistributionAPIResponse } from '../../../../../server/lib/transactions/distribution'; import { IBucket } from '../../../../../server/lib/transactions/distribution/get_buckets/transform'; @@ -99,7 +94,7 @@ interface Props { distribution?: TransactionDistributionAPIResponse; urlParams: IUrlParams; isLoading: boolean; - onBucketSelected: Dispatch>; + onBucketSelected(index: number): void; } export const TransactionDistribution: FunctionComponent = ( diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index 379884a677866..b2f0834107df4 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -50,8 +50,7 @@ export async function bucketFetcher( ], should: [ { term: { [TRACE_ID]: traceId } }, - { term: { [TRANSACTION_ID]: transactionId } }, - { term: { [TRANSACTION_SAMPLED]: true } } + { term: { [TRANSACTION_ID]: transactionId } } ] } }, From ca896ae68d8ef5d8031e6ba016726de1acad1b59 Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Mon, 2 Dec 2019 09:39:52 +0100 Subject: [PATCH 3/4] refactoring --- .../components/app/TransactionDetails/Distribution/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index 9e41243fe84b5..237199e032a3e 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -144,7 +144,7 @@ export const TransactionDistribution: FunctionComponent = ( sample => sample.transactionId === transactionId && sample.traceId === traceId ); - return sampleFound === -1 ? false : true; + return sampleFound !== -1; }); onBucketSelected(bucketIndex); From b9739513ad09a54d3ddd9fe293d68a0d75a49691 Mon Sep 17 00:00:00 2001 From: cauemarcondes Date: Mon, 2 Dec 2019 12:02:45 +0100 Subject: [PATCH 4/4] refactoring --- ...tribution.test.js => distribution.test.ts} | 3 +- .../TransactionDetails/Distribution/index.tsx | 28 +++++-------------- .../WaterfallWithSummmary/index.tsx | 5 ++-- .../app/TransactionDetails/index.tsx | 15 +++++++--- 4 files changed, 23 insertions(+), 28 deletions(-) rename x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/{distribution.test.js => distribution.test.ts} (92%) diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.ts similarity index 92% rename from x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js rename to x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.ts index eb42d19f3517e..85398a1324f7b 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.js +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/__test__/distribution.test.ts @@ -5,6 +5,7 @@ */ import { getFormattedBuckets } from '../index'; +import { IBucket } from '../../../../../../server/lib/transactions/distribution/get_buckets/transform'; describe('Distribution', () => { it('getFormattedBuckets', () => { @@ -30,7 +31,7 @@ describe('Distribution', () => { } ] } - ]; + ] as IBucket[]; expect(getFormattedBuckets(buckets, 20)).toEqual([ { x: 20, x0: 0, y: 0, style: { cursor: 'default' }, samples: [] }, { x: 40, x0: 20, y: 0, style: { cursor: 'default' }, samples: [] }, diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index 237199e032a3e..acd50438b4d54 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -43,7 +43,7 @@ export function getFormattedBuckets(buckets: IBucket[], bucketSize: number) { x: key + bucketSize, y: count, style: { - cursor: count > 0 && !isEmpty(samples) ? 'pointer' : 'default' + cursor: isEmpty(samples) ? 'default' : 'pointer' } }; } @@ -94,7 +94,7 @@ interface Props { distribution?: TransactionDistributionAPIResponse; urlParams: IUrlParams; isLoading: boolean; - onBucketSelected(index: number): void; + bucketIndex: number; } export const TransactionDistribution: FunctionComponent = ( @@ -102,9 +102,9 @@ export const TransactionDistribution: FunctionComponent = ( ) => { const { distribution, - urlParams: { transactionId, traceId, transactionType }, + urlParams: { transactionType }, isLoading, - onBucketSelected + bucketIndex } = props; const formatYShort = useCallback(getFormatYShort(transactionType), [ @@ -139,16 +139,6 @@ export const TransactionDistribution: FunctionComponent = ( const xMax = d3.max(buckets, d => d.x) || 0; const timeFormatter = getDurationFormatter(xMax); - const bucketIndex = buckets.findIndex(bucket => { - const sampleFound = bucket.samples.findIndex( - sample => - sample.transactionId === transactionId && sample.traceId === traceId - ); - return sampleFound !== -1; - }); - - onBucketSelected(bucketIndex); - return (
@@ -183,7 +173,7 @@ export const TransactionDistribution: FunctionComponent = ( bucketSize={distribution.bucketSize} bucketIndex={bucketIndex} onClick={(bucket: IChartPoint) => { - if (!isEmpty(bucket.samples) && bucket.y > 0) { + if (!isEmpty(bucket.samples)) { const sample = bucket.samples[0]; history.push({ ...history.location, @@ -198,12 +188,8 @@ export const TransactionDistribution: FunctionComponent = ( formatX={(time: number) => timeFormatter(time).formatted} formatYShort={formatYShort} formatYLong={formatYLong} - verticalLineHover={(bucket: IChartPoint) => - bucket.y > 0 && isEmpty(bucket.samples) - } - backgroundHover={(bucket: IChartPoint) => - bucket.y > 0 && !isEmpty(bucket.samples) - } + verticalLineHover={(bucket: IChartPoint) => isEmpty(bucket.samples)} + backgroundHover={(bucket: IChartPoint) => !isEmpty(bucket.samples)} tooltipHeader={(bucket: IChartPoint) => { const xFormatted = timeFormatter(bucket.x); const x0Formatted = timeFormatter(bucket.x0); diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx index d0c0d16e84195..b56370a59c8e2 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/index.tsx @@ -28,9 +28,10 @@ import { IBucket } from '../../../../../server/lib/transactions/distribution/get import { history } from '../../../../utils/history'; import { fromQuery, toQuery } from '../../../shared/Links/url_helpers'; import { MaybeViewTraceLink } from './MaybeViewTraceLink'; +import { units, px } from '../../../../style/variables'; const PaginationContainer = styled.div` - margin-left: 4px; + margin-left: ${px(units.quarter)}; display: flex; align-items: center; @@ -39,7 +40,7 @@ const PaginationContainer = styled.div` } > span:last-of-type { - margin-right: 8px; + margin-right: ${px(units.half)}; } `; diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx index 092f10bc65156..dbd0e9d3b9d22 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/index.tsx @@ -13,7 +13,7 @@ import { EuiFlexItem } from '@elastic/eui'; import _ from 'lodash'; -import React, { useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { useTransactionCharts } from '../../../hooks/useTransactionCharts'; import { useTransactionDistribution } from '../../../hooks/useTransactionDistribution'; import { useWaterfall } from '../../../hooks/useWaterfall'; @@ -61,8 +61,15 @@ export function TransactionDetails() { return config; }, [transactionName, transactionType, serviceName]); - const [selectedBucket, setSelectedBucket] = useState(-1); - const traceSamples = distributionData.buckets[selectedBucket]?.samples; + const bucketIndex = distributionData.buckets.findIndex(bucket => + bucket.samples.some( + sample => + sample.transactionId === urlParams.transactionId && + sample.traceId === urlParams.traceId + ) + ); + + const traceSamples = distributionData.buckets[bucketIndex]?.samples; return (
@@ -97,7 +104,7 @@ export function TransactionDetails() { distribution={distributionData} isLoading={distributionStatus === FETCH_STATUS.LOADING} urlParams={urlParams} - onBucketSelected={setSelectedBucket} + bucketIndex={bucketIndex} />