[APM] latencyAggregationType is not persisted when navigation to Transaction overview to detail (#87046)
* persisting latency aggregation type * addressing PR comments * removing useLatencyAggregationType hook * addressing PR comments * addressing PR comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
183cf56fcd
commit
e3455ce35b
|
@ -24,7 +24,7 @@ import { APIReturnType } from '../../../../services/rest/createCallApmApi';
|
||||||
import { APMError } from '../../../../../typings/es_schemas/ui/apm_error';
|
import { APMError } from '../../../../../typings/es_schemas/ui/apm_error';
|
||||||
import type { IUrlParams } from '../../../../context/url_params_context/types';
|
import type { IUrlParams } from '../../../../context/url_params_context/types';
|
||||||
import { px, unit, units } from '../../../../style/variables';
|
import { px, unit, units } from '../../../../style/variables';
|
||||||
import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_detail_link';
|
||||||
import { DiscoverErrorLink } from '../../../shared/Links/DiscoverLinks/DiscoverErrorLink';
|
import { DiscoverErrorLink } from '../../../shared/Links/DiscoverLinks/DiscoverErrorLink';
|
||||||
import { fromQuery, toQuery } from '../../../shared/Links/url_helpers';
|
import { fromQuery, toQuery } from '../../../shared/Links/url_helpers';
|
||||||
import { ErrorMetadata } from '../../../shared/MetadataTable/ErrorMetadata';
|
import { ErrorMetadata } from '../../../shared/MetadataTable/ErrorMetadata';
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { EmptyMessage } from '../../shared/EmptyMessage';
|
||||||
import { ImpactBar } from '../../shared/ImpactBar';
|
import { ImpactBar } from '../../shared/ImpactBar';
|
||||||
import { ITableColumn, ManagedTable } from '../../shared/ManagedTable';
|
import { ITableColumn, ManagedTable } from '../../shared/ManagedTable';
|
||||||
import { LoadingStatePrompt } from '../../shared/LoadingStatePrompt';
|
import { LoadingStatePrompt } from '../../shared/LoadingStatePrompt';
|
||||||
import { TransactionDetailLink } from '../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../shared/Links/apm/transaction_detail_link';
|
||||||
import { APIReturnType } from '../../../services/rest/createCallApmApi';
|
import { APIReturnType } from '../../../services/rest/createCallApmApi';
|
||||||
|
|
||||||
type TraceGroup = APIReturnType<'GET /api/apm/traces'>['items'][0];
|
type TraceGroup = APIReturnType<'GET /api/apm/traces'>['items'][0];
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
* you may not use this file except in compliance with 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 { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import React from 'react';
|
||||||
|
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||||
import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/transaction';
|
import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/transaction';
|
||||||
import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_detail_link';
|
||||||
import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers';
|
import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers';
|
||||||
|
|
||||||
export const MaybeViewTraceLink = ({
|
export const MaybeViewTraceLink = ({
|
||||||
|
@ -18,6 +19,9 @@ export const MaybeViewTraceLink = ({
|
||||||
transaction: ITransaction;
|
transaction: ITransaction;
|
||||||
waterfall: IWaterfall;
|
waterfall: IWaterfall;
|
||||||
}) => {
|
}) => {
|
||||||
|
const {
|
||||||
|
urlParams: { latencyAggregationType },
|
||||||
|
} = useUrlParams();
|
||||||
const viewFullTraceButtonLabel = i18n.translate(
|
const viewFullTraceButtonLabel = i18n.translate(
|
||||||
'xpack.apm.transactionDetails.viewFullTraceButtonLabel',
|
'xpack.apm.transactionDetails.viewFullTraceButtonLabel',
|
||||||
{
|
{
|
||||||
|
@ -77,6 +81,7 @@ export const MaybeViewTraceLink = ({
|
||||||
traceId={rootTransaction.trace.id}
|
traceId={rootTransaction.trace.id}
|
||||||
transactionName={rootTransaction.transaction.name}
|
transactionName={rootTransaction.transaction.name}
|
||||||
transactionType={rootTransaction.transaction.type}
|
transactionType={rootTransaction.transaction.type}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
>
|
>
|
||||||
<EuiButton iconType="apmTrace">{viewFullTraceButtonLabel}</EuiButton>
|
<EuiButton iconType="apmTrace">{viewFullTraceButtonLabel}</EuiButton>
|
||||||
</TransactionDetailLink>
|
</TransactionDetailLink>
|
||||||
|
|
|
@ -6,20 +6,25 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useUrlParams } from '../../../../../../context/url_params_context/use_url_params';
|
||||||
import {
|
import {
|
||||||
SERVICE_NAME,
|
SERVICE_NAME,
|
||||||
TRANSACTION_NAME,
|
TRANSACTION_NAME,
|
||||||
} from '../../../../../../../common/elasticsearch_fieldnames';
|
} from '../../../../../../../common/elasticsearch_fieldnames';
|
||||||
import { Transaction } from '../../../../../../../typings/es_schemas/ui/transaction';
|
import { Transaction } from '../../../../../../../typings/es_schemas/ui/transaction';
|
||||||
import { TransactionDetailLink } from '../../../../../shared/Links/apm/TransactionDetailLink';
|
|
||||||
import { StickyProperties } from '../../../../../shared/StickyProperties';
|
|
||||||
import { ServiceOrTransactionsOverviewLink } from '../../../../../shared/Links/apm/service_transactions_overview_link';
|
import { ServiceOrTransactionsOverviewLink } from '../../../../../shared/Links/apm/service_transactions_overview_link';
|
||||||
|
import { TransactionDetailLink } from '../../../../../shared/Links/apm/transaction_detail_link';
|
||||||
|
import { StickyProperties } from '../../../../../shared/StickyProperties';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
transaction?: Transaction;
|
transaction?: Transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FlyoutTopLevelProperties({ transaction }: Props) {
|
export function FlyoutTopLevelProperties({ transaction }: Props) {
|
||||||
|
const {
|
||||||
|
urlParams: { latencyAggregationType },
|
||||||
|
} = useUrlParams();
|
||||||
|
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +56,7 @@ export function FlyoutTopLevelProperties({ transaction }: Props) {
|
||||||
traceId={transaction.trace.id}
|
traceId={transaction.trace.id}
|
||||||
transactionName={transaction.transaction.name}
|
transactionName={transaction.transaction.name}
|
||||||
transactionType={transaction.transaction.type}
|
transactionType={transaction.transaction.type}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
>
|
>
|
||||||
{transaction.transaction.name}
|
{transaction.transaction.name}
|
||||||
</TransactionDetailLink>
|
</TransactionDetailLink>
|
||||||
|
|
|
@ -6,17 +6,18 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Transaction } from '../../../../../../../../typings/es_schemas/ui/transaction';
|
import { useUrlParams } from '../../../../../../../context/url_params_context/use_url_params';
|
||||||
import {
|
import {
|
||||||
|
SERVICE_NAME,
|
||||||
SPAN_NAME,
|
SPAN_NAME,
|
||||||
TRANSACTION_NAME,
|
TRANSACTION_NAME,
|
||||||
SERVICE_NAME,
|
|
||||||
} from '../../../../../../../../common/elasticsearch_fieldnames';
|
} from '../../../../../../../../common/elasticsearch_fieldnames';
|
||||||
import { NOT_AVAILABLE_LABEL } from '../../../../../../../../common/i18n';
|
import { NOT_AVAILABLE_LABEL } from '../../../../../../../../common/i18n';
|
||||||
import { Span } from '../../../../../../../../typings/es_schemas/ui/span';
|
import { Span } from '../../../../../../../../typings/es_schemas/ui/span';
|
||||||
import { StickyProperties } from '../../../../../../shared/StickyProperties';
|
import { Transaction } from '../../../../../../../../typings/es_schemas/ui/transaction';
|
||||||
import { ServiceOrTransactionsOverviewLink } from '../../../../../../shared/Links/apm/service_transactions_overview_link';
|
import { ServiceOrTransactionsOverviewLink } from '../../../../../../shared/Links/apm/service_transactions_overview_link';
|
||||||
import { TransactionDetailLink } from '../../../../../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../../../../../shared/Links/apm/transaction_detail_link';
|
||||||
|
import { StickyProperties } from '../../../../../../shared/StickyProperties';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
span: Span;
|
span: Span;
|
||||||
|
@ -24,6 +25,9 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StickySpanProperties({ span, transaction }: Props) {
|
export function StickySpanProperties({ span, transaction }: Props) {
|
||||||
|
const {
|
||||||
|
urlParams: { latencyAggregationType },
|
||||||
|
} = useUrlParams();
|
||||||
const spanName = span.span.name;
|
const spanName = span.span.name;
|
||||||
const transactionStickyProperties = transaction
|
const transactionStickyProperties = transaction
|
||||||
? [
|
? [
|
||||||
|
@ -56,6 +60,7 @@ export function StickySpanProperties({ span, transaction }: Props) {
|
||||||
traceId={transaction.trace.id}
|
traceId={transaction.trace.id}
|
||||||
transactionName={transaction.transaction.name}
|
transactionName={transaction.transaction.name}
|
||||||
transactionType={transaction.transaction.type}
|
transactionType={transaction.transaction.type}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
>
|
>
|
||||||
{transaction.transaction.name}
|
{transaction.transaction.name}
|
||||||
</TransactionDetailLink>
|
</TransactionDetailLink>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
|
||||||
import { enableServiceOverview } from '../../../../common/ui_settings_keys';
|
import { enableServiceOverview } from '../../../../common/ui_settings_keys';
|
||||||
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
|
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
|
||||||
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
|
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
|
||||||
|
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
|
||||||
import { useErrorOverviewHref } from '../../shared/Links/apm/ErrorOverviewLink';
|
import { useErrorOverviewHref } from '../../shared/Links/apm/ErrorOverviewLink';
|
||||||
import { useMetricOverviewHref } from '../../shared/Links/apm/MetricOverviewLink';
|
import { useMetricOverviewHref } from '../../shared/Links/apm/MetricOverviewLink';
|
||||||
import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
|
import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
|
||||||
|
@ -46,6 +47,9 @@ interface Props {
|
||||||
export function ServiceDetailTabs({ serviceName, tab }: Props) {
|
export function ServiceDetailTabs({ serviceName, tab }: Props) {
|
||||||
const { agentName } = useApmServiceContext();
|
const { agentName } = useApmServiceContext();
|
||||||
const { uiSettings } = useApmPluginContext().core;
|
const { uiSettings } = useApmPluginContext().core;
|
||||||
|
const {
|
||||||
|
urlParams: { latencyAggregationType },
|
||||||
|
} = useUrlParams();
|
||||||
|
|
||||||
const overviewTab = {
|
const overviewTab = {
|
||||||
key: 'overview',
|
key: 'overview',
|
||||||
|
@ -60,7 +64,7 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {
|
||||||
|
|
||||||
const transactionsTab = {
|
const transactionsTab = {
|
||||||
key: 'transactions',
|
key: 'transactions',
|
||||||
href: useTransactionsOverviewHref(serviceName),
|
href: useTransactionsOverviewHref({ serviceName, latencyAggregationType }),
|
||||||
text: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
|
text: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
|
||||||
defaultMessage: 'Transactions',
|
defaultMessage: 'Transactions',
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { ServiceOverview } from './';
|
||||||
import { waitFor } from '@testing-library/dom';
|
import { waitFor } from '@testing-library/dom';
|
||||||
import * as callApmApiModule from '../../../services/rest/createCallApmApi';
|
import * as callApmApiModule from '../../../services/rest/createCallApmApi';
|
||||||
import * as useApmServiceContextHooks from '../../../context/apm_service/use_apm_service_context';
|
import * as useApmServiceContextHooks from '../../../context/apm_service/use_apm_service_context';
|
||||||
|
import { LatencyAggregationType } from '../../../../common/latency_aggregation_types';
|
||||||
|
|
||||||
const KibanaReactContext = createKibanaReactContext({
|
const KibanaReactContext = createKibanaReactContext({
|
||||||
usageCollection: { reportUiCounter: () => {} },
|
usageCollection: { reportUiCounter: () => {} },
|
||||||
|
@ -45,7 +46,11 @@ function Wrapper({ children }: { children?: ReactNode }) {
|
||||||
<KibanaReactContext.Provider>
|
<KibanaReactContext.Provider>
|
||||||
<MockApmPluginContextWrapper value={value}>
|
<MockApmPluginContextWrapper value={value}>
|
||||||
<MockUrlParamsContextProvider
|
<MockUrlParamsContextProvider
|
||||||
params={{ rangeFrom: 'now-15m', rangeTo: 'now' }}
|
params={{
|
||||||
|
rangeFrom: 'now-15m',
|
||||||
|
rangeTo: 'now',
|
||||||
|
latencyAggregationType: LatencyAggregationType.avg,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</MockUrlParamsContextProvider>
|
</MockUrlParamsContextProvider>
|
||||||
|
|
|
@ -23,7 +23,6 @@ import {
|
||||||
import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
|
import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
|
||||||
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||||
import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher';
|
import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher';
|
||||||
import { useLatencyAggregationType } from '../../../../hooks/use_latency_Aggregation_type';
|
|
||||||
import {
|
import {
|
||||||
APIReturnType,
|
APIReturnType,
|
||||||
callApmApi,
|
callApmApi,
|
||||||
|
@ -31,7 +30,7 @@ import {
|
||||||
import { px, unit } from '../../../../style/variables';
|
import { px, unit } from '../../../../style/variables';
|
||||||
import { SparkPlot } from '../../../shared/charts/spark_plot';
|
import { SparkPlot } from '../../../shared/charts/spark_plot';
|
||||||
import { ImpactBar } from '../../../shared/ImpactBar';
|
import { ImpactBar } from '../../../shared/ImpactBar';
|
||||||
import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_detail_link';
|
||||||
import { TransactionOverviewLink } from '../../../shared/Links/apm/transaction_overview_link';
|
import { TransactionOverviewLink } from '../../../shared/Links/apm/transaction_overview_link';
|
||||||
import { TableFetchWrapper } from '../../../shared/table_fetch_wrapper';
|
import { TableFetchWrapper } from '../../../shared/table_fetch_wrapper';
|
||||||
import { TruncateWithTooltip } from '../../../shared/truncate_with_tooltip';
|
import { TruncateWithTooltip } from '../../../shared/truncate_with_tooltip';
|
||||||
|
@ -54,10 +53,16 @@ const DEFAULT_SORT = {
|
||||||
field: 'impact' as const,
|
field: 'impact' as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getLatencyAggregationTypeLabel(
|
function getLatencyAggregationTypeLabel(latencyAggregationType?: string) {
|
||||||
latencyAggregationType?: LatencyAggregationType
|
|
||||||
) {
|
|
||||||
switch (latencyAggregationType) {
|
switch (latencyAggregationType) {
|
||||||
|
case 'avg': {
|
||||||
|
i18n.translate(
|
||||||
|
'xpack.apm.serviceOverview.transactionsTableColumnLatency.avg',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Latency (avg.)',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
case 'p95': {
|
case 'p95': {
|
||||||
return i18n.translate(
|
return i18n.translate(
|
||||||
'xpack.apm.serviceOverview.transactionsTableColumnLatency.p95',
|
'xpack.apm.serviceOverview.transactionsTableColumnLatency.p95',
|
||||||
|
@ -74,24 +79,15 @@ function getLatencyAggregationTypeLabel(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
default: {
|
|
||||||
return i18n.translate(
|
|
||||||
'xpack.apm.serviceOverview.transactionsTableColumnLatency.avg',
|
|
||||||
{
|
|
||||||
defaultMessage: 'Latency (avg.)',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ServiceOverviewTransactionsTable(props: Props) {
|
export function ServiceOverviewTransactionsTable(props: Props) {
|
||||||
const { serviceName } = props;
|
const { serviceName } = props;
|
||||||
const { transactionType } = useApmServiceContext();
|
const { transactionType } = useApmServiceContext();
|
||||||
const latencyAggregationType = useLatencyAggregationType();
|
|
||||||
const {
|
const {
|
||||||
uiFilters,
|
uiFilters,
|
||||||
urlParams: { start, end },
|
urlParams: { start, end, latencyAggregationType },
|
||||||
} = useUrlParams();
|
} = useUrlParams();
|
||||||
|
|
||||||
const [tableOptions, setTableOptions] = useState<{
|
const [tableOptions, setTableOptions] = useState<{
|
||||||
|
@ -135,7 +131,7 @@ export function ServiceOverviewTransactionsTable(props: Props) {
|
||||||
sortField: tableOptions.sort.field,
|
sortField: tableOptions.sort.field,
|
||||||
sortDirection: tableOptions.sort.direction,
|
sortDirection: tableOptions.sort.direction,
|
||||||
transactionType,
|
transactionType,
|
||||||
latencyAggregationType,
|
latencyAggregationType: latencyAggregationType as LatencyAggregationType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
|
@ -187,6 +183,7 @@ export function ServiceOverviewTransactionsTable(props: Props) {
|
||||||
serviceName={serviceName}
|
serviceName={serviceName}
|
||||||
transactionName={name}
|
transactionName={name}
|
||||||
transactionType={type}
|
transactionType={type}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</TransactionDetailLink>
|
</TransactionDetailLink>
|
||||||
|
@ -282,7 +279,10 @@ export function ServiceOverviewTransactionsTable(props: Props) {
|
||||||
</EuiTitle>
|
</EuiTitle>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<TransactionOverviewLink serviceName={serviceName}>
|
<TransactionOverviewLink
|
||||||
|
serviceName={serviceName}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
|
>
|
||||||
{i18n.translate(
|
{i18n.translate(
|
||||||
'xpack.apm.serviceOverview.transactionsTableLinkText',
|
'xpack.apm.serviceOverview.transactionsTableLinkText',
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { EuiToolTip, EuiIconTip } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||||
import { APIReturnType } from '../../../../services/rest/createCallApmApi';
|
import { APIReturnType } from '../../../../services/rest/createCallApmApi';
|
||||||
import {
|
import {
|
||||||
asMillisecondDuration,
|
asMillisecondDuration,
|
||||||
|
@ -18,7 +19,7 @@ import { ImpactBar } from '../../../shared/ImpactBar';
|
||||||
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
|
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
|
||||||
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
|
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
|
||||||
import { EmptyMessage } from '../../../shared/EmptyMessage';
|
import { EmptyMessage } from '../../../shared/EmptyMessage';
|
||||||
import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
|
import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_detail_link';
|
||||||
|
|
||||||
type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups'>['items'][0];
|
type TransactionGroup = APIReturnType<'GET /api/apm/services/{serviceName}/transactions/groups'>['items'][0];
|
||||||
|
|
||||||
|
@ -40,6 +41,9 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TransactionList({ items, isLoading }: Props) {
|
export function TransactionList({ items, isLoading }: Props) {
|
||||||
|
const {
|
||||||
|
urlParams: { latencyAggregationType },
|
||||||
|
} = useUrlParams();
|
||||||
const columns: Array<ITableColumn<TransactionGroup>> = useMemo(
|
const columns: Array<ITableColumn<TransactionGroup>> = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
|
@ -58,6 +62,7 @@ export function TransactionList({ items, isLoading }: Props) {
|
||||||
serviceName={serviceName}
|
serviceName={serviceName}
|
||||||
transactionName={transactionName}
|
transactionName={transactionName}
|
||||||
transactionType={transactionType}
|
transactionType={transactionType}
|
||||||
|
latencyAggregationType={latencyAggregationType}
|
||||||
>
|
>
|
||||||
<EuiToolTip
|
<EuiToolTip
|
||||||
id="transaction-name-link-tooltip"
|
id="transaction-name-link-tooltip"
|
||||||
|
@ -134,7 +139,7 @@ export function TransactionList({ items, isLoading }: Props) {
|
||||||
render: (value: number) => <ImpactBar value={value} />,
|
render: (value: number) => <ImpactBar value={value} />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[]
|
[latencyAggregationType]
|
||||||
);
|
);
|
||||||
|
|
||||||
const noItemsMessage = (
|
const noItemsMessage = (
|
||||||
|
|
|
@ -1,49 +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 React from 'react';
|
|
||||||
import { APMLink, APMLinkExtendProps } from './APMLink';
|
|
||||||
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
|
||||||
import { pickKeys } from '../../../../../common/utils/pick_keys';
|
|
||||||
|
|
||||||
interface Props extends APMLinkExtendProps {
|
|
||||||
serviceName: string;
|
|
||||||
traceId?: string;
|
|
||||||
transactionId?: string;
|
|
||||||
transactionName: string;
|
|
||||||
transactionType: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function TransactionDetailLink({
|
|
||||||
serviceName,
|
|
||||||
traceId,
|
|
||||||
transactionId,
|
|
||||||
transactionName,
|
|
||||||
transactionType,
|
|
||||||
...rest
|
|
||||||
}: Props) {
|
|
||||||
const { urlParams } = useUrlParams();
|
|
||||||
|
|
||||||
const persistedFilters = pickKeys(
|
|
||||||
urlParams,
|
|
||||||
'transactionResult',
|
|
||||||
'serviceVersion'
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<APMLink
|
|
||||||
path={`/services/${serviceName}/transactions/view`}
|
|
||||||
query={{
|
|
||||||
traceId,
|
|
||||||
transactionId,
|
|
||||||
transactionName,
|
|
||||||
transactionType,
|
|
||||||
...persistedFilters,
|
|
||||||
}}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import { EuiLink } from '@elastic/eui';
|
||||||
|
import { getAPMHref, APMLinkExtendProps } from './APMLink';
|
||||||
|
import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
|
||||||
|
import { pickKeys } from '../../../../../common/utils/pick_keys';
|
||||||
|
import { APMQueryParams } from '../url_helpers';
|
||||||
|
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
|
||||||
|
|
||||||
|
interface Props extends APMLinkExtendProps {
|
||||||
|
serviceName: string;
|
||||||
|
traceId?: string;
|
||||||
|
transactionId?: string;
|
||||||
|
transactionName: string;
|
||||||
|
transactionType: string;
|
||||||
|
latencyAggregationType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const persistedFilters: Array<keyof APMQueryParams> = [
|
||||||
|
'transactionResult',
|
||||||
|
'serviceVersion',
|
||||||
|
];
|
||||||
|
|
||||||
|
export function TransactionDetailLink({
|
||||||
|
serviceName,
|
||||||
|
traceId,
|
||||||
|
transactionId,
|
||||||
|
transactionName,
|
||||||
|
transactionType,
|
||||||
|
latencyAggregationType,
|
||||||
|
...rest
|
||||||
|
}: Props) {
|
||||||
|
const { urlParams } = useUrlParams();
|
||||||
|
const { core } = useApmPluginContext();
|
||||||
|
const location = useLocation();
|
||||||
|
const href = getAPMHref({
|
||||||
|
basePath: core.http.basePath,
|
||||||
|
path: `/services/${serviceName}/transactions/view`,
|
||||||
|
query: {
|
||||||
|
traceId,
|
||||||
|
transactionId,
|
||||||
|
transactionName,
|
||||||
|
transactionType,
|
||||||
|
...(latencyAggregationType ? { latencyAggregationType } : {}),
|
||||||
|
...pickKeys(urlParams as APMQueryParams, ...persistedFilters),
|
||||||
|
},
|
||||||
|
search: location.search,
|
||||||
|
});
|
||||||
|
|
||||||
|
return <EuiLink href={href} {...rest} />;
|
||||||
|
}
|
|
@ -17,13 +17,11 @@ import {
|
||||||
|
|
||||||
const history = createMemoryHistory();
|
const history = createMemoryHistory();
|
||||||
|
|
||||||
function wrapper({ queryParams }: { queryParams?: Record<string, unknown> }) {
|
function Wrapper({ children }: { children: React.ReactElement }) {
|
||||||
return ({ children }: { children: React.ReactElement }) => (
|
return (
|
||||||
<MockApmPluginContextWrapper>
|
<MockApmPluginContextWrapper>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<MockUrlParamsContextProvider params={queryParams}>
|
<MockUrlParamsContextProvider>{children}</MockUrlParamsContextProvider>
|
||||||
{children}
|
|
||||||
</MockUrlParamsContextProvider>
|
|
||||||
</Router>
|
</Router>
|
||||||
</MockApmPluginContextWrapper>
|
</MockApmPluginContextWrapper>
|
||||||
);
|
);
|
||||||
|
@ -32,18 +30,24 @@ function wrapper({ queryParams }: { queryParams?: Record<string, unknown> }) {
|
||||||
describe('Transactions overview link', () => {
|
describe('Transactions overview link', () => {
|
||||||
describe('useTransactionsOverviewHref', () => {
|
describe('useTransactionsOverviewHref', () => {
|
||||||
it('returns transaction link', () => {
|
it('returns transaction link', () => {
|
||||||
const { result } = renderHook(() => useTransactionsOverviewHref('foo'), {
|
const { result } = renderHook(
|
||||||
wrapper: wrapper({}),
|
() => useTransactionsOverviewHref({ serviceName: 'foo' }),
|
||||||
});
|
{ wrapper: Wrapper }
|
||||||
|
);
|
||||||
expect(result.current).toEqual(
|
expect(result.current).toEqual(
|
||||||
'/basepath/app/apm/services/foo/transactions'
|
'/basepath/app/apm/services/foo/transactions'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns transaction link with persisted query items', () => {
|
it('returns transaction link with persisted query items', () => {
|
||||||
const { result } = renderHook(() => useTransactionsOverviewHref('foo'), {
|
const { result } = renderHook(
|
||||||
wrapper: wrapper({ queryParams: { latencyAggregationType: 'avg' } }),
|
() =>
|
||||||
});
|
useTransactionsOverviewHref({
|
||||||
|
serviceName: 'foo',
|
||||||
|
latencyAggregationType: 'avg',
|
||||||
|
}),
|
||||||
|
{ wrapper: Wrapper }
|
||||||
|
);
|
||||||
expect(result.current).toEqual(
|
expect(result.current).toEqual(
|
||||||
'/basepath/app/apm/services/foo/transactions?latencyAggregationType=avg'
|
'/basepath/app/apm/services/foo/transactions?latencyAggregationType=avg'
|
||||||
);
|
);
|
||||||
|
@ -55,13 +59,12 @@ describe('Transactions overview link', () => {
|
||||||
.href;
|
.href;
|
||||||
}
|
}
|
||||||
it('returns transaction link', () => {
|
it('returns transaction link', () => {
|
||||||
const Component = wrapper({});
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Component>
|
<Wrapper>
|
||||||
<TransactionOverviewLink serviceName="foo">
|
<TransactionOverviewLink serviceName="foo">
|
||||||
Service name
|
Service name
|
||||||
</TransactionOverviewLink>
|
</TransactionOverviewLink>
|
||||||
</Component>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
expect(getHref(container)).toEqual(
|
expect(getHref(container)).toEqual(
|
||||||
'http://localhost/basepath/app/apm/services/foo/transactions'
|
'http://localhost/basepath/app/apm/services/foo/transactions'
|
||||||
|
@ -69,15 +72,15 @@ describe('Transactions overview link', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns transaction link with persisted query items', () => {
|
it('returns transaction link with persisted query items', () => {
|
||||||
const Component = wrapper({
|
|
||||||
queryParams: { latencyAggregationType: 'avg' },
|
|
||||||
});
|
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Component>
|
<Wrapper>
|
||||||
<TransactionOverviewLink serviceName="foo">
|
<TransactionOverviewLink
|
||||||
|
serviceName="foo"
|
||||||
|
latencyAggregationType="avg"
|
||||||
|
>
|
||||||
Service name
|
Service name
|
||||||
</TransactionOverviewLink>
|
</TransactionOverviewLink>
|
||||||
</Component>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
expect(getHref(container)).toEqual(
|
expect(getHref(container)).toEqual(
|
||||||
'http://localhost/basepath/app/apm/services/foo/transactions?latencyAggregationType=avg'
|
'http://localhost/basepath/app/apm/services/foo/transactions?latencyAggregationType=avg'
|
||||||
|
|
|
@ -6,22 +6,42 @@
|
||||||
|
|
||||||
import { EuiLink } from '@elastic/eui';
|
import { EuiLink } from '@elastic/eui';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { APMQueryParams } from '../url_helpers';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { APMLinkExtendProps, useAPMHref } from './APMLink';
|
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
|
||||||
|
import { APMLinkExtendProps, getAPMHref } from './APMLink';
|
||||||
|
|
||||||
interface Props extends APMLinkExtendProps {
|
interface Props extends APMLinkExtendProps {
|
||||||
serviceName: string;
|
serviceName: string;
|
||||||
|
latencyAggregationType?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const persistedFilters: Array<keyof APMQueryParams> = [
|
export function useTransactionsOverviewHref({
|
||||||
'latencyAggregationType',
|
serviceName,
|
||||||
];
|
latencyAggregationType,
|
||||||
|
}: {
|
||||||
|
serviceName: string;
|
||||||
|
latencyAggregationType?: string;
|
||||||
|
}) {
|
||||||
|
const { core } = useApmPluginContext();
|
||||||
|
const location = useLocation();
|
||||||
|
const { search } = location;
|
||||||
|
|
||||||
export function useTransactionsOverviewHref(serviceName: string) {
|
return getAPMHref({
|
||||||
return useAPMHref(`/services/${serviceName}/transactions`, persistedFilters);
|
basePath: core.http.basePath,
|
||||||
|
path: `/services/${serviceName}/transactions`,
|
||||||
|
query: { ...(latencyAggregationType ? { latencyAggregationType } : {}) },
|
||||||
|
search,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TransactionOverviewLink({ serviceName, ...rest }: Props) {
|
export function TransactionOverviewLink({
|
||||||
const href = useTransactionsOverviewHref(serviceName);
|
serviceName,
|
||||||
|
latencyAggregationType,
|
||||||
|
...rest
|
||||||
|
}: Props) {
|
||||||
|
const href = useTransactionsOverviewHref({
|
||||||
|
serviceName,
|
||||||
|
latencyAggregationType,
|
||||||
|
});
|
||||||
return <EuiLink href={href} {...rest} />;
|
return <EuiLink href={href} {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import { History } from 'history';
|
import { History } from 'history';
|
||||||
import { parse, stringify } from 'query-string';
|
import { parse, stringify } from 'query-string';
|
||||||
import { LatencyAggregationType } from '../../../../common/latency_aggregation_types';
|
|
||||||
import { url } from '../../../../../../../src/plugins/kibana_utils/public';
|
import { url } from '../../../../../../../src/plugins/kibana_utils/public';
|
||||||
import { LocalUIFilterName } from '../../../../common/ui_filter';
|
import { LocalUIFilterName } from '../../../../common/ui_filter';
|
||||||
|
|
||||||
|
@ -85,7 +84,7 @@ export type APMQueryParams = {
|
||||||
refreshInterval?: string | number;
|
refreshInterval?: string | number;
|
||||||
searchTerm?: string;
|
searchTerm?: string;
|
||||||
percentile?: 50 | 75 | 90 | 95 | 99;
|
percentile?: 50 | 75 | 90 | 95 | 99;
|
||||||
latencyAggregationType?: LatencyAggregationType;
|
latencyAggregationType?: string;
|
||||||
} & { [key in LocalUIFilterName]?: string };
|
} & { [key in LocalUIFilterName]?: string };
|
||||||
|
|
||||||
// forces every value of T[K] to be type: string
|
// forces every value of T[K] to be type: string
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Location } from 'history';
|
import { Location } from 'history';
|
||||||
|
import { LatencyAggregationType } from '../../../common/latency_aggregation_types';
|
||||||
import { pickKeys } from '../../../common/utils/pick_keys';
|
import { pickKeys } from '../../../common/utils/pick_keys';
|
||||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||||
import { localUIFilterNames } from '../../../server/lib/ui_filters/local_ui_filters/config';
|
import { localUIFilterNames } from '../../../server/lib/ui_filters/local_ui_filters/config';
|
||||||
|
@ -48,7 +49,7 @@ export function resolveUrlParams(location: Location, state: TimeUrlParams) {
|
||||||
environment,
|
environment,
|
||||||
searchTerm,
|
searchTerm,
|
||||||
percentile,
|
percentile,
|
||||||
latencyAggregationType,
|
latencyAggregationType = LatencyAggregationType.avg,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
const localUIFilters = pickKeys(query, ...localUIFilterNames);
|
const localUIFilters = pickKeys(query, ...localUIFilterNames);
|
||||||
|
|
|
@ -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;
|
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { LatencyAggregationType } from '../../common/latency_aggregation_types';
|
|
||||||
import { UIFilters } from '../../typings/ui_filters';
|
|
||||||
import { IUrlParams } from '../context/url_params_context/types';
|
|
||||||
import * as urlParams from '../context/url_params_context/use_url_params';
|
|
||||||
import { useLatencyAggregationType } from './use_latency_Aggregation_type';
|
|
||||||
|
|
||||||
describe('useLatencyAggregationType', () => {
|
|
||||||
afterAll(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
it('returns avg when no value was given', () => {
|
|
||||||
jest.spyOn(urlParams, 'useUrlParams').mockReturnValue({
|
|
||||||
urlParams: { latencyAggregationType: undefined } as IUrlParams,
|
|
||||||
refreshTimeRange: jest.fn(),
|
|
||||||
uiFilters: {} as UIFilters,
|
|
||||||
});
|
|
||||||
const latencyAggregationType = useLatencyAggregationType();
|
|
||||||
expect(latencyAggregationType).toEqual(LatencyAggregationType.avg);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns avg when no value does not match any of the availabe options', () => {
|
|
||||||
jest.spyOn(urlParams, 'useUrlParams').mockReturnValue({
|
|
||||||
urlParams: { latencyAggregationType: 'invalid_type' } as IUrlParams,
|
|
||||||
refreshTimeRange: jest.fn(),
|
|
||||||
uiFilters: {} as UIFilters,
|
|
||||||
});
|
|
||||||
const latencyAggregationType = useLatencyAggregationType();
|
|
||||||
expect(latencyAggregationType).toEqual(LatencyAggregationType.avg);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the value in the url', () => {
|
|
||||||
jest.spyOn(urlParams, 'useUrlParams').mockReturnValue({
|
|
||||||
urlParams: { latencyAggregationType: 'p95' } as IUrlParams,
|
|
||||||
refreshTimeRange: jest.fn(),
|
|
||||||
uiFilters: {} as UIFilters,
|
|
||||||
});
|
|
||||||
const latencyAggregationType = useLatencyAggregationType();
|
|
||||||
expect(latencyAggregationType).toEqual(LatencyAggregationType.p95);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,24 +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 { LatencyAggregationType } from '../../common/latency_aggregation_types';
|
|
||||||
import { useUrlParams } from '../context/url_params_context/use_url_params';
|
|
||||||
|
|
||||||
export function useLatencyAggregationType(): LatencyAggregationType {
|
|
||||||
const {
|
|
||||||
urlParams: { latencyAggregationType },
|
|
||||||
} = useUrlParams();
|
|
||||||
|
|
||||||
if (!latencyAggregationType) {
|
|
||||||
return LatencyAggregationType.avg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (latencyAggregationType in LatencyAggregationType) {
|
|
||||||
return latencyAggregationType as LatencyAggregationType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LatencyAggregationType.avg;
|
|
||||||
}
|
|
|
@ -11,15 +11,14 @@ import { useUrlParams } from '../context/url_params_context/use_url_params';
|
||||||
import { useApmServiceContext } from '../context/apm_service/use_apm_service_context';
|
import { useApmServiceContext } from '../context/apm_service/use_apm_service_context';
|
||||||
import { getLatencyChartSelector } from '../selectors/latency_chart_selectors';
|
import { getLatencyChartSelector } from '../selectors/latency_chart_selectors';
|
||||||
import { useTheme } from './use_theme';
|
import { useTheme } from './use_theme';
|
||||||
import { useLatencyAggregationType } from './use_latency_Aggregation_type';
|
import { LatencyAggregationType } from '../../common/latency_aggregation_types';
|
||||||
|
|
||||||
export function useTransactionLatencyChartsFetcher() {
|
export function useTransactionLatencyChartsFetcher() {
|
||||||
const { serviceName } = useParams<{ serviceName?: string }>();
|
const { serviceName } = useParams<{ serviceName?: string }>();
|
||||||
const { transactionType } = useApmServiceContext();
|
const { transactionType } = useApmServiceContext();
|
||||||
const latencyAggregationType = useLatencyAggregationType();
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const {
|
const {
|
||||||
urlParams: { start, end, transactionName },
|
urlParams: { start, end, transactionName, latencyAggregationType },
|
||||||
uiFilters,
|
uiFilters,
|
||||||
} = useUrlParams();
|
} = useUrlParams();
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ export function useTransactionLatencyChartsFetcher() {
|
||||||
transactionType,
|
transactionType,
|
||||||
transactionName,
|
transactionName,
|
||||||
uiFilters: JSON.stringify(uiFilters),
|
uiFilters: JSON.stringify(uiFilters),
|
||||||
latencyAggregationType,
|
latencyAggregationType: latencyAggregationType as LatencyAggregationType,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { rgba } from 'polished';
|
import { rgba } from 'polished';
|
||||||
import { EuiTheme } from '../../../observability/public';
|
import { EuiTheme } from '../../../observability/public';
|
||||||
import { LatencyAggregationType } from '../../common/latency_aggregation_types';
|
|
||||||
import { asDuration } from '../../common/utils/formatters';
|
import { asDuration } from '../../common/utils/formatters';
|
||||||
import {
|
import {
|
||||||
Coordinate,
|
Coordinate,
|
||||||
|
@ -33,7 +32,7 @@ export function getLatencyChartSelector({
|
||||||
}: {
|
}: {
|
||||||
latencyChart?: LatencyChartsResponse;
|
latencyChart?: LatencyChartsResponse;
|
||||||
theme: EuiTheme;
|
theme: EuiTheme;
|
||||||
latencyAggregationType?: LatencyAggregationType;
|
latencyAggregationType?: string;
|
||||||
}): LatencyChart {
|
}): LatencyChart {
|
||||||
if (!latencyChart?.latencyTimeseries || !latencyAggregationType) {
|
if (!latencyChart?.latencyTimeseries || !latencyAggregationType) {
|
||||||
return {
|
return {
|
||||||
|
@ -63,7 +62,7 @@ function getLatencyTimeseries({
|
||||||
}: {
|
}: {
|
||||||
latencyChart: LatencyChartsResponse;
|
latencyChart: LatencyChartsResponse;
|
||||||
theme: EuiTheme;
|
theme: EuiTheme;
|
||||||
latencyAggregationType: LatencyAggregationType;
|
latencyAggregationType: string;
|
||||||
}) {
|
}) {
|
||||||
const { overallAvgDuration } = latencyChart;
|
const { overallAvgDuration } = latencyChart;
|
||||||
const { latencyTimeseries } = latencyChart;
|
const { latencyTimeseries } = latencyChart;
|
||||||
|
|
Loading…
Reference in a new issue