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