diff --git a/x-pack/plugins/apm/common/environment_filter_values.ts b/x-pack/plugins/apm/common/environment_filter_values.ts index e231f37a170ed..8f5b6456b8c92 100644 --- a/x-pack/plugins/apm/common/environment_filter_values.ts +++ b/x-pack/plugins/apm/common/environment_filter_values.ts @@ -33,3 +33,27 @@ export const ENVIRONMENT_NOT_DEFINED = { export function getEnvironmentLabel(environment: string) { return environmentLabels[environment] || environment; } + +// returns the environment url param that should be used +// based on the requested environment. If the requested +// environment is different from the URL parameter, we'll +// return ENVIRONMENT_ALL. If it's not, we'll just return +// the current environment URL param +export function getNextEnvironmentUrlParam({ + requestedEnvironment, + currentEnvironmentUrlParam, +}: { + requestedEnvironment?: string; + currentEnvironmentUrlParam?: string; +}) { + const normalizedRequestedEnvironment = + requestedEnvironment || ENVIRONMENT_NOT_DEFINED.value; + const normalizedQueryEnvironment = + currentEnvironmentUrlParam || ENVIRONMENT_ALL.value; + + if (normalizedRequestedEnvironment === normalizedQueryEnvironment) { + return currentEnvironmentUrlParam; + } + + return ENVIRONMENT_ALL.value; +} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx index 49a016f338888..fec14ccf76c93 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx @@ -7,6 +7,7 @@ import { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { getNextEnvironmentUrlParam } from '../../../../../common/environment_filter_values'; 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/transaction_detail_link'; @@ -20,8 +21,9 @@ export const MaybeViewTraceLink = ({ waterfall: IWaterfall; }) => { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); + const viewFullTraceButtonLabel = i18n.translate( 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', { @@ -73,6 +75,11 @@ export const MaybeViewTraceLink = ({ // the user is viewing a zoomed in version of the trace. Link to the full trace } else { + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: rootTransaction?.service.environment, + currentEnvironmentUrlParam: environment, + }); + return ( {viewFullTraceButtonLabel} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx index a67ec0a69ed87..6b6d54b6cbad6 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useUrlParams } from '../../../../../../context/url_params_context/use_url_params'; +import { getNextEnvironmentUrlParam } from '../../../../../../../common/environment_filter_values'; import { SERVICE_NAME, TRANSACTION_NAME, @@ -22,13 +23,18 @@ interface Props { export function FlyoutTopLevelProperties({ transaction }: Props) { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); if (!transaction) { return null; } + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: transaction.service.environment, + currentEnvironmentUrlParam: environment, + }); + const stickyProperties = [ { label: i18n.translate('xpack.apm.transactionDetails.serviceLabel', { @@ -38,6 +44,7 @@ export function FlyoutTopLevelProperties({ transaction }: Props) { val: ( {transaction.service.name} @@ -56,6 +63,7 @@ export function FlyoutTopLevelProperties({ transaction }: Props) { traceId={transaction.trace.id} transactionName={transaction.transaction.name} transactionType={transaction.transaction.type} + environment={nextEnvironment} latencyAggregationType={latencyAggregationType} > {transaction.transaction.name} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx index 5a1f6e3d2a24d..82b43b3dce99a 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useUrlParams } from '../../../../../../../context/url_params_context/use_url_params'; +import { getNextEnvironmentUrlParam } from '../../../../../../../../common/environment_filter_values'; import { SERVICE_NAME, SPAN_NAME, @@ -26,8 +27,14 @@ interface Props { export function StickySpanProperties({ span, transaction }: Props) { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); + + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: transaction?.service.environment, + currentEnvironmentUrlParam: environment, + }); + const spanName = span.span.name; const transactionStickyProperties = transaction ? [ @@ -39,6 +46,7 @@ export function StickySpanProperties({ span, transaction }: Props) { val: ( {transaction.service.name} @@ -60,6 +68,7 @@ export function StickySpanProperties({ span, transaction }: Props) { traceId={transaction.trace.id} transactionName={transaction.transaction.name} transactionType={transaction.transaction.type} + environment={nextEnvironment} latencyAggregationType={latencyAggregationType} > {transaction.transaction.name} diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index 079c599f8f7ba..1bd7310e3251d 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -13,7 +13,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; +import { + ENVIRONMENT_ALL, + getNextEnvironmentUrlParam, +} from '../../../../../common/environment_filter_values'; import { asMillisecondDuration, asPercent, @@ -40,6 +43,10 @@ interface Props { } export function ServiceOverviewDependenciesTable({ serviceName }: Props) { + const { + urlParams: { start, end, environment }, + } = useUrlParams(); + const columns: Array> = [ { field: 'name', @@ -64,7 +71,13 @@ export function ServiceOverviewDependenciesTable({ serviceName }: Props) { {item.type === 'service' ? ( - + {item.name} ) : ( @@ -154,10 +167,6 @@ export function ServiceOverviewDependenciesTable({ serviceName }: Props) { }, ]; - const { - urlParams: { start, end, environment }, - } = useUrlParams(); - const { data = [], status } = useFetcher(() => { if (!start || !end) { return; diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx index 7acc2542a65f3..fe5bfc6c4679b 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx @@ -36,16 +36,24 @@ export const PERSISTENT_APM_PARAMS: Array = [ /** * Hook to get a link for a path with persisted filters */ -export function useAPMHref( - path: string, - persistentFilters: Array = [] -) { +export function useAPMHref({ + path, + persistedFilters, + query, +}: { + path: string; + persistedFilters?: Array; + query?: APMQueryParams; +}) { const { urlParams } = useUrlParams(); const { basePath } = useApmPluginContext().core.http; const { search } = useLocation(); - const query = pickKeys(urlParams as APMQueryParams, ...persistentFilters); + const nextQuery = { + ...pickKeys(urlParams as APMQueryParams, ...(persistedFilters ?? [])), + ...query, + }; - return getAPMHref({ basePath, path, query, search }); + return getAPMHref({ basePath, path, query: nextQuery, search }); } /** diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx index dcf21de7dca8d..506787c0fe62f 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx @@ -17,7 +17,10 @@ const persistedFilters: Array = [ ]; export function useErrorOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/errors`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/errors`, + persistedFilters, + }); } interface Props extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx index 8031b6088d420..e369e920a4b82 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx @@ -16,7 +16,10 @@ const persistedFilters: Array = [ ]; export function useMetricOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/metrics`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/metrics`, + persistedFilters, + }); } interface Props extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx index 670b7137219e1..b5b74f06d65ba 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx @@ -8,10 +8,10 @@ import React from 'react'; import { APMLinkExtendProps, useAPMHref } from './APMLink'; export function useServiceMapHref(serviceName?: string) { - const pathFor = serviceName + const path = serviceName ? `/services/${serviceName}/service-map` : '/service-map'; - return useAPMHref(pathFor); + return useAPMHref({ path }); } interface ServiceMapLinkProps extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx index 279c038d95a80..b2382ef99e982 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx @@ -14,5 +14,8 @@ const persistedFilters: Array = [ ]; export function useServiceNodeOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/nodes`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/nodes`, + persistedFilters, + }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx index 3cb0009a12c94..a5f7b3f2b28e4 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx @@ -20,5 +20,5 @@ const persistedFilters: Array = [ ]; export function useTraceOverviewHref() { - return useAPMHref('/traces', persistedFilters); + return useAPMHref({ path: '/traces', persistedFilters }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx index c3b80cbeb701b..1d879f86dff3d 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx @@ -15,5 +15,5 @@ import { useAPMHref } from './APMLink'; const persistedFilters: Array = ['host', 'agentName']; export function useServiceInventoryHref() { - return useAPMHref('/services', persistedFilters); + return useAPMHref({ path: '/services', persistedFilters }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx index ba53243a6bc75..31ce04cf23fbc 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx @@ -15,20 +15,34 @@ import { APMLinkExtendProps, useAPMHref } from './APMLink'; interface ServiceOverviewLinkProps extends APMLinkExtendProps { serviceName: string; + environment?: string; } const persistedFilters: Array = [ 'latencyAggregationType', ]; -export function useServiceOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/overview`, persistedFilters); +export function useServiceOverviewHref( + serviceName: string, + environment?: string +) { + const query = environment + ? { + environment, + } + : {}; + return useAPMHref({ + path: `/services/${serviceName}/overview`, + persistedFilters, + query, + }); } export function ServiceOverviewLink({ serviceName, + environment, ...rest }: ServiceOverviewLinkProps) { - const href = useServiceOverviewHref(serviceName); + const href = useServiceOverviewHref(serviceName, environment); return ; } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx index 8b96ba8ab233a..c4ea99030d87c 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx @@ -17,18 +17,28 @@ const persistedFilters: Array = [ 'latencyAggregationType', ]; -export function useServiceOrTransactionsOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}`, persistedFilters); +export function useServiceOrTransactionsOverviewHref( + serviceName: string, + environment?: string +) { + const query = environment ? { environment } : {}; + return useAPMHref({ + path: `/services/${serviceName}`, + persistedFilters, + query, + }); } interface Props extends APMLinkExtendProps { serviceName: string; + environment?: string; } export function ServiceOrTransactionsOverviewLink({ serviceName, + environment, ...rest }: Props) { - const href = useServiceOrTransactionsOverviewHref(serviceName); + const href = useServiceOrTransactionsOverviewHref(serviceName, environment); return ; } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx index 8108dcf41321f..a97d860d99798 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; import { EuiLink } from '@elastic/eui'; +import { pickBy, identity } from 'lodash'; import { getAPMHref, APMLinkExtendProps } from './APMLink'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { pickKeys } from '../../../../../common/utils/pick_keys'; @@ -20,6 +21,7 @@ interface Props extends APMLinkExtendProps { transactionName: string; transactionType: string; latencyAggregationType?: string; + environment?: string; } const persistedFilters: Array = [ @@ -34,6 +36,7 @@ export function TransactionDetailLink({ transactionName, transactionType, latencyAggregationType, + environment, ...rest }: Props) { const { urlParams } = useUrlParams(); @@ -47,8 +50,8 @@ export function TransactionDetailLink({ transactionId, transactionName, transactionType, - ...(latencyAggregationType ? { latencyAggregationType } : {}), ...pickKeys(urlParams as APMQueryParams, ...persistedFilters), + ...pickBy({ latencyAggregationType, environment }, identity), }, search: location.search, }); diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts b/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts index e152ed23af1b3..3938a9b54d913 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts @@ -18,6 +18,7 @@ export interface SpanRaw extends APMBaseDoc { trace: { id: string }; // trace is required service: { name: string; + environment?: string; }; span: { destination?: {