Skip to content

Commit

Permalink
[APM] Service overview transactions table (#83429)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgieselaar authored Nov 20, 2020
1 parent 2074b29 commit 6417ee6
Show file tree
Hide file tree
Showing 22 changed files with 1,186 additions and 69 deletions.
30 changes: 27 additions & 3 deletions x-pack/plugins/apm/common/utils/formatters/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { i18n } from '@kbn/i18n';
import moment from 'moment';
import { memoize } from 'lodash';
import { NOT_AVAILABLE_LABEL } from '../../../common/i18n';
import { asDecimalOrInteger, asInteger } from './formatters';
import { asDecimal, asDecimalOrInteger, asInteger } from './formatters';
import { TimeUnit } from './datetime';
import { Maybe } from '../../../typings/common';
import { isFiniteNumber } from '../is_finite_number';

interface FormatterOptions {
defaultValue?: string;
Expand Down Expand Up @@ -99,7 +100,7 @@ function convertTo({
microseconds: Maybe<number>;
defaultValue?: string;
}): ConvertedDuration {
if (microseconds == null) {
if (!isFiniteNumber(microseconds)) {
return { value: defaultValue, formatted: defaultValue };
}

Expand Down Expand Up @@ -143,14 +144,37 @@ export const getDurationFormatter: TimeFormatterBuilder = memoize(
}
);

export function asTransactionRate(value: Maybe<number>) {
if (!isFiniteNumber(value)) {
return NOT_AVAILABLE_LABEL;
}

let displayedValue: string;

if (value === 0) {
displayedValue = '0';
} else if (value <= 0.1) {
displayedValue = '< 0.1';
} else {
displayedValue = asDecimal(value);
}

return i18n.translate('xpack.apm.transactionRateLabel', {
defaultMessage: `{value} tpm`,
values: {
value: displayedValue,
},
});
}

/**
* Converts value and returns it formatted - 00 unit
*/
export function asDuration(
value: Maybe<number>,
{ defaultValue = NOT_AVAILABLE_LABEL }: FormatterOptions = {}
) {
if (value == null) {
if (!isFiniteNumber(value)) {
return defaultValue;
}

Expand Down
9 changes: 6 additions & 3 deletions x-pack/plugins/apm/common/utils/formatters/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
*/
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';
import { Maybe } from '../../../typings/common';
import { NOT_AVAILABLE_LABEL } from '../../i18n';
import { isFiniteNumber } from '../is_finite_number';

export function asDecimal(value: number) {
return numeral(value).format('0,0.0');
Expand All @@ -25,11 +28,11 @@ export function tpmUnit(type?: string) {
}

export function asPercent(
numerator: number,
numerator: Maybe<number>,
denominator: number | undefined,
fallbackResult = ''
fallbackResult = NOT_AVAILABLE_LABEL
) {
if (!denominator || isNaN(numerator)) {
if (!denominator || !isFiniteNumber(numerator)) {
return fallbackResult;
}

Expand Down
12 changes: 12 additions & 0 deletions x-pack/plugins/apm/common/utils/is_finite_number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 { isFinite } from 'lodash';
import { Maybe } from '../../typings/common';

// _.isNumber() returns true for NaN, _.isFinite() does not refine
export function isFiniteNumber(value: Maybe<number>): value is number {
return isFinite(value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,19 @@ export function ServiceStatsList({
title: i18n.translate('xpack.apm.serviceMap.errorRatePopoverStat', {
defaultMessage: 'Trans. error rate (avg.)',
}),
description: isNumber(avgErrorRate) ? asPercent(avgErrorRate, 1) : null,
description: asPercent(avgErrorRate, 1, ''),
},
{
title: i18n.translate('xpack.apm.serviceMap.avgCpuUsagePopoverStat', {
defaultMessage: 'CPU usage (avg.)',
}),
description: isNumber(avgCpuUsage) ? asPercent(avgCpuUsage, 1) : null,
description: asPercent(avgCpuUsage, 1, ''),
},
{
title: i18n.translate('xpack.apm.serviceMap.avgMemoryUsagePopoverStat', {
defaultMessage: 'Memory usage (avg.)',
}),
description: isNumber(avgMemoryUsage)
? asPercent(avgMemoryUsage, 1)
: null,
description: asPercent(avgMemoryUsage, 1, ''),
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function ServiceNodeOverview({ serviceName }: ServiceNodeOverviewProps) {
}),
field: 'cpu',
sortable: true,
render: (value: number | null) => asPercent(value || 0, 1),
render: (value: number | null) => asPercent(value, 1),
},
{
name: i18n.translate('xpack.apm.jvmsTable.heapMemoryColumnLabel', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { useUrlParams } from '../../../../hooks/useUrlParams';
import { SparkPlotWithValueLabel } from '../../../shared/charts/spark_plot/spark_plot_with_value_label';

export function ServiceListMetric({
Expand All @@ -16,14 +15,8 @@ export function ServiceListMetric({
series?: Array<{ x: number; y: number | null }>;
valueLabel: React.ReactNode;
}) {
const {
urlParams: { start, end },
} = useUrlParams();

return (
<SparkPlotWithValueLabel
start={parseFloat(start!)}
end={parseFloat(end!)}
valueLabel={valueLabel}
series={series}
color={color}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ export const SERVICE_COLUMNS: Array<ITableColumn<ServiceListItem>> = [
render: (_, { transactionErrorRate }) => {
const value = transactionErrorRate?.value;

const valueLabel =
value !== null && value !== undefined ? asPercent(value, 1) : '';
const valueLabel = asPercent(value, 1);

return (
<ServiceListMetric
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import { isRumAgentName } from '../../../../common/agent_name';
import { ChartsSyncContextProvider } from '../../../context/charts_sync_context';
import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
import { SearchBar } from '../../shared/search_bar';
import { ServiceOverviewErrorsTable } from './service_overview_errors_table';
import { ServiceOverviewTransactionsTable } from './service_overview_transactions_table';
import { TableLinkFlexItem } from './table_link_flex_item';

/**
Expand Down Expand Up @@ -78,30 +78,7 @@ export function ServiceOverview({
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.transactionsTableTitle',
{
defaultMessage: 'Transactions',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
<TableLinkFlexItem>
<TransactionOverviewLink serviceName={serviceName}>
{i18n.translate(
'xpack.apm.serviceOverview.transactionsTableLinkText',
{
defaultMessage: 'View transactions',
}
)}
</TransactionOverviewLink>
</TableLinkFlexItem>
</EuiFlexGroup>
<ServiceOverviewTransactionsTable serviceName={serviceName} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { px, truncate, unit } from '../../../../style/variables';
import { SparkPlotWithValueLabel } from '../../../shared/charts/spark_plot/spark_plot_with_value_label';
import { ErrorDetailLink } from '../../../shared/Links/apm/ErrorDetailLink';
import { ErrorOverviewLink } from '../../../shared/Links/apm/ErrorOverviewLink';
import { TableFetchWrapper } from '../../../shared/table_fetch_wrapper';
import { TimestampTooltip } from '../../../shared/TimestampTooltip';
import { ServiceOverviewTable } from '../service_overview_table';
import { TableLinkFlexItem } from '../table_link_flex_item';
import { FetchWrapper } from './fetch_wrapper';

interface Props {
serviceName: string;
Expand Down Expand Up @@ -135,8 +135,6 @@ export function ServiceOverviewErrorsTable({ serviceName }: Props) {
},
}
)}
start={parseFloat(start!)}
end={parseFloat(end!)}
/>
);
},
Expand Down Expand Up @@ -225,7 +223,7 @@ export function ServiceOverviewErrorsTable({ serviceName }: Props) {
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<FetchWrapper status={status}>
<TableFetchWrapper status={status}>
<ServiceOverviewTable
columns={columns}
items={items}
Expand Down Expand Up @@ -261,7 +259,7 @@ export function ServiceOverviewErrorsTable({ serviceName }: Props) {
},
}}
/>
</FetchWrapper>
</TableFetchWrapper>
</EuiFlexItem>
</EuiFlexGroup>
);
Expand Down
Loading

0 comments on commit 6417ee6

Please sign in to comment.