mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[APM] Breadcrumbs not updating from service jump on service map (#136144)
* invalidating useEffect to update breadcrumbs * removing useEffect * removing callback function * adding callback * adding usEffect * fixing * adding fnDeps param * addressing pr comments * addressing pr comments
This commit is contained in:
parent
8c844d8b49
commit
bca30a8e6e
12 changed files with 227 additions and 154 deletions
|
@ -979,7 +979,7 @@ module.exports = {
|
||||||
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
||||||
'react-hooks/exhaustive-deps': [
|
'react-hooks/exhaustive-deps': [
|
||||||
'error',
|
'error',
|
||||||
{ additionalHooks: '^(useFetcher|useProgressiveFetcher)$' },
|
{ additionalHooks: '^(useFetcher|useProgressiveFetcher|useBreadcrumb)$' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,10 @@ export const Breadcrumb = ({
|
||||||
children: React.ReactElement;
|
children: React.ReactElement;
|
||||||
}) => {
|
}) => {
|
||||||
const { core } = useApmPluginContext();
|
const { core } = useApmPluginContext();
|
||||||
useBreadcrumb({ title, href: core.http.basePath.prepend('/app/apm' + href) });
|
useBreadcrumb(
|
||||||
|
() => ({ title, href: core.http.basePath.prepend('/app/apm' + href) }),
|
||||||
|
[core.http.basePath, href, title]
|
||||||
|
);
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,26 +30,39 @@ export function DependencyDetailOverview() {
|
||||||
|
|
||||||
const apmRouter = useApmRouter();
|
const apmRouter = useApmRouter();
|
||||||
|
|
||||||
useBreadcrumb([
|
useBreadcrumb(
|
||||||
{
|
() => [
|
||||||
title: i18n.translate(
|
{
|
||||||
'xpack.apm.dependencyDetailOverview.breadcrumbTitle',
|
title: i18n.translate(
|
||||||
{ defaultMessage: 'Overview' }
|
'xpack.apm.dependencyDetailOverview.breadcrumbTitle',
|
||||||
),
|
{ defaultMessage: 'Overview' }
|
||||||
href: apmRouter.link('/dependencies/overview', {
|
),
|
||||||
query: {
|
href: apmRouter.link('/dependencies/overview', {
|
||||||
dependencyName,
|
query: {
|
||||||
rangeFrom,
|
dependencyName,
|
||||||
rangeTo,
|
rangeFrom,
|
||||||
refreshInterval,
|
rangeTo,
|
||||||
refreshPaused,
|
refreshInterval,
|
||||||
environment,
|
refreshPaused,
|
||||||
kuery,
|
environment,
|
||||||
comparisonEnabled,
|
kuery,
|
||||||
},
|
comparisonEnabled,
|
||||||
}),
|
},
|
||||||
},
|
}),
|
||||||
]);
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
apmRouter,
|
||||||
|
comparisonEnabled,
|
||||||
|
dependencyName,
|
||||||
|
environment,
|
||||||
|
kuery,
|
||||||
|
rangeFrom,
|
||||||
|
rangeTo,
|
||||||
|
refreshInterval,
|
||||||
|
refreshPaused,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -31,36 +31,49 @@ export function DependencyDetailView({
|
||||||
|
|
||||||
const apmRouter = useApmRouter();
|
const apmRouter = useApmRouter();
|
||||||
|
|
||||||
useBreadcrumb([
|
useBreadcrumb(
|
||||||
{
|
() => [
|
||||||
title: DependenciesInventoryTitle,
|
{
|
||||||
href: apmRouter.link('/dependencies/inventory', {
|
title: DependenciesInventoryTitle,
|
||||||
query: {
|
href: apmRouter.link('/dependencies/inventory', {
|
||||||
rangeFrom,
|
query: {
|
||||||
rangeTo,
|
rangeFrom,
|
||||||
refreshInterval,
|
rangeTo,
|
||||||
refreshPaused,
|
refreshInterval,
|
||||||
environment,
|
refreshPaused,
|
||||||
kuery,
|
environment,
|
||||||
comparisonEnabled,
|
kuery,
|
||||||
},
|
comparisonEnabled,
|
||||||
}),
|
},
|
||||||
},
|
}),
|
||||||
{
|
},
|
||||||
title: dependencyName,
|
{
|
||||||
href: apmRouter.link('/dependencies', {
|
title: dependencyName,
|
||||||
query: {
|
href: apmRouter.link('/dependencies', {
|
||||||
dependencyName,
|
query: {
|
||||||
rangeFrom,
|
dependencyName,
|
||||||
rangeTo,
|
rangeFrom,
|
||||||
refreshInterval,
|
rangeTo,
|
||||||
refreshPaused,
|
refreshInterval,
|
||||||
environment,
|
refreshPaused,
|
||||||
kuery,
|
environment,
|
||||||
comparisonEnabled,
|
kuery,
|
||||||
},
|
comparisonEnabled,
|
||||||
}),
|
},
|
||||||
},
|
}),
|
||||||
]);
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
apmRouter,
|
||||||
|
comparisonEnabled,
|
||||||
|
dependencyName,
|
||||||
|
environment,
|
||||||
|
kuery,
|
||||||
|
rangeFrom,
|
||||||
|
rangeTo,
|
||||||
|
refreshInterval,
|
||||||
|
refreshPaused,
|
||||||
|
]
|
||||||
|
);
|
||||||
return <DependencyDetailTemplate>{children}</DependencyDetailTemplate>;
|
return <DependencyDetailTemplate>{children}</DependencyDetailTemplate>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,23 +127,36 @@ export function ErrorGroupDetails() {
|
||||||
|
|
||||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||||
|
|
||||||
useBreadcrumb({
|
useBreadcrumb(
|
||||||
title: groupId,
|
() => ({
|
||||||
href: apmRouter.link('/services/{serviceName}/errors/{groupId}', {
|
title: groupId,
|
||||||
path: {
|
href: apmRouter.link('/services/{serviceName}/errors/{groupId}', {
|
||||||
serviceName,
|
path: {
|
||||||
groupId,
|
serviceName,
|
||||||
},
|
groupId,
|
||||||
query: {
|
},
|
||||||
rangeFrom,
|
query: {
|
||||||
rangeTo,
|
rangeFrom,
|
||||||
environment,
|
rangeTo,
|
||||||
kuery,
|
environment,
|
||||||
serviceGroup,
|
kuery,
|
||||||
comparisonEnabled,
|
serviceGroup,
|
||||||
},
|
comparisonEnabled,
|
||||||
|
},
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
[
|
||||||
|
apmRouter,
|
||||||
|
comparisonEnabled,
|
||||||
|
environment,
|
||||||
|
groupId,
|
||||||
|
kuery,
|
||||||
|
rangeFrom,
|
||||||
|
rangeTo,
|
||||||
|
serviceGroup,
|
||||||
|
serviceName,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
const { data: errorGroupData } = useFetcher(
|
const { data: errorGroupData } = useFetcher(
|
||||||
(callApmApi) => {
|
(callApmApi) => {
|
||||||
|
|
|
@ -60,19 +60,22 @@ export function ServiceNodeMetrics() {
|
||||||
|
|
||||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||||
|
|
||||||
useBreadcrumb({
|
useBreadcrumb(
|
||||||
title: getServiceNodeName(serviceNodeName),
|
() => ({
|
||||||
href: apmRouter.link(
|
title: getServiceNodeName(serviceNodeName),
|
||||||
'/services/{serviceName}/nodes/{serviceNodeName}/metrics',
|
href: apmRouter.link(
|
||||||
{
|
'/services/{serviceName}/nodes/{serviceNodeName}/metrics',
|
||||||
path: {
|
{
|
||||||
serviceName,
|
path: {
|
||||||
serviceNodeName,
|
serviceName,
|
||||||
},
|
serviceNodeName,
|
||||||
query,
|
},
|
||||||
}
|
query,
|
||||||
),
|
}
|
||||||
});
|
),
|
||||||
|
}),
|
||||||
|
[apmRouter, query, serviceName, serviceNodeName]
|
||||||
|
);
|
||||||
|
|
||||||
const { data } = useServiceMetricChartsFetcher({
|
const { data } = useServiceMetricChartsFetcher({
|
||||||
serviceNodeName,
|
serviceNodeName,
|
||||||
|
|
|
@ -44,13 +44,16 @@ export function TransactionDetails() {
|
||||||
replace(history, { query: { transactionType } });
|
replace(history, { query: { transactionType } });
|
||||||
}
|
}
|
||||||
|
|
||||||
useBreadcrumb({
|
useBreadcrumb(
|
||||||
title: transactionName,
|
() => ({
|
||||||
href: apmRouter.link('/services/{serviceName}/transactions/view', {
|
title: transactionName,
|
||||||
path,
|
href: apmRouter.link('/services/{serviceName}/transactions/view', {
|
||||||
query,
|
path,
|
||||||
|
query,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
[apmRouter, path, query, transactionName]
|
||||||
|
);
|
||||||
|
|
||||||
const isServerless = isServerlessAgent(runtimeName);
|
const isServerless = isServerlessAgent(runtimeName);
|
||||||
|
|
||||||
|
|
|
@ -19,19 +19,22 @@ export function ApmServiceWrapper() {
|
||||||
|
|
||||||
const router = useApmRouter();
|
const router = useApmRouter();
|
||||||
|
|
||||||
useBreadcrumb([
|
useBreadcrumb(
|
||||||
{
|
() => [
|
||||||
title: ServiceInventoryTitle,
|
{
|
||||||
href: router.link('/services', { query }),
|
title: ServiceInventoryTitle,
|
||||||
},
|
href: router.link('/services', { query }),
|
||||||
{
|
},
|
||||||
title: serviceName,
|
{
|
||||||
href: router.link('/services/{serviceName}', {
|
title: serviceName,
|
||||||
query,
|
href: router.link('/services/{serviceName}', {
|
||||||
path: { serviceName },
|
query,
|
||||||
}),
|
path: { serviceName },
|
||||||
},
|
}),
|
||||||
]);
|
},
|
||||||
|
],
|
||||||
|
[query, router, serviceName]
|
||||||
|
);
|
||||||
|
|
||||||
return <Outlet />;
|
return <Outlet />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,13 +86,16 @@ function TemplateWithContext({
|
||||||
|
|
||||||
const tabs = useTabs({ selectedTab });
|
const tabs = useTabs({ selectedTab });
|
||||||
|
|
||||||
useBreadcrumb({
|
useBreadcrumb(
|
||||||
title,
|
() => ({
|
||||||
href: router.link(`/services/{serviceName}/${selectedTab}` as const, {
|
title,
|
||||||
path: { serviceName },
|
href: router.link(`/services/{serviceName}/${selectedTab}` as const, {
|
||||||
query,
|
path: { serviceName },
|
||||||
|
query,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
[query, router, selectedTab, serviceName, title]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApmMainTemplate
|
<ApmMainTemplate
|
||||||
|
|
|
@ -116,30 +116,33 @@ export function ServiceGroupTemplate({
|
||||||
|
|
||||||
const tabs = useTabs(serviceGroupContextTab);
|
const tabs = useTabs(serviceGroupContextTab);
|
||||||
const selectedTab = tabs?.find(({ isSelected }) => isSelected);
|
const selectedTab = tabs?.find(({ isSelected }) => isSelected);
|
||||||
useBreadcrumb([
|
useBreadcrumb(
|
||||||
{
|
() => [
|
||||||
title: i18n.translate('xpack.apm.serviceGroups.breadcrumb.title', {
|
{
|
||||||
defaultMessage: 'Services',
|
title: i18n.translate('xpack.apm.serviceGroups.breadcrumb.title', {
|
||||||
}),
|
defaultMessage: 'Services',
|
||||||
href: serviceGroupsLink,
|
}),
|
||||||
},
|
href: serviceGroupsLink,
|
||||||
...(selectedTab
|
},
|
||||||
? [
|
...(selectedTab
|
||||||
...(serviceGroupName
|
? [
|
||||||
? [
|
...(serviceGroupName
|
||||||
{
|
? [
|
||||||
title: serviceGroupName,
|
{
|
||||||
href: router.link('/services', { query }),
|
title: serviceGroupName,
|
||||||
},
|
href: router.link('/services', { query }),
|
||||||
]
|
},
|
||||||
: []),
|
]
|
||||||
{
|
: []),
|
||||||
title: selectedTab.label,
|
{
|
||||||
href: selectedTab.href,
|
title: selectedTab.label,
|
||||||
} as { title: string; href: string },
|
href: selectedTab.href,
|
||||||
]
|
} as { title: string; href: string },
|
||||||
: []),
|
]
|
||||||
]);
|
: []),
|
||||||
|
],
|
||||||
|
[query, router, selectedTab, serviceGroupName, serviceGroupsLink]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<ApmMainTemplate
|
<ApmMainTemplate
|
||||||
pageTitle={isServiceGroupsEnabled ? serviceGroupsPageTitle : pageTitle}
|
pageTitle={isServiceGroupsEnabled ? serviceGroupsPageTitle : pageTitle}
|
||||||
|
|
|
@ -10,7 +10,10 @@ import { useContext, useEffect, useRef } from 'react';
|
||||||
import { castArray } from 'lodash';
|
import { castArray } from 'lodash';
|
||||||
import { Breadcrumb, BreadcrumbsContext } from './context';
|
import { Breadcrumb, BreadcrumbsContext } from './context';
|
||||||
|
|
||||||
export function useBreadcrumb(breadcrumb: Breadcrumb | Breadcrumb[]) {
|
export function useBreadcrumb(
|
||||||
|
callback: () => Breadcrumb | Breadcrumb[],
|
||||||
|
fnDeps: any[]
|
||||||
|
) {
|
||||||
const api = useContext(BreadcrumbsContext);
|
const api = useContext(BreadcrumbsContext);
|
||||||
|
|
||||||
if (!api) {
|
if (!api) {
|
||||||
|
@ -29,7 +32,7 @@ export function useBreadcrumb(breadcrumb: Breadcrumb | Breadcrumb[]) {
|
||||||
matchedRoute.current = match?.route;
|
matchedRoute.current = match?.route;
|
||||||
|
|
||||||
if (matchedRoute.current) {
|
if (matchedRoute.current) {
|
||||||
api.set(matchedRoute.current, castArray(breadcrumb));
|
api.set(matchedRoute.current, castArray(callback()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -38,5 +41,5 @@ export function useBreadcrumb(breadcrumb: Breadcrumb | Breadcrumb[]) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, [match, ...fnDeps]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,24 +26,37 @@ export function useDependencyDetailOperationsBreadcrumb() {
|
||||||
|
|
||||||
const apmRouter = useApmRouter();
|
const apmRouter = useApmRouter();
|
||||||
|
|
||||||
useBreadcrumb([
|
useBreadcrumb(
|
||||||
{
|
() => [
|
||||||
title: i18n.translate(
|
{
|
||||||
'xpack.apm.dependencyDetailOperations.breadcrumbTitle',
|
title: i18n.translate(
|
||||||
{ defaultMessage: 'Operations' }
|
'xpack.apm.dependencyDetailOperations.breadcrumbTitle',
|
||||||
),
|
{ defaultMessage: 'Operations' }
|
||||||
href: apmRouter.link('/dependencies/operations', {
|
),
|
||||||
query: {
|
href: apmRouter.link('/dependencies/operations', {
|
||||||
dependencyName,
|
query: {
|
||||||
rangeFrom,
|
dependencyName,
|
||||||
rangeTo,
|
rangeFrom,
|
||||||
refreshInterval,
|
rangeTo,
|
||||||
refreshPaused,
|
refreshInterval,
|
||||||
environment,
|
refreshPaused,
|
||||||
kuery,
|
environment,
|
||||||
comparisonEnabled,
|
kuery,
|
||||||
},
|
comparisonEnabled,
|
||||||
}),
|
},
|
||||||
},
|
}),
|
||||||
]);
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
apmRouter,
|
||||||
|
comparisonEnabled,
|
||||||
|
dependencyName,
|
||||||
|
environment,
|
||||||
|
kuery,
|
||||||
|
rangeFrom,
|
||||||
|
rangeTo,
|
||||||
|
refreshInterval,
|
||||||
|
refreshPaused,
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue