mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[APM] Rename backends to dependencies in URLs and APIs (#136330)
* renaming api endpoints * renaming route functions * GET /internal/apm/dependencies/top_dependencies * GET /internal/apm/dependencies/upstream_services * server changes * renaming route params * refactoring * refactoring client * refactogin client * refactoring routes * fixing redirection * refactoring component * renaming nodetype * renaming backend link * backend template * renaming backends operations * dependency operation * DependencyMetricCharts * DependencyMetricCharts * DependencyOperationDetailView * DependencyDetailOverview * remaining * updating tests and i18n
This commit is contained in:
parent
aea46fd372
commit
031729e81a
75 changed files with 1060 additions and 998 deletions
|
@ -9,7 +9,7 @@ import { Coordinate } from '../typings/timeseries';
|
|||
|
||||
export enum NodeType {
|
||||
service = 'service',
|
||||
backend = 'backend',
|
||||
dependency = 'dependency',
|
||||
}
|
||||
|
||||
interface NodeBase {
|
||||
|
@ -23,14 +23,14 @@ export interface ServiceNode extends NodeBase {
|
|||
environment: string;
|
||||
}
|
||||
|
||||
export interface BackendNode extends NodeBase {
|
||||
type: NodeType.backend;
|
||||
backendName: string;
|
||||
export interface DependencyNode extends NodeBase {
|
||||
type: NodeType.dependency;
|
||||
dependencyName: string;
|
||||
spanType: string;
|
||||
spanSubtype: string;
|
||||
}
|
||||
|
||||
export type Node = ServiceNode | BackendNode;
|
||||
export type Node = ServiceNode | DependencyNode;
|
||||
|
||||
export interface ConnectionStatsItem {
|
||||
location: Node;
|
||||
|
@ -67,5 +67,7 @@ export interface ConnectionStatsItemWithComparisonData {
|
|||
}
|
||||
|
||||
export function getNodeName(node: Node) {
|
||||
return node.type === NodeType.service ? node.serviceName : node.backendName;
|
||||
return node.type === NodeType.service
|
||||
? node.serviceName
|
||||
: node.dependencyName;
|
||||
}
|
||||
|
|
|
@ -21,17 +21,17 @@ export const kueryBarPlaceholder = i18n.translate(
|
|||
);
|
||||
|
||||
export const getKueryBarBoolFilter = ({
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment,
|
||||
}: {
|
||||
backendName?: string;
|
||||
dependencyName?: string;
|
||||
environment: string;
|
||||
}) => {
|
||||
return [
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.metric } },
|
||||
{ exists: { field: SPAN_DESTINATION_SERVICE_RESOURCE } },
|
||||
...(backendName
|
||||
? [{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } }]
|
||||
...(dependencyName
|
||||
? [{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName } }]
|
||||
: []),
|
||||
...environmentQuery(environment),
|
||||
];
|
|
@ -49,7 +49,7 @@ describe('Comparison feature flag', () => {
|
|||
});
|
||||
|
||||
it('shows the comparison feature enabled in services overview', () => {
|
||||
cy.visit('/app/apm/backends');
|
||||
cy.visit('/app/apm/dependencies');
|
||||
cy.get('input[type="checkbox"]#comparison').should('be.checked');
|
||||
cy.get('[data-test-subj="comparisonSelect"]').should('not.be.disabled');
|
||||
});
|
||||
|
@ -89,7 +89,7 @@ describe('Comparison feature flag', () => {
|
|||
});
|
||||
|
||||
it('shows the comparison feature disabled in dependencies overview page', () => {
|
||||
cy.visit('/app/apm/backends');
|
||||
cy.visit('/app/apm/dependencies');
|
||||
cy.get('input[type="checkbox"]#comparison').should('not.be.checked');
|
||||
cy.get('[data-test-subj="comparisonSelect"]').should('be.disabled');
|
||||
});
|
||||
|
|
|
@ -60,9 +60,9 @@ describe('Dependencies', () => {
|
|||
describe.skip('dependency overview page', () => {
|
||||
it('shows dependency information and you can navigate to a page for an upstream service', () => {
|
||||
cy.visit(
|
||||
`/app/apm/backends/overview?${new URLSearchParams({
|
||||
`/app/apm/dependencies/overview?${new URLSearchParams({
|
||||
...timeRange,
|
||||
backendName: 'postgresql',
|
||||
dependencyName: 'postgresql',
|
||||
})}`
|
||||
);
|
||||
|
||||
|
@ -77,9 +77,9 @@ describe('Dependencies', () => {
|
|||
|
||||
it('has no detectable a11y violations on load', () => {
|
||||
cy.visit(
|
||||
`/app/apm/backends/overview?${new URLSearchParams({
|
||||
`/app/apm/dependencies/overview?${new URLSearchParams({
|
||||
...timeRange,
|
||||
backendName: 'postgresql',
|
||||
dependencyName: 'postgresql',
|
||||
})}`
|
||||
);
|
||||
cy.contains('h1', 'postgresql');
|
||||
|
|
|
@ -1,16 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useBackendDetailOperationsBreadcrumb } from '../../../hooks/use_backend_detail_operations_breadcrumb';
|
||||
import { BackendDetailOperationsList } from './backend_detail_operations_list';
|
||||
|
||||
export function BackendDetailOperations() {
|
||||
useBackendDetailOperationsBreadcrumb();
|
||||
|
||||
return <BackendDetailOperationsList />;
|
||||
}
|
|
@ -14,10 +14,10 @@ import { getNodeName, NodeType } from '../../../../../common/connections';
|
|||
import { useApmParams } from '../../../../hooks/use_apm_params';
|
||||
import { useFetcher } from '../../../../hooks/use_fetcher';
|
||||
import { useTimeRange } from '../../../../hooks/use_time_range';
|
||||
import { BackendLink } from '../../../shared/backend_link';
|
||||
import { DependencyLink } from '../../../shared/dependency_link';
|
||||
import { DependenciesTable } from '../../../shared/dependencies_table';
|
||||
|
||||
export function BackendInventoryDependenciesTable() {
|
||||
export function DependenciesInventoryTable() {
|
||||
const {
|
||||
query: {
|
||||
rangeFrom,
|
||||
|
@ -27,7 +27,7 @@ export function BackendInventoryDependenciesTable() {
|
|||
comparisonEnabled,
|
||||
offset,
|
||||
},
|
||||
} = useApmParams('/backends/inventory');
|
||||
} = useApmParams('/dependencies/inventory');
|
||||
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
|
@ -39,7 +39,7 @@ export function BackendInventoryDependenciesTable() {
|
|||
return;
|
||||
}
|
||||
|
||||
return callApmApi('GET /internal/apm/backends/top_backends', {
|
||||
return callApmApi('GET /internal/apm/dependencies/top_dependencies', {
|
||||
params: {
|
||||
query: {
|
||||
start,
|
||||
|
@ -59,19 +59,19 @@ export function BackendInventoryDependenciesTable() {
|
|||
);
|
||||
|
||||
const dependencies =
|
||||
data?.backends.map((dependency) => {
|
||||
data?.dependencies.map((dependency) => {
|
||||
const { location } = dependency;
|
||||
const name = getNodeName(location);
|
||||
|
||||
if (location.type !== NodeType.backend) {
|
||||
throw new Error('Expected a backend node');
|
||||
if (location.type !== NodeType.dependency) {
|
||||
throw new Error('Expected a dependency node');
|
||||
}
|
||||
const link = (
|
||||
<BackendLink
|
||||
<DependencyLink
|
||||
type={location.spanType}
|
||||
subtype={location.spanSubtype}
|
||||
query={{
|
||||
backendName: location.backendName,
|
||||
dependencyName: location.dependencyName,
|
||||
comparisonEnabled,
|
||||
offset,
|
||||
environment,
|
||||
|
@ -83,7 +83,7 @@ export function BackendInventoryDependenciesTable() {
|
|||
trackEvent({
|
||||
app: 'apm',
|
||||
metricType: METRIC_TYPE.CLICK,
|
||||
metric: 'backend_inventory_to_backend_detail',
|
||||
metric: 'dependencies_inventory_to_dependency_detail',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
@ -102,7 +102,7 @@ export function BackendInventoryDependenciesTable() {
|
|||
dependencies={dependencies}
|
||||
title={null}
|
||||
nameColumnTitle={i18n.translate(
|
||||
'xpack.apm.backendInventory.dependencyTableColumn',
|
||||
'xpack.apm.dependenciesInventory.dependencyTableColumn',
|
||||
{
|
||||
defaultMessage: 'Dependency',
|
||||
}
|
|
@ -10,15 +10,15 @@ import React from 'react';
|
|||
import {
|
||||
getKueryBarBoolFilter,
|
||||
kueryBarPlaceholder,
|
||||
} from '../../../../common/backends';
|
||||
} from '../../../../common/dependencies';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
import { SearchBar } from '../../shared/search_bar';
|
||||
import { BackendInventoryDependenciesTable } from './backend_inventory_dependencies_table';
|
||||
import { DependenciesInventoryTable } from './dependencies_inventory_table';
|
||||
|
||||
export function BackendInventory() {
|
||||
export function DependenciesInventory() {
|
||||
const {
|
||||
query: { environment },
|
||||
} = useApmParams('/backends/inventory');
|
||||
} = useApmParams('/dependencies/inventory');
|
||||
const kueryBarBoolFilter = getKueryBarBoolFilter({
|
||||
environment,
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ export function BackendInventory() {
|
|||
kueryBarBoolFilter={kueryBarBoolFilter}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
<BackendInventoryDependenciesTable />
|
||||
<DependenciesInventoryTable />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -21,36 +21,36 @@ import { EmptyMessage } from '../../../shared/empty_message';
|
|||
import { ITableColumn, ManagedTable } from '../../../shared/managed_table';
|
||||
import { getComparisonEnabled } from '../../../shared/time_comparison/get_comparison_enabled';
|
||||
import { TruncateWithTooltip } from '../../../shared/truncate_with_tooltip';
|
||||
import { BackendOperationDetailLink } from '../../backend_operation_detail_view/backend_operation_detail_link';
|
||||
import { DependencyOperationDetailLink } from '../../dependency_operation_detail_view/dependency_operation_detail_link';
|
||||
|
||||
interface OperationStatisticsItem extends SpanMetricGroup {
|
||||
spanName: string;
|
||||
}
|
||||
|
||||
function OperationLink({ spanName }: { spanName: string }) {
|
||||
const { query } = useApmParams('/backends/operations');
|
||||
const { query } = useApmParams('/dependencies/operations');
|
||||
|
||||
return (
|
||||
<TruncateWithTooltip
|
||||
data-test-subj="apmOperationsListAppLink"
|
||||
text={spanName}
|
||||
content={<BackendOperationDetailLink {...query} spanName={spanName} />}
|
||||
content={<DependencyOperationDetailLink {...query} spanName={spanName} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function BackendDetailOperationsList() {
|
||||
export function DependencyDetailOperationsList() {
|
||||
const {
|
||||
query: {
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment,
|
||||
kuery,
|
||||
comparisonEnabled: urlComparisonEnabled,
|
||||
offset,
|
||||
},
|
||||
} = useApmParams('/backends/operations');
|
||||
} = useApmParams('/dependencies/operations');
|
||||
|
||||
const { core } = useApmPluginContext();
|
||||
|
||||
|
@ -68,10 +68,10 @@ export function BackendDetailOperationsList() {
|
|||
|
||||
const primaryStatsFetch = useFetcher(
|
||||
(callApmApi) => {
|
||||
return callApmApi('GET /internal/apm/backends/operations', {
|
||||
return callApmApi('GET /internal/apm/dependencies/operations', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
environment,
|
||||
|
@ -80,7 +80,7 @@ export function BackendDetailOperationsList() {
|
|||
},
|
||||
});
|
||||
},
|
||||
[backendName, start, end, environment, kuery]
|
||||
[dependencyName, start, end, environment, kuery]
|
||||
);
|
||||
|
||||
const comparisonStatsFetch = useFetcher(
|
||||
|
@ -90,10 +90,10 @@ export function BackendDetailOperationsList() {
|
|||
operations: [],
|
||||
});
|
||||
}
|
||||
return callApmApi('GET /internal/apm/backends/operations', {
|
||||
return callApmApi('GET /internal/apm/dependencies/operations', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -103,16 +103,14 @@ export function BackendDetailOperationsList() {
|
|||
},
|
||||
});
|
||||
},
|
||||
[backendName, start, end, offset, environment, kuery, comparisonEnabled]
|
||||
[dependencyName, start, end, offset, environment, kuery, comparisonEnabled]
|
||||
);
|
||||
|
||||
const columns: Array<ITableColumn<OperationStatisticsItem>> = [
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendDetailOperationsList.spanNameColumnLabel',
|
||||
{
|
||||
defaultMessage: 'Span name',
|
||||
}
|
||||
'xpack.apm.dependencyDetailOperationsList.spanNameColumnLabel',
|
||||
{ defaultMessage: 'Span name' }
|
||||
),
|
||||
field: 'spanName',
|
||||
sortable: true,
|
||||
|
@ -132,10 +130,8 @@ export function BackendDetailOperationsList() {
|
|||
const noItemsMessage = (
|
||||
<EmptyMessage
|
||||
heading={i18n.translate(
|
||||
'xpack.apm.backendDetailOperationsList.notFoundLabel',
|
||||
{
|
||||
defaultMessage: 'No operations found',
|
||||
}
|
||||
'xpack.apm.dependencyDetailOperationsList.notFoundLabel',
|
||||
{ defaultMessage: 'No operations found' }
|
||||
)}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useDependencyDetailOperationsBreadcrumb } from '../../../hooks/use_dependency_detail_operations_breadcrumb';
|
||||
import { DependencyDetailOperationsList } from './dependency_detail_operations_list';
|
||||
|
||||
export function DependencyDetailOperations() {
|
||||
useDependencyDetailOperationsBreadcrumb();
|
||||
|
||||
return <DependencyDetailOperationsList />;
|
||||
}
|
|
@ -17,10 +17,10 @@ import { useTimeRange } from '../../../hooks/use_time_range';
|
|||
import { getComparisonEnabled } from '../../shared/time_comparison/get_comparison_enabled';
|
||||
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
|
||||
|
||||
export function BackendDetailDependenciesTable() {
|
||||
export function DependenciesDetailTable() {
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
|
@ -28,7 +28,7 @@ export function BackendDetailDependenciesTable() {
|
|||
comparisonEnabled: urlComparisonEnabled,
|
||||
offset,
|
||||
},
|
||||
} = useApmParams('/backends/overview');
|
||||
} = useApmParams('/dependencies/overview');
|
||||
|
||||
const { core } = useApmPluginContext();
|
||||
|
||||
|
@ -41,10 +41,10 @@ export function BackendDetailDependenciesTable() {
|
|||
|
||||
const { data, status } = useFetcher(
|
||||
(callApmApi) => {
|
||||
return callApmApi('GET /internal/apm/backends/upstream_services', {
|
||||
return callApmApi('GET /internal/apm/dependencies/upstream_services', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
environment,
|
||||
|
@ -58,7 +58,7 @@ export function BackendDetailDependenciesTable() {
|
|||
},
|
||||
});
|
||||
},
|
||||
[start, end, environment, offset, backendName, kuery, comparisonEnabled]
|
||||
[start, end, environment, offset, dependencyName, kuery, comparisonEnabled]
|
||||
);
|
||||
|
||||
const dependencies =
|
||||
|
@ -97,14 +97,13 @@ export function BackendDetailDependenciesTable() {
|
|||
return (
|
||||
<DependenciesTable
|
||||
dependencies={dependencies}
|
||||
title={i18n.translate('xpack.apm.backendDetail.dependenciesTableTitle', {
|
||||
defaultMessage: 'Upstream services',
|
||||
})}
|
||||
title={i18n.translate(
|
||||
'xpack.apm.dependencyDetail.dependenciesTableTitle',
|
||||
{ defaultMessage: 'Upstream services' }
|
||||
)}
|
||||
nameColumnTitle={i18n.translate(
|
||||
'xpack.apm.backendDetail.dependenciesTableColumnBackend',
|
||||
{
|
||||
defaultMessage: 'Service',
|
||||
}
|
||||
'xpack.apm.dependencyDetail.dependenciesTableColumn',
|
||||
{ defaultMessage: 'Service' }
|
||||
)}
|
||||
status={status}
|
||||
compact={false}
|
|
@ -11,13 +11,13 @@ import { useBreadcrumb } from '../../../context/breadcrumbs/use_breadcrumb';
|
|||
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
import { useApmRouter } from '../../../hooks/use_apm_router';
|
||||
import { BackendDetailDependenciesTable } from './backend_detail_dependencies_table';
|
||||
import { BackendMetricCharts } from '../../shared/backend_metric_charts';
|
||||
import { DependenciesDetailTable } from './dependencies_detail_table';
|
||||
import { DependencyMetricCharts } from '../../shared/dependency_metric_charts';
|
||||
|
||||
export function BackendDetailOverview() {
|
||||
export function DependencyDetailOverview() {
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
||||
|
@ -26,18 +26,19 @@ export function BackendDetailOverview() {
|
|||
kuery,
|
||||
comparisonEnabled,
|
||||
},
|
||||
} = useApmParams('/backends/overview');
|
||||
} = useApmParams('/dependencies/overview');
|
||||
|
||||
const apmRouter = useApmRouter();
|
||||
|
||||
useBreadcrumb([
|
||||
{
|
||||
title: i18n.translate('xpack.apm.backendDetailOverview.breadcrumbTitle', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
href: apmRouter.link('/backends/overview', {
|
||||
title: i18n.translate(
|
||||
'xpack.apm.dependencyDetailOverview.breadcrumbTitle',
|
||||
{ defaultMessage: 'Overview' }
|
||||
),
|
||||
href: apmRouter.link('/dependencies/overview', {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
||||
|
@ -53,10 +54,10 @@ export function BackendDetailOverview() {
|
|||
return (
|
||||
<>
|
||||
<ChartPointerEventContextProvider>
|
||||
<BackendMetricCharts />
|
||||
<DependencyMetricCharts />
|
||||
</ChartPointerEventContextProvider>
|
||||
<EuiSpacer size="l" />
|
||||
<BackendDetailDependenciesTable />
|
||||
<DependenciesDetailTable />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -8,17 +8,17 @@ import React from 'react';
|
|||
import { useBreadcrumb } from '../../../context/breadcrumbs/use_breadcrumb';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
import { useApmRouter } from '../../../hooks/use_apm_router';
|
||||
import { DependenciesInventoryTitle } from '../../routing/home';
|
||||
import { BackendDetailTemplate } from '../../routing/templates/backend_detail_template';
|
||||
import { DependenciesInventoryTitle } from '../../routing/home/dependencies';
|
||||
import { DependencyDetailTemplate } from '../../routing/templates/dependency_detail_template';
|
||||
|
||||
export function BackendDetailView({
|
||||
export function DependencyDetailView({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactChild;
|
||||
}) {
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
||||
|
@ -27,14 +27,14 @@ export function BackendDetailView({
|
|||
kuery,
|
||||
comparisonEnabled,
|
||||
},
|
||||
} = useApmParams('/backends');
|
||||
} = useApmParams('/dependencies');
|
||||
|
||||
const apmRouter = useApmRouter();
|
||||
|
||||
useBreadcrumb([
|
||||
{
|
||||
title: DependenciesInventoryTitle,
|
||||
href: apmRouter.link('/backends/inventory', {
|
||||
href: apmRouter.link('/dependencies/inventory', {
|
||||
query: {
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
|
@ -47,10 +47,10 @@ export function BackendDetailView({
|
|||
}),
|
||||
},
|
||||
{
|
||||
title: backendName,
|
||||
href: apmRouter.link('/backends', {
|
||||
title: dependencyName,
|
||||
href: apmRouter.link('/dependencies', {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
||||
|
@ -62,6 +62,5 @@ export function BackendDetailView({
|
|||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
return <BackendDetailTemplate>{children}</BackendDetailTemplate>;
|
||||
return <DependencyDetailTemplate>{children}</DependencyDetailTemplate>;
|
||||
}
|
|
@ -10,14 +10,14 @@ import { TypeOf } from '@kbn/typed-react-router-config';
|
|||
import { useApmRouter } from '../../../hooks/use_apm_router';
|
||||
import { ApmRoutes } from '../../routing/apm_route_config';
|
||||
|
||||
type Query = TypeOf<ApmRoutes, '/backends/operation'>['query'];
|
||||
type Query = TypeOf<ApmRoutes, '/dependencies/operation'>['query'];
|
||||
|
||||
export function BackendOperationDetailLink(query: Query) {
|
||||
export function DependencyOperationDetailLink(query: Query) {
|
||||
const router = useApmRouter();
|
||||
|
||||
const { spanName } = query;
|
||||
|
||||
const link = router.link('/backends/operation', {
|
||||
const link = router.link('/dependencies/operation', {
|
||||
query,
|
||||
});
|
||||
|
|
@ -28,18 +28,18 @@ import { ITableColumn, ManagedTable } from '../../shared/managed_table';
|
|||
import { ServiceLink } from '../../shared/service_link';
|
||||
import { TimestampTooltip } from '../../shared/timestamp_tooltip';
|
||||
|
||||
type BackendSpan = ValuesType<
|
||||
APIReturnType<'GET /internal/apm/backends/operations/spans'>['spans']
|
||||
type DependencySpan = ValuesType<
|
||||
APIReturnType<'GET /internal/apm/dependencies/operations/spans'>['spans']
|
||||
>;
|
||||
|
||||
export function BackendOperationDetailTraceList() {
|
||||
export function DependencyOperationDetailTraceList() {
|
||||
const router = useApmRouter();
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
comparisonEnabled,
|
||||
environment,
|
||||
|
@ -52,7 +52,7 @@ export function BackendOperationDetailTraceList() {
|
|||
sampleRangeFrom,
|
||||
sampleRangeTo,
|
||||
},
|
||||
} = useApmParams('/backends/operation');
|
||||
} = useApmParams('/dependencies/operation');
|
||||
|
||||
function getTraceLink({
|
||||
transactionName,
|
||||
|
@ -101,10 +101,10 @@ export function BackendOperationDetailTraceList() {
|
|||
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
const columns: Array<ITableColumn<BackendSpan>> = [
|
||||
const columns: Array<ITableColumn<DependencySpan>> = [
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListOutcomeColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListOutcomeColumn',
|
||||
{ defaultMessage: 'Outcome' }
|
||||
),
|
||||
field: 'outcome',
|
||||
|
@ -123,7 +123,7 @@ export function BackendOperationDetailTraceList() {
|
|||
},
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListTraceIdColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListTraceIdColumn',
|
||||
{ defaultMessage: 'Trace' }
|
||||
),
|
||||
field: 'traceId',
|
||||
|
@ -154,7 +154,7 @@ export function BackendOperationDetailTraceList() {
|
|||
},
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListServiceNameColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListServiceNameColumn',
|
||||
{ defaultMessage: 'Originating service' }
|
||||
),
|
||||
field: 'serviceName',
|
||||
|
@ -183,7 +183,7 @@ export function BackendOperationDetailTraceList() {
|
|||
},
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListTransactionNameColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListTransactionNameColumn',
|
||||
{ defaultMessage: 'Transaction name' }
|
||||
),
|
||||
field: 'transactionName',
|
||||
|
@ -211,7 +211,7 @@ export function BackendOperationDetailTraceList() {
|
|||
},
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListDurationColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListDurationColumn',
|
||||
{ defaultMessage: 'Duration' }
|
||||
),
|
||||
field: 'duration',
|
||||
|
@ -223,7 +223,7 @@ export function BackendOperationDetailTraceList() {
|
|||
},
|
||||
{
|
||||
name: i18n.translate(
|
||||
'xpack.apm.backendOperationDetailTraceListTimestampColumn',
|
||||
'xpack.apm.dependencyOperationDetailTraceListTimestampColumn',
|
||||
{ defaultMessage: 'Timestamp' }
|
||||
),
|
||||
field: '@timestamp',
|
||||
|
@ -237,10 +237,10 @@ export function BackendOperationDetailTraceList() {
|
|||
|
||||
const { data = { spans: [] }, status } = useFetcher(
|
||||
(callApmApi) => {
|
||||
return callApmApi('GET /internal/apm/backends/operations/spans', {
|
||||
return callApmApi('GET /internal/apm/dependencies/operations/spans', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
start,
|
||||
end,
|
||||
|
@ -253,7 +253,7 @@ export function BackendOperationDetailTraceList() {
|
|||
});
|
||||
},
|
||||
[
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
start,
|
||||
end,
|
||||
|
@ -269,7 +269,7 @@ export function BackendOperationDetailTraceList() {
|
|||
<EuiFlexItem>
|
||||
<EuiTitle size="xxs">
|
||||
<EuiText>
|
||||
{i18n.translate('xpack.apm.backendOperationDetailTraceList', {
|
||||
{i18n.translate('xpack.apm.dependencyOperationDetailTraceList', {
|
||||
defaultMessage: 'Traces',
|
||||
})}
|
||||
</EuiText>
|
|
@ -16,18 +16,18 @@ import { useTimeRange } from '../../../hooks/use_time_range';
|
|||
import { DurationDistributionChartData } from '../../shared/charts/duration_distribution_chart';
|
||||
import { DurationDistributionChartWithScrubber } from '../../shared/charts/duration_distribution_chart_with_scrubber';
|
||||
|
||||
export function BackendOperationDistributionChart() {
|
||||
export function DependencyOperationDistributionChart() {
|
||||
const { clearChartSelection, selectSampleFromChartSelection } =
|
||||
useSampleChartSelection();
|
||||
|
||||
// there is no "current" event in the backend operation detail view
|
||||
// there is no "current" event in the dependency operation detail view
|
||||
const markerCurrentEvent = undefined;
|
||||
|
||||
const euiTheme = useTheme();
|
||||
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
environment,
|
||||
kuery,
|
||||
|
@ -36,7 +36,7 @@ export function BackendOperationDistributionChart() {
|
|||
sampleRangeFrom = 0,
|
||||
sampleRangeTo = 0,
|
||||
},
|
||||
} = useApmParams('/backends/operation');
|
||||
} = useApmParams('/dependencies/operation');
|
||||
|
||||
const selection: [number, number] | undefined =
|
||||
sampleRangeFrom >= 0 && sampleRangeTo > 0
|
||||
|
@ -47,11 +47,11 @@ export function BackendOperationDistributionChart() {
|
|||
|
||||
const { status, data } = useFetcher(
|
||||
(callApmApi) => {
|
||||
return callApmApi('GET /internal/apm/backends/charts/distribution', {
|
||||
return callApmApi('GET /internal/apm/dependencies/charts/distribution', {
|
||||
params: {
|
||||
query: {
|
||||
percentileThreshold: DEFAULT_PERCENTILE_THRESHOLD,
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
environment,
|
||||
kuery,
|
||||
|
@ -61,7 +61,7 @@ export function BackendOperationDistributionChart() {
|
|||
},
|
||||
});
|
||||
},
|
||||
[backendName, spanName, environment, kuery, start, end]
|
||||
[dependencyName, spanName, environment, kuery, start, end]
|
||||
);
|
||||
|
||||
const hasData =
|
||||
|
@ -73,20 +73,16 @@ export function BackendOperationDistributionChart() {
|
|||
areaSeriesColor: euiTheme.eui.euiColorVis1,
|
||||
histogram: data?.allSpansDistribution.overallHistogram ?? [],
|
||||
id: i18n.translate(
|
||||
'xpack.apm.backendOperationDistributionChart.allSpansLegendLabel',
|
||||
{
|
||||
defaultMessage: 'All spans',
|
||||
}
|
||||
'xpack.apm.dependencyOperationDistributionChart.allSpansLegendLabel',
|
||||
{ defaultMessage: 'All spans' }
|
||||
),
|
||||
},
|
||||
{
|
||||
areaSeriesColor: euiTheme.eui.euiColorVis7,
|
||||
histogram: data?.failedSpansDistribution?.overallHistogram ?? [],
|
||||
id: i18n.translate(
|
||||
'xpack.apm.backendOperationDistributionChart.failedSpansLegendLabel',
|
||||
{
|
||||
defaultMessage: 'Failed spans',
|
||||
}
|
||||
'xpack.apm.dependencyOperationDistributionChart.failedSpansLegendLabel',
|
||||
{ defaultMessage: 'Failed spans' }
|
||||
),
|
||||
},
|
||||
];
|
|
@ -10,47 +10,47 @@ import React from 'react';
|
|||
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
import { useApmRouter } from '../../../hooks/use_apm_router';
|
||||
import { useBackendDetailOperationsBreadcrumb } from '../../../hooks/use_backend_detail_operations_breadcrumb';
|
||||
import { BackendMetricCharts } from '../../shared/backend_metric_charts';
|
||||
import { useDependencyDetailOperationsBreadcrumb } from '../../../hooks/use_dependency_detail_operations_breadcrumb';
|
||||
import { DependencyMetricCharts } from '../../shared/dependency_metric_charts';
|
||||
import { DetailViewHeader } from '../../shared/detail_view_header';
|
||||
import { BackendOperationDistributionChart } from './backend_operation_distribution_chart';
|
||||
import { BackendOperationDetailTraceList } from './backend_operation_detail_trace_list';
|
||||
import { DependencyOperationDistributionChart } from './dependendecy_operation_distribution_chart';
|
||||
import { DependencyOperationDetailTraceList } from './dependency_operation_detail_trace_list';
|
||||
|
||||
export function BackendOperationDetailView() {
|
||||
export function DependencyOperationDetailView() {
|
||||
const router = useApmRouter();
|
||||
|
||||
const {
|
||||
query: { spanName, ...query },
|
||||
} = useApmParams('/backends/operation');
|
||||
} = useApmParams('/dependencies/operation');
|
||||
|
||||
useBackendDetailOperationsBreadcrumb();
|
||||
useDependencyDetailOperationsBreadcrumb();
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="column">
|
||||
<EuiFlexItem>
|
||||
<DetailViewHeader
|
||||
backLabel={i18n.translate(
|
||||
'xpack.apm.backendOperationDetailView.header.backLinkLabel',
|
||||
'xpack.apm.dependecyOperationDetailView.header.backLinkLabel',
|
||||
{ defaultMessage: 'All operations' }
|
||||
)}
|
||||
backHref={router.link('/backends/operations', { query })}
|
||||
backHref={router.link('/dependencies/operations', { query })}
|
||||
title={spanName}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexItem>
|
||||
<ChartPointerEventContextProvider>
|
||||
<BackendMetricCharts />
|
||||
<DependencyMetricCharts />
|
||||
</ChartPointerEventContextProvider>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasBorder>
|
||||
<BackendOperationDistributionChart />
|
||||
<DependencyOperationDistributionChart />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasBorder>
|
||||
<BackendOperationDetailTraceList />
|
||||
<DependencyOperationDetailTraceList />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
|
@ -21,14 +21,15 @@ import { ApmRoutes } from '../../../routing/apm_route_config';
|
|||
import { StatsList } from './stats_list';
|
||||
import { APIReturnType } from '../../../../services/rest/create_call_apm_api';
|
||||
|
||||
type BackendReturn = APIReturnType<'GET /internal/apm/service-map/backend'>;
|
||||
type DependencyReturn =
|
||||
APIReturnType<'GET /internal/apm/service-map/dependency'>;
|
||||
|
||||
const INITIAL_STATE: Partial<BackendReturn> = {
|
||||
const INITIAL_STATE: Partial<DependencyReturn> = {
|
||||
currentPeriod: undefined,
|
||||
previousPeriod: undefined,
|
||||
};
|
||||
|
||||
export function BackendContents({
|
||||
export function DependencyContents({
|
||||
elementData,
|
||||
environment,
|
||||
start,
|
||||
|
@ -45,15 +46,15 @@ export function BackendContents({
|
|||
|
||||
const apmRouter = useApmRouter();
|
||||
|
||||
const backendName = nodeData.label;
|
||||
const dependencyName = nodeData.label;
|
||||
|
||||
const { data = INITIAL_STATE, status } = useFetcher(
|
||||
(callApmApi) => {
|
||||
if (backendName) {
|
||||
return callApmApi('GET /internal/apm/service-map/backend', {
|
||||
if (dependencyName) {
|
||||
return callApmApi('GET /internal/apm/service-map/dependency', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment,
|
||||
start,
|
||||
end,
|
||||
|
@ -66,16 +67,16 @@ export function BackendContents({
|
|||
});
|
||||
}
|
||||
},
|
||||
[environment, backendName, start, end, offset, comparisonEnabled]
|
||||
[environment, dependencyName, start, end, offset, comparisonEnabled]
|
||||
);
|
||||
|
||||
const isLoading = status === FETCH_STATUS.LOADING;
|
||||
const detailsUrl = backendName
|
||||
? apmRouter.link('/backends/overview', {
|
||||
const detailsUrl = dependencyName
|
||||
? apmRouter.link('/dependencies/overview', {
|
||||
query: {
|
||||
...query,
|
||||
backendName,
|
||||
} as TypeOf<ApmRoutes, '/backends/overview'>['query'],
|
||||
dependencyName,
|
||||
} as TypeOf<ApmRoutes, '/dependencies/overview'>['query'],
|
||||
})
|
||||
: undefined;
|
||||
|
||||
|
@ -96,7 +97,7 @@ export function BackendContents({
|
|||
trackEvent({
|
||||
app: 'apm',
|
||||
metricType: METRIC_TYPE.CLICK,
|
||||
metric: 'service_map_to_backend_detail',
|
||||
metric: 'service_map_to_dependency_detail',
|
||||
});
|
||||
}}
|
||||
>
|
|
@ -31,7 +31,7 @@ import { useTheme } from '../../../../hooks/use_theme';
|
|||
import { useTraceExplorerEnabledSetting } from '../../../../hooks/use_trace_explorer_enabled_setting';
|
||||
import { CytoscapeContext } from '../cytoscape';
|
||||
import { getAnimationOptions, popoverWidth } from '../cytoscape_options';
|
||||
import { BackendContents } from './backend_contents';
|
||||
import { DependencyContents } from './dependency_contents';
|
||||
import { EdgeContents } from './edge_contents';
|
||||
import { ExternalsListContents } from './externals_list_contents';
|
||||
import { ResourceContents } from './resource_contents';
|
||||
|
@ -64,7 +64,7 @@ function getContentsComponent(
|
|||
return EdgeContents;
|
||||
}
|
||||
|
||||
return BackendContents;
|
||||
return DependencyContents;
|
||||
}
|
||||
|
||||
export interface ContentsProps {
|
||||
|
|
|
@ -99,7 +99,7 @@ const stories: Meta<Args> = {
|
|||
};
|
||||
export default stories;
|
||||
|
||||
export const Backend: Story<Args> = () => {
|
||||
export const Dependency: Story<Args> = () => {
|
||||
return (
|
||||
<Popover
|
||||
environment={ENVIRONMENT_ALL.value}
|
||||
|
@ -109,7 +109,7 @@ export const Backend: Story<Args> = () => {
|
|||
/>
|
||||
);
|
||||
};
|
||||
Backend.args = {
|
||||
Dependency.args = {
|
||||
nodeData: {
|
||||
'span.subtype': 'postgresql',
|
||||
'span.destination.service.resource': 'postgresql',
|
||||
|
@ -119,7 +119,7 @@ Backend.args = {
|
|||
},
|
||||
};
|
||||
|
||||
export const BackendWithLongTitle: Story<Args> = () => {
|
||||
export const DependencyWithLongTitle: Story<Args> = () => {
|
||||
return (
|
||||
<Popover
|
||||
environment={ENVIRONMENT_ALL.value}
|
||||
|
@ -129,7 +129,7 @@ export const BackendWithLongTitle: Story<Args> = () => {
|
|||
/>
|
||||
);
|
||||
};
|
||||
BackendWithLongTitle.args = {
|
||||
DependencyWithLongTitle.args = {
|
||||
nodeData: {
|
||||
'span.subtype': 'http',
|
||||
'span.destination.service.resource':
|
||||
|
|
|
@ -10,12 +10,13 @@ import { render, screen, waitFor } from '@testing-library/react';
|
|||
import React from 'react';
|
||||
import * as stories from './popover.stories';
|
||||
|
||||
const { Backend, ExternalsList, Resource, Service } = composeStories(stories);
|
||||
const { Dependency, ExternalsList, Resource, Service } =
|
||||
composeStories(stories);
|
||||
|
||||
describe('Popover', () => {
|
||||
describe('with backend data', () => {
|
||||
describe('with dependency data', () => {
|
||||
it('renders a dependency link', async () => {
|
||||
render(<Backend />);
|
||||
render(<Dependency />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
|
|
|
@ -16,7 +16,7 @@ import { useApmServiceContext } from '../../../../context/apm_service/use_apm_se
|
|||
import { useApmParams } from '../../../../hooks/use_apm_params';
|
||||
import { useFetcher } from '../../../../hooks/use_fetcher';
|
||||
import { useTimeRange } from '../../../../hooks/use_time_range';
|
||||
import { BackendLink } from '../../../shared/backend_link';
|
||||
import { DependencyLink } from '../../../shared/dependency_link';
|
||||
import { DependenciesTable } from '../../../shared/dependencies_table';
|
||||
import { ServiceLink } from '../../../shared/service_link';
|
||||
|
||||
|
@ -83,12 +83,12 @@ export function ServiceOverviewDependenciesTable({
|
|||
const { location } = dependency;
|
||||
const name = getNodeName(location);
|
||||
const itemLink =
|
||||
location.type === NodeType.backend ? (
|
||||
<BackendLink
|
||||
location.type === NodeType.dependency ? (
|
||||
<DependencyLink
|
||||
type={location.spanType}
|
||||
subtype={location.spanSubtype}
|
||||
query={{
|
||||
backendName: location.backendName,
|
||||
dependencyName: location.dependencyName,
|
||||
comparisonEnabled,
|
||||
offset,
|
||||
environment,
|
||||
|
@ -100,7 +100,7 @@ export function ServiceOverviewDependenciesTable({
|
|||
trackEvent({
|
||||
app: 'apm',
|
||||
metricType: METRIC_TYPE.CLICK,
|
||||
metric: 'service_dependencies_to_backend_detail',
|
||||
metric: 'service_dependencies_to_dependency_detail',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -19,7 +19,7 @@ import { NOT_AVAILABLE_LABEL } from '../../../../../../../../common/i18n';
|
|||
import { Span } from '../../../../../../../../typings/es_schemas/ui/span';
|
||||
import { Transaction } from '../../../../../../../../typings/es_schemas/ui/transaction';
|
||||
import { useAnyOfApmParams } from '../../../../../../../hooks/use_apm_params';
|
||||
import { BackendLink } from '../../../../../../shared/backend_link';
|
||||
import { DependencyLink } from '../../../../../../shared/dependency_link';
|
||||
import { TransactionDetailLink } from '../../../../../../shared/links/apm/transaction_detail_link';
|
||||
import { ServiceLink } from '../../../../../../shared/service_link';
|
||||
import { StickyProperties } from '../../../../../../shared/sticky_properties';
|
||||
|
@ -112,10 +112,10 @@ export function StickySpanProperties({ span, transaction }: Props) {
|
|||
),
|
||||
fieldName: SPAN_DESTINATION_SERVICE_RESOURCE,
|
||||
val: (
|
||||
<BackendLink
|
||||
<DependencyLink
|
||||
query={{
|
||||
...query,
|
||||
backendName: dependencyName,
|
||||
dependencyName,
|
||||
}}
|
||||
subtype={span.span.subtype}
|
||||
type={span.span.type}
|
||||
|
@ -123,7 +123,7 @@ export function StickySpanProperties({ span, transaction }: Props) {
|
|||
trackEvent({
|
||||
app: 'apm',
|
||||
metricType: METRIC_TYPE.CLICK,
|
||||
metric: 'span_flyout_to_backend_detail',
|
||||
metric: 'span_flyout_to_dependency_detail',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -39,7 +39,7 @@ import { apmRouter } from './apm_route_config';
|
|||
import { TrackPageview } from './track_pageview';
|
||||
import { RedirectWithDefaultEnvironment } from '../shared/redirect_with_default_environment';
|
||||
import { RedirectWithOffset } from '../shared/redirect_with_offset';
|
||||
import { RedirectBackendsToBackendInventory } from './home/redirect_backends_to_backend_inventory';
|
||||
import { RedirectDependenciesToDependenciesInventory } from './home/redirect_dependencies_to_dependencies_inventory';
|
||||
|
||||
const storage = new Storage(localStorage);
|
||||
|
||||
|
@ -66,7 +66,7 @@ export function ApmAppRoot({
|
|||
<i18nCore.Context>
|
||||
<TimeRangeIdContextProvider>
|
||||
<RouterProvider history={history} router={apmRouter as any}>
|
||||
<RedirectBackendsToBackendInventory>
|
||||
<RedirectDependenciesToDependenciesInventory>
|
||||
<RedirectWithDefaultEnvironment>
|
||||
<RedirectWithDefaultDateRange>
|
||||
<RedirectWithOffset>
|
||||
|
@ -93,7 +93,7 @@ export function ApmAppRoot({
|
|||
</RedirectWithOffset>
|
||||
</RedirectWithDefaultDateRange>
|
||||
</RedirectWithDefaultEnvironment>
|
||||
</RedirectBackendsToBackendInventory>
|
||||
</RedirectDependenciesToDependenciesInventory>
|
||||
</RouterProvider>
|
||||
</TimeRangeIdContextProvider>
|
||||
</i18nCore.Context>
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
||||
import { Outlet } from '@kbn/typed-react-router-config';
|
||||
import * as t from 'io-ts';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import qs from 'query-string';
|
||||
import { page } from '.';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { DependencyDetailOperations } from '../../app/dependency_detail_operations';
|
||||
import { DependencyDetailOverview } from '../../app/dependency_detail_overview';
|
||||
import { DependencyDetailView } from '../../app/dependency_detail_view';
|
||||
import { DependenciesInventory } from '../../app/dependencies_inventory';
|
||||
import { DependencyOperationDetailView } from '../../app/dependency_operation_detail_view';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
|
||||
export const DependenciesInventoryTitle = i18n.translate(
|
||||
'xpack.apm.views.dependenciesInventory.title',
|
||||
{ defaultMessage: 'Dependencies' }
|
||||
);
|
||||
|
||||
function RedirectDependenciesToDependenciesOverview() {
|
||||
const { query } = useApmParams('/dependencies');
|
||||
const search = qs.stringify(query);
|
||||
return <Redirect to={{ pathname: `/dependencies/overview`, search }} />;
|
||||
}
|
||||
|
||||
export const dependencies = {
|
||||
...page({
|
||||
path: '/dependencies/inventory',
|
||||
title: DependenciesInventoryTitle,
|
||||
element: <DependenciesInventory />,
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
comparisonEnabled: toBooleanRt,
|
||||
}),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
}),
|
||||
'/dependencies': {
|
||||
element: (
|
||||
<DependencyDetailView>
|
||||
<Outlet />
|
||||
</DependencyDetailView>
|
||||
),
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
comparisonEnabled: toBooleanRt,
|
||||
dependencyName: t.string,
|
||||
}),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
children: {
|
||||
'/dependencies': {
|
||||
element: <RedirectDependenciesToDependenciesOverview />,
|
||||
},
|
||||
'/dependencies/operations': {
|
||||
element: <DependencyDetailOperations />,
|
||||
},
|
||||
'/dependencies/operation': {
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
spanName: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
sampleRangeFrom: toNumberRt,
|
||||
sampleRangeTo: toNumberRt,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
element: <DependencyOperationDetailView />,
|
||||
},
|
||||
'/dependencies/overview': {
|
||||
element: <DependencyDetailOverview />,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -5,35 +5,30 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
||||
import { Outlet, Route } from '@kbn/typed-react-router-config';
|
||||
import * as t from 'io-ts';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
|
||||
import { environmentRt } from '../../../../common/environment_rt';
|
||||
import { TraceSearchType } from '../../../../common/trace_explorer';
|
||||
import { BackendDetailOverview } from '../../app/backend_detail_overview';
|
||||
import { BackendInventory } from '../../app/backend_inventory';
|
||||
import { TimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context';
|
||||
import { Breadcrumb } from '../../app/breadcrumb';
|
||||
import { ServiceInventory } from '../../app/service_inventory';
|
||||
import { ServiceMapHome } from '../../app/service_map';
|
||||
import { TraceOverview } from '../../app/trace_overview';
|
||||
import { TraceExplorer } from '../../app/trace_explorer';
|
||||
import { TopTracesOverview } from '../../app/top_traces_overview';
|
||||
import { TraceExplorer } from '../../app/trace_explorer';
|
||||
import { TraceOverview } from '../../app/trace_overview';
|
||||
import { TransactionTab } from '../../app/transaction_details/waterfall_with_summary/transaction_tabs';
|
||||
import { RedirectTo } from '../redirect_to';
|
||||
import { ServiceGroupsRedirect } from '../service_groups_redirect';
|
||||
import { ApmMainTemplate } from '../templates/apm_main_template';
|
||||
import { ServiceGroupTemplate } from '../templates/service_group_template';
|
||||
import { ServiceGroupsRedirect } from '../service_groups_redirect';
|
||||
import { RedirectTo } from '../redirect_to';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { TransactionTab } from '../../app/transaction_details/waterfall_with_summary/transaction_tabs';
|
||||
import { BackendDetailOperations } from '../../app/backend_detail_operations';
|
||||
import { BackendDetailView } from '../../app/backend_detail_view';
|
||||
import { RedirectPathBackendDetailView } from './redirect_path_backend_detail_view';
|
||||
import { RedirectBackendsToBackendDetailOverview } from './redirect_backends_to_backend_detail_view';
|
||||
import { BackendOperationDetailView } from '../../app/backend_operation_detail_view';
|
||||
import { TimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context';
|
||||
import { dependencies } from './dependencies';
|
||||
import { legacyBackends } from './legacy_backends';
|
||||
|
||||
function page<
|
||||
export function page<
|
||||
TPath extends string,
|
||||
TChildren extends Record<string, Route> | undefined = undefined,
|
||||
TParams extends t.Type<any> | undefined = undefined
|
||||
|
@ -136,13 +131,6 @@ export const ServiceMapTitle = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const DependenciesInventoryTitle = i18n.translate(
|
||||
'xpack.apm.views.dependenciesInventory.title',
|
||||
{
|
||||
defaultMessage: 'Dependencies',
|
||||
}
|
||||
);
|
||||
|
||||
export const DependenciesOperationsTitle = i18n.translate(
|
||||
'xpack.apm.views.dependenciesOperations.title',
|
||||
{
|
||||
|
@ -242,74 +230,8 @@ export const home = {
|
|||
},
|
||||
},
|
||||
}),
|
||||
...page({
|
||||
path: '/backends/inventory',
|
||||
title: DependenciesInventoryTitle,
|
||||
element: <BackendInventory />,
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
comparisonEnabled: toBooleanRt,
|
||||
}),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
}),
|
||||
'/backends/{backendName}/overview': {
|
||||
element: <RedirectPathBackendDetailView />,
|
||||
params: t.type({
|
||||
path: t.type({
|
||||
backendName: t.string,
|
||||
}),
|
||||
}),
|
||||
},
|
||||
'/backends': {
|
||||
element: <Outlet />,
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
comparisonEnabled: toBooleanRt,
|
||||
backendName: t.string,
|
||||
}),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
children: {
|
||||
'/backends': {
|
||||
element: (
|
||||
<BackendDetailView>
|
||||
<Outlet />
|
||||
</BackendDetailView>
|
||||
),
|
||||
children: {
|
||||
'/backends/operations': {
|
||||
element: <BackendDetailOperations />,
|
||||
},
|
||||
|
||||
'/backends/operation': {
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
spanName: t.string,
|
||||
}),
|
||||
t.partial({
|
||||
sampleRangeFrom: toNumberRt,
|
||||
sampleRangeTo: toNumberRt,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
element: <BackendOperationDetailView />,
|
||||
},
|
||||
'/backends/overview': {
|
||||
element: <BackendDetailOverview />,
|
||||
},
|
||||
'/backends': {
|
||||
element: <RedirectBackendsToBackendDetailOverview />,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
...dependencies,
|
||||
...legacyBackends,
|
||||
'/': {
|
||||
element: (
|
||||
<ServiceGroupsRedirect>
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
||||
import { Outlet } from '@kbn/typed-react-router-config';
|
||||
import * as t from 'io-ts';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import qs from 'query-string';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
|
||||
function RedirectBackends({ to }: { to: string }) {
|
||||
const { query } = useApmParams('/backends/*');
|
||||
const search = qs.stringify(query);
|
||||
return <Redirect to={{ pathname: to, search }} />;
|
||||
}
|
||||
|
||||
function RedirectBackendsOverviewToDependenciesOverview() {
|
||||
const {
|
||||
path: { dependencyName },
|
||||
query,
|
||||
} = useApmParams('/backends/{dependencyName}/overview');
|
||||
|
||||
const search = qs.stringify({ ...query, dependencyName });
|
||||
|
||||
return <Redirect to={{ pathname: `/dependencies/overview`, search }} />;
|
||||
}
|
||||
|
||||
export const legacyBackends = {
|
||||
'/backends/inventory': {
|
||||
element: <RedirectBackends to="/dependencies/inventory" />,
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({ comparisonEnabled: toBooleanRt }),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
},
|
||||
'/backends/{dependencyName}/overview': {
|
||||
element: <RedirectBackendsOverviewToDependenciesOverview />,
|
||||
params: t.type({ path: t.type({ dependencyName: t.string }) }),
|
||||
},
|
||||
'/backends': {
|
||||
element: <Outlet />,
|
||||
params: t.partial({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
comparisonEnabled: toBooleanRt,
|
||||
dependencyName: t.string,
|
||||
}),
|
||||
offsetRt,
|
||||
]),
|
||||
}),
|
||||
children: {
|
||||
'/backends': {
|
||||
element: <RedirectBackends to="/dependencies" />,
|
||||
},
|
||||
'/backends/operations': {
|
||||
element: <RedirectBackends to="/dependencies/operations" />,
|
||||
},
|
||||
'/backends/operation': {
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({ spanName: t.string }),
|
||||
t.partial({
|
||||
sampleRangeFrom: toNumberRt,
|
||||
sampleRangeTo: toNumberRt,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
element: <RedirectBackends to="/dependencies/operation" />,
|
||||
},
|
||||
'/backends/overview': {
|
||||
element: <RedirectBackends to="/dependencies/overview" />,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,19 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import qs from 'query-string';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
|
||||
export function RedirectBackendsToBackendDetailOverview() {
|
||||
const { query } = useApmParams('/backends');
|
||||
|
||||
const search = qs.stringify(query);
|
||||
|
||||
return <Redirect to={{ pathname: `/backends/overview`, search }} />;
|
||||
}
|
|
@ -9,7 +9,7 @@ import { useLocation, Redirect } from 'react-router-dom';
|
|||
import qs from 'query-string';
|
||||
import React from 'react';
|
||||
|
||||
export function RedirectBackendsToBackendInventory({
|
||||
export function RedirectDependenciesToDependenciesInventory({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactElement;
|
||||
|
@ -19,7 +19,7 @@ export function RedirectBackendsToBackendInventory({
|
|||
const query = qs.parse(location.search);
|
||||
|
||||
const normalizedPathname = location.pathname.replace(/\/$/, '');
|
||||
if (normalizedPathname === '/backends' && !('backendName' in query)) {
|
||||
if (normalizedPathname === '/dependencies' && !('dependencyName' in query)) {
|
||||
return (
|
||||
<Redirect
|
||||
to={qs.stringifyUrl({
|
|
@ -1,22 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import qs from 'query-string';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
|
||||
export function RedirectPathBackendDetailView() {
|
||||
const {
|
||||
path: { backendName },
|
||||
query,
|
||||
} = useApmParams('/backends/{backendName}/overview');
|
||||
|
||||
const search = qs.stringify({ ...query, backendName });
|
||||
|
||||
return <Redirect to={{ pathname: `/backends/overview`, search }} />;
|
||||
}
|
|
@ -19,18 +19,18 @@ import { SearchBar } from '../../shared/search_bar';
|
|||
import {
|
||||
getKueryBarBoolFilter,
|
||||
kueryBarPlaceholder,
|
||||
} from '../../../../common/backends';
|
||||
} from '../../../../common/dependencies';
|
||||
import { useOperationBreakdownEnabledSetting } from '../../../hooks/use_operations_breakdown_enabled_setting';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function BackendDetailTemplate({ children }: Props) {
|
||||
export function DependencyDetailTemplate({ children }: Props) {
|
||||
const {
|
||||
query,
|
||||
query: { backendName, rangeFrom, rangeTo, environment },
|
||||
} = useApmParams('/backends');
|
||||
query: { dependencyName, rangeFrom, rangeTo, environment },
|
||||
} = useApmParams('/dependencies');
|
||||
|
||||
const router = useApmRouter();
|
||||
|
||||
|
@ -43,52 +43,53 @@ export function BackendDetailTemplate({ children }: Props) {
|
|||
|
||||
const kueryBarBoolFilter = getKueryBarBoolFilter({
|
||||
environment,
|
||||
backendName,
|
||||
dependencyName,
|
||||
});
|
||||
|
||||
const backendMetadataFetch = useFetcher(
|
||||
const dependencyMetadataFetch = useFetcher(
|
||||
(callApmApi) => {
|
||||
if (!start || !end) {
|
||||
return;
|
||||
}
|
||||
|
||||
return callApmApi('GET /internal/apm/backends/metadata', {
|
||||
return callApmApi('GET /internal/apm/dependencies/metadata', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
[backendName, start, end]
|
||||
[dependencyName, start, end]
|
||||
);
|
||||
|
||||
const { data: { metadata } = {} } = backendMetadataFetch;
|
||||
const { data: { metadata } = {} } = dependencyMetadataFetch;
|
||||
|
||||
const tabs = isOperationsBreakdownFeatureEnabled
|
||||
? [
|
||||
{
|
||||
key: 'overview',
|
||||
href: router.link('/backends/overview', {
|
||||
href: router.link('/dependencies/overview', {
|
||||
query,
|
||||
}),
|
||||
label: i18n.translate('xpack.apm.backendDetailOverview.title', {
|
||||
label: i18n.translate('xpack.apm.DependencyDetailOverview.title', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
isSelected: path === '/backends/overview',
|
||||
isSelected: path === '/dependencies/overview',
|
||||
},
|
||||
{
|
||||
key: 'operations',
|
||||
href: router.link('/backends/operations', {
|
||||
href: router.link('/dependencies/operations', {
|
||||
query,
|
||||
}),
|
||||
label: i18n.translate('xpack.apm.backendDetailOperations.title', {
|
||||
label: i18n.translate('xpack.apm.DependencyDetailOperations.title', {
|
||||
defaultMessage: 'Operations',
|
||||
}),
|
||||
isSelected:
|
||||
path === '/backends/operations' || path === '/backends/operation',
|
||||
path === '/dependencies/operations' ||
|
||||
path === '/dependencies/operation',
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
@ -101,7 +102,7 @@ export function BackendDetailTemplate({ children }: Props) {
|
|||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="l">
|
||||
<h1>{backendName}</h1>
|
||||
<h1>{dependencyName}</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
|
@ -91,7 +91,11 @@ export function TimeseriesChart({
|
|||
const chartTheme = useChartTheme();
|
||||
const {
|
||||
query: { comparisonEnabled, offset },
|
||||
} = useAnyOfApmParams('/services', '/backends/*', '/services/{serviceName}');
|
||||
} = useAnyOfApmParams(
|
||||
'/services',
|
||||
'/dependencies/*',
|
||||
'/services/{serviceName}'
|
||||
);
|
||||
|
||||
const anomalyChartTimeseries = getChartAnomalyTimeseries({
|
||||
anomalyTimeseries,
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
import { Story } from '@storybook/react';
|
||||
import React, { ComponentProps, ComponentType } from 'react';
|
||||
import { MockApmPluginContextWrapper } from '../../context/apm_plugin/mock_apm_plugin_context';
|
||||
import { BackendLink } from './backend_link';
|
||||
import { DependencyLink } from './dependency_link';
|
||||
|
||||
type Args = ComponentProps<typeof BackendLink>;
|
||||
type Args = ComponentProps<typeof DependencyLink>;
|
||||
|
||||
export default {
|
||||
title: 'shared/BackendLink',
|
||||
component: BackendLink,
|
||||
title: 'shared/DependencyLink',
|
||||
component: DependencyLink,
|
||||
decorators: [
|
||||
(StoryComponent: ComponentType) => {
|
||||
return (
|
||||
|
@ -27,11 +27,11 @@ export default {
|
|||
};
|
||||
|
||||
export const Example: Story<Args> = (args) => {
|
||||
return <BackendLink {...args} />;
|
||||
return <DependencyLink {...args} />;
|
||||
};
|
||||
Example.args = {
|
||||
query: {
|
||||
backendName: 'postgres',
|
||||
dependencyName: 'postgres',
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
kuery: '',
|
||||
rangeFrom: 'now-15m',
|
|
@ -8,11 +8,11 @@
|
|||
import { composeStories } from '@storybook/testing-react';
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import * as stories from './backend_link.stories';
|
||||
import * as stories from './dependency_link.stories';
|
||||
|
||||
const { Example } = composeStories(stories);
|
||||
|
||||
describe('BackendLink', () => {
|
||||
describe('DependencyLink', () => {
|
||||
it('renders', () => {
|
||||
expect(() => render(<Example />)).not.toThrowError();
|
||||
});
|
|
@ -16,24 +16,19 @@ import { SpanIcon } from './span_icon';
|
|||
|
||||
const StyledLink = euiStyled(EuiLink)`${truncate('100%')};`;
|
||||
|
||||
interface BackendLinkProps {
|
||||
query: TypeOf<ApmRoutes, '/backends/overview'>['query'];
|
||||
interface Props {
|
||||
query: TypeOf<ApmRoutes, '/dependencies/overview'>['query'];
|
||||
subtype?: string;
|
||||
type?: string;
|
||||
onClick?: React.ComponentProps<typeof EuiLink>['onClick'];
|
||||
}
|
||||
|
||||
export function BackendLink({
|
||||
query,
|
||||
subtype,
|
||||
type,
|
||||
onClick,
|
||||
}: BackendLinkProps) {
|
||||
export function DependencyLink({ query, subtype, type, onClick }: Props) {
|
||||
const { link } = useApmRouter();
|
||||
|
||||
return (
|
||||
<StyledLink
|
||||
href={link('/backends/overview', {
|
||||
href={link('/dependencies/overview', {
|
||||
query,
|
||||
})}
|
||||
onClick={onClick}
|
||||
|
@ -43,7 +38,7 @@ export function BackendLink({
|
|||
<SpanIcon type={type} subtype={subtype} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="eui-textTruncate">
|
||||
<span className="eui-textTruncate">{query.backendName}</span>
|
||||
<span className="eui-textTruncate">{query.dependencyName}</span>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</StyledLink>
|
|
@ -18,16 +18,16 @@ import {
|
|||
getTimeSeriesColor,
|
||||
} from '../charts/helper/get_timeseries_color';
|
||||
import { getComparisonChartTheme } from '../time_comparison/get_comparison_chart_theme';
|
||||
import { BackendMetricChartsRouteParams } from './backend_metric_charts_route_params';
|
||||
import { DependencyMetricChartsRouteParams } from './dependency_metric_charts_route_params';
|
||||
import { useSearchServiceDestinationMetrics } from '../../../context/time_range_metadata/use_search_service_destination_metrics';
|
||||
|
||||
function yLabelFormat(y?: number | null) {
|
||||
return asPercent(y || 0, 1);
|
||||
}
|
||||
|
||||
export function BackendFailedTransactionRateChart({
|
||||
export function DependencyFailedTransactionRateChart({
|
||||
height,
|
||||
backendName,
|
||||
dependencyName,
|
||||
kuery,
|
||||
environment,
|
||||
rangeFrom,
|
||||
|
@ -37,7 +37,7 @@ export function BackendFailedTransactionRateChart({
|
|||
spanName,
|
||||
}: {
|
||||
height: number;
|
||||
} & BackendMetricChartsRouteParams) {
|
||||
} & DependencyMetricChartsRouteParams) {
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
const comparisonChartTheme = getComparisonChartTheme();
|
||||
|
@ -51,10 +51,10 @@ export function BackendFailedTransactionRateChart({
|
|||
return;
|
||||
}
|
||||
|
||||
return callApmApi('GET /internal/apm/backends/charts/error_rate', {
|
||||
return callApmApi('GET /internal/apm/dependencies/charts/error_rate', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset:
|
||||
|
@ -70,7 +70,7 @@ export function BackendFailedTransactionRateChart({
|
|||
});
|
||||
},
|
||||
[
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -96,7 +96,7 @@ export function BackendFailedTransactionRateChart({
|
|||
data: data.currentTimeseries,
|
||||
type: 'linemark',
|
||||
color: currentPeriodColor,
|
||||
title: i18n.translate('xpack.apm.backendErrorRateChart.chartTitle', {
|
||||
title: i18n.translate('xpack.apm.dependencyErrorRateChart.chartTitle', {
|
||||
defaultMessage: 'Failed transaction rate',
|
||||
}),
|
||||
});
|
|
@ -22,12 +22,12 @@ import {
|
|||
getTimeSeriesColor,
|
||||
} from '../charts/helper/get_timeseries_color';
|
||||
import { getComparisonChartTheme } from '../time_comparison/get_comparison_chart_theme';
|
||||
import { BackendMetricChartsRouteParams } from './backend_metric_charts_route_params';
|
||||
import { DependencyMetricChartsRouteParams } from './dependency_metric_charts_route_params';
|
||||
import { useSearchServiceDestinationMetrics } from '../../../context/time_range_metadata/use_search_service_destination_metrics';
|
||||
|
||||
export function BackendLatencyChart({
|
||||
export function DependencyLatencyChart({
|
||||
height,
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
|
@ -35,7 +35,7 @@ export function BackendLatencyChart({
|
|||
offset,
|
||||
comparisonEnabled,
|
||||
spanName,
|
||||
}: { height: number } & BackendMetricChartsRouteParams) {
|
||||
}: { height: number } & DependencyMetricChartsRouteParams) {
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
const comparisonChartTheme = getComparisonChartTheme();
|
||||
|
@ -49,10 +49,10 @@ export function BackendLatencyChart({
|
|||
return;
|
||||
}
|
||||
|
||||
return callApmApi('GET /internal/apm/backends/charts/latency', {
|
||||
return callApmApi('GET /internal/apm/dependencies/charts/latency', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset:
|
||||
|
@ -68,7 +68,7 @@ export function BackendLatencyChart({
|
|||
});
|
||||
},
|
||||
[
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -95,7 +95,7 @@ export function BackendLatencyChart({
|
|||
data: data.currentTimeseries,
|
||||
type: 'linemark',
|
||||
color: currentPeriodColor,
|
||||
title: i18n.translate('xpack.apm.backendLatencyChart.chartTitle', {
|
||||
title: i18n.translate('xpack.apm.dependencyLatencyChart.chartTitle', {
|
||||
defaultMessage: 'Latency',
|
||||
}),
|
||||
});
|
|
@ -7,12 +7,12 @@
|
|||
import { TypeOf } from '@kbn/typed-react-router-config';
|
||||
import { ApmRoutes } from '../../routing/apm_route_config';
|
||||
|
||||
export type BackendMetricChartsRouteParams = Pick<
|
||||
export type DependencyMetricChartsRouteParams = Pick<
|
||||
{ spanName?: string } & TypeOf<
|
||||
ApmRoutes,
|
||||
'/backends/operation' | '/backends/overview'
|
||||
'/dependencies/operation' | '/dependencies/overview'
|
||||
>['query'],
|
||||
| 'backendName'
|
||||
| 'dependencyName'
|
||||
| 'comparisonEnabled'
|
||||
| 'spanName'
|
||||
| 'rangeFrom'
|
|
@ -18,12 +18,12 @@ import {
|
|||
getTimeSeriesColor,
|
||||
} from '../charts/helper/get_timeseries_color';
|
||||
import { getComparisonChartTheme } from '../time_comparison/get_comparison_chart_theme';
|
||||
import { BackendMetricChartsRouteParams } from './backend_metric_charts_route_params';
|
||||
import { DependencyMetricChartsRouteParams } from './dependency_metric_charts_route_params';
|
||||
import { useSearchServiceDestinationMetrics } from '../../../context/time_range_metadata/use_search_service_destination_metrics';
|
||||
|
||||
export function BackendThroughputChart({
|
||||
export function DependencyThroughputChart({
|
||||
height,
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
|
@ -31,7 +31,7 @@ export function BackendThroughputChart({
|
|||
offset,
|
||||
comparisonEnabled,
|
||||
spanName,
|
||||
}: { height: number } & BackendMetricChartsRouteParams) {
|
||||
}: { height: number } & DependencyMetricChartsRouteParams) {
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
const comparisonChartTheme = getComparisonChartTheme();
|
||||
|
@ -45,10 +45,10 @@ export function BackendThroughputChart({
|
|||
return;
|
||||
}
|
||||
|
||||
return callApmApi('GET /internal/apm/backends/charts/throughput', {
|
||||
return callApmApi('GET /internal/apm/dependencies/charts/throughput', {
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset:
|
||||
|
@ -64,7 +64,7 @@ export function BackendThroughputChart({
|
|||
});
|
||||
},
|
||||
[
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -91,9 +91,10 @@ export function BackendThroughputChart({
|
|||
data: data.currentTimeseries,
|
||||
type: 'linemark',
|
||||
color: currentPeriodColor,
|
||||
title: i18n.translate('xpack.apm.backendThroughputChart.chartTitle', {
|
||||
defaultMessage: 'Throughput',
|
||||
}),
|
||||
title: i18n.translate(
|
||||
'xpack.apm.dependencyThroughputChart.chartTitle',
|
||||
{ defaultMessage: 'Throughput' }
|
||||
),
|
||||
});
|
||||
}
|
||||
|
|
@ -10,18 +10,18 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { useAnyOfApmParams } from '../../../hooks/use_apm_params';
|
||||
import { useBreakpoints } from '../../../hooks/use_breakpoints';
|
||||
import { BackendFailedTransactionRateChart } from './backend_error_rate_chart';
|
||||
import { BackendLatencyChart } from './backend_latency_chart';
|
||||
import { BackendMetricChartsRouteParams } from './backend_metric_charts_route_params';
|
||||
import { BackendThroughputChart } from './backend_throughput_chart';
|
||||
import { DependencyFailedTransactionRateChart } from './dependency_failed_transaction_rate_chart';
|
||||
import { DependencyLatencyChart } from './dependency_latency_chart';
|
||||
import { DependencyMetricChartsRouteParams } from './dependency_metric_charts_route_params';
|
||||
import { DependencyThroughputChart } from './dependency_throughput_chart';
|
||||
|
||||
export function BackendMetricCharts() {
|
||||
export function DependencyMetricCharts() {
|
||||
const largeScreenOrSmaller = useBreakpoints().isLarge;
|
||||
|
||||
const {
|
||||
query,
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
|
@ -29,12 +29,12 @@ export function BackendMetricCharts() {
|
|||
comparisonEnabled,
|
||||
offset,
|
||||
},
|
||||
} = useAnyOfApmParams('/backends/overview', '/backends/operation');
|
||||
} = useAnyOfApmParams('/dependencies/overview', '/dependencies/operation');
|
||||
|
||||
const spanName = 'spanName' in query ? query.spanName : undefined;
|
||||
|
||||
const props: BackendMetricChartsRouteParams = {
|
||||
backendName,
|
||||
const props: DependencyMetricChartsRouteParams = {
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
kuery,
|
||||
|
@ -53,24 +53,12 @@ export function BackendMetricCharts() {
|
|||
<EuiPanel hasBorder={true}>
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
{i18n.translate('xpack.apm.backendDetailLatencyChartTitle', {
|
||||
{i18n.translate('xpack.apm.dependencyDetailLatencyChartTitle', {
|
||||
defaultMessage: 'Latency',
|
||||
})}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<BackendLatencyChart height={200} {...props} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasBorder={true}>
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
{i18n.translate('xpack.apm.backendDetailThroughputChartTitle', {
|
||||
defaultMessage: 'Throughput',
|
||||
})}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<BackendThroughputChart height={200} {...props} />
|
||||
<DependencyLatencyChart height={200} {...props} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
|
@ -78,12 +66,25 @@ export function BackendMetricCharts() {
|
|||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
{i18n.translate(
|
||||
'xpack.apm.backendDetailFailedTransactionRateChartTitle',
|
||||
'xpack.apm.dependencyDetailThroughputChartTitle',
|
||||
{ defaultMessage: 'Throughput' }
|
||||
)}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<DependencyThroughputChart height={200} {...props} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasBorder={true}>
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
{i18n.translate(
|
||||
'xpack.apm.dependencyDetailFailedTransactionRateChartTitle',
|
||||
{ defaultMessage: 'Failed transaction rate' }
|
||||
)}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<BackendFailedTransactionRateChart height={200} {...props} />
|
||||
<DependencyFailedTransactionRateChart height={200} {...props} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
|
@ -20,8 +20,8 @@ export function isRouteWithTimeRange({
|
|||
route.path === '/services' ||
|
||||
route.path === '/traces' ||
|
||||
route.path === '/service-map' ||
|
||||
route.path === '/backends' ||
|
||||
route.path === '/backends/inventory' ||
|
||||
route.path === '/dependencies' ||
|
||||
route.path === '/dependencies/inventory' ||
|
||||
route.path === '/services/{serviceName}' ||
|
||||
route.path === '/service-groups' ||
|
||||
location.pathname === '/' ||
|
||||
|
@ -44,8 +44,8 @@ export function isRouteWithComparison({
|
|||
return (
|
||||
route.path === '/services' ||
|
||||
route.path === '/service-map' ||
|
||||
route.path === '/backends' ||
|
||||
route.path === '/backends/inventory' ||
|
||||
route.path === '/dependencies' ||
|
||||
route.path === '/dependencies/inventory' ||
|
||||
route.path === '/services/{serviceName}' ||
|
||||
route.path === '/service-groups' ||
|
||||
location.pathname === '/' ||
|
||||
|
|
|
@ -39,7 +39,11 @@ export function TimeComparison() {
|
|||
const { isSmall } = useBreakpoints();
|
||||
const {
|
||||
query: { rangeFrom, rangeTo, comparisonEnabled, offset },
|
||||
} = useAnyOfApmParams('/services', '/backends/*', '/services/{serviceName}');
|
||||
} = useAnyOfApmParams(
|
||||
'/services',
|
||||
'/dependencies/*',
|
||||
'/services/{serviceName}'
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
const apmRouter = useApmRouter();
|
||||
|
|
|
@ -38,7 +38,8 @@ export function TimeRangeMetadataContextProvider({
|
|||
const routePath = useApmRoutePath();
|
||||
|
||||
const isOperationView =
|
||||
routePath === '/backends/operation' || routePath === '/backends/operations';
|
||||
routePath === '/dependencies/operation' ||
|
||||
routePath === '/dependencies/operations';
|
||||
|
||||
const fetcherResult = useFetcher(
|
||||
(callApmApi) => {
|
||||
|
|
|
@ -10,10 +10,10 @@ import { useBreadcrumb } from '../context/breadcrumbs/use_breadcrumb';
|
|||
import { useAnyOfApmParams } from './use_apm_params';
|
||||
import { useApmRouter } from './use_apm_router';
|
||||
|
||||
export function useBackendDetailOperationsBreadcrumb() {
|
||||
export function useDependencyDetailOperationsBreadcrumb() {
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
||||
|
@ -22,19 +22,19 @@ export function useBackendDetailOperationsBreadcrumb() {
|
|||
kuery,
|
||||
comparisonEnabled,
|
||||
},
|
||||
} = useAnyOfApmParams('/backends/operations', '/backends/operation');
|
||||
} = useAnyOfApmParams('/dependencies/operations', '/dependencies/operation');
|
||||
|
||||
const apmRouter = useApmRouter();
|
||||
|
||||
useBreadcrumb([
|
||||
{
|
||||
title: i18n.translate(
|
||||
'xpack.apm.backendDetailOperations.breadcrumbTitle',
|
||||
'xpack.apm.dependencyDetailOperations.breadcrumbTitle',
|
||||
{ defaultMessage: 'Operations' }
|
||||
),
|
||||
href: apmRouter.link('/backends/operations', {
|
||||
href: apmRouter.link('/dependencies/operations', {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
rangeFrom,
|
||||
rangeTo,
|
||||
refreshInterval,
|
|
@ -19,7 +19,11 @@ const fallbackPreviousPeriodText = i18n.translate(
|
|||
export const usePreviousPeriodLabel = () => {
|
||||
const {
|
||||
query: { rangeFrom, rangeTo, offset },
|
||||
} = useAnyOfApmParams('/services', '/backends/*', '/services/{serviceName}');
|
||||
} = useAnyOfApmParams(
|
||||
'/services',
|
||||
'/dependencies/*',
|
||||
'/services/{serviceName}'
|
||||
);
|
||||
|
||||
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
{
|
||||
label: dependenciesTitle,
|
||||
app: 'apm',
|
||||
path: '/backends/inventory',
|
||||
path: '/dependencies/inventory',
|
||||
onClick: () => {
|
||||
const { usageCollection } = pluginsStart as {
|
||||
usageCollection?: UsageCollectionStart;
|
||||
|
@ -188,7 +188,7 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
usageCollection.reportUiCounter(
|
||||
'apm',
|
||||
METRIC_TYPE.CLICK,
|
||||
'side_nav_backend'
|
||||
'side_nav_dependency'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -299,9 +299,9 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
{ id: 'traces', title: tracesTitle, path: '/traces' },
|
||||
{ id: 'service-map', title: serviceMapTitle, path: '/service-map' },
|
||||
{
|
||||
id: 'backends',
|
||||
id: 'dependencies',
|
||||
title: dependenciesTitle,
|
||||
path: '/backends/inventory',
|
||||
path: '/dependencies/inventory',
|
||||
},
|
||||
],
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import { Node, NodeType } from '../../../../common/connections';
|
|||
import { excludeRumExitSpansQuery } from '../exclude_rum_exit_spans_query';
|
||||
|
||||
type Destination = {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanId: string;
|
||||
spanType: string;
|
||||
spanSubtype: string;
|
||||
|
@ -43,10 +43,10 @@ type Destination = {
|
|||
}
|
||||
);
|
||||
|
||||
// This operation tries to find a service for a backend, by:
|
||||
// This operation tries to find a service for a dependency, by:
|
||||
// - getting a span for each value of span.destination.service.resource (which indicates an outgoing call)
|
||||
// - for each span, find the transaction it creates
|
||||
// - if there is a transaction, match the backend name (span.destination.service.resource) to a service
|
||||
// - if there is a transaction, match the dependency name (span.destination.service.resource) to a service
|
||||
export const getDestinationMap = ({
|
||||
setup,
|
||||
start,
|
||||
|
@ -91,7 +91,7 @@ export const getDestinationMap = ({
|
|||
size: 10000,
|
||||
sources: asMutableArray([
|
||||
{
|
||||
backendName: {
|
||||
dependencyName: {
|
||||
terms: { field: SPAN_DESTINATION_SERVICE_RESOURCE },
|
||||
},
|
||||
},
|
||||
|
@ -130,7 +130,7 @@ export const getDestinationMap = ({
|
|||
const spanId = sample[SPAN_ID] as string;
|
||||
|
||||
destinationsBySpanId.set(spanId, {
|
||||
backendName: bucket.key.backendName as string,
|
||||
dependencyName: bucket.key.dependencyName as string,
|
||||
spanId,
|
||||
spanType: (sample[SPAN_TYPE] as string | null) || '',
|
||||
spanSubtype: (sample[SPAN_SUBTYPE] as string | null) || '',
|
||||
|
@ -189,11 +189,11 @@ export const getDestinationMap = ({
|
|||
}
|
||||
});
|
||||
|
||||
const nodesByBackendName = new Map<string, Node>();
|
||||
const nodesBydependencyName = new Map<string, Node>();
|
||||
|
||||
destinationsBySpanId.forEach((destination) => {
|
||||
const existingDestination =
|
||||
nodesByBackendName.get(destination.backendName) ?? {};
|
||||
nodesBydependencyName.get(destination.dependencyName) ?? {};
|
||||
|
||||
const mergedDestination = {
|
||||
...existingDestination,
|
||||
|
@ -211,17 +211,17 @@ export const getDestinationMap = ({
|
|||
};
|
||||
} else {
|
||||
node = {
|
||||
backendName: mergedDestination.backendName,
|
||||
dependencyName: mergedDestination.dependencyName,
|
||||
spanType: mergedDestination.spanType,
|
||||
spanSubtype: mergedDestination.spanSubtype,
|
||||
id: objectHash({ backendName: mergedDestination.backendName }),
|
||||
type: NodeType.backend,
|
||||
id: objectHash({ dependencyName: mergedDestination.dependencyName }),
|
||||
type: NodeType.dependency,
|
||||
};
|
||||
}
|
||||
|
||||
nodesByBackendName.set(destination.backendName, node);
|
||||
nodesBydependencyName.set(destination.dependencyName, node);
|
||||
});
|
||||
|
||||
return nodesByBackendName;
|
||||
return nodesBydependencyName;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -88,7 +88,7 @@ export const getStats = async ({
|
|||
},
|
||||
},
|
||||
{
|
||||
backendName: {
|
||||
dependencyName: {
|
||||
terms: {
|
||||
field: SPAN_DESTINATION_SERVICE_RESOURCE,
|
||||
},
|
||||
|
@ -178,7 +178,7 @@ export const getStats = async ({
|
|||
response.aggregations?.connections.buckets.map((bucket) => {
|
||||
const sample = bucket.sample.top[0].metrics;
|
||||
const serviceName = bucket.key.serviceName as string;
|
||||
const backendName = bucket.key.backendName as string;
|
||||
const dependencyName = bucket.key.dependencyName as string;
|
||||
|
||||
return {
|
||||
from: {
|
||||
|
@ -190,11 +190,11 @@ export const getStats = async ({
|
|||
type: NodeType.service as const,
|
||||
},
|
||||
to: {
|
||||
id: objectHash({ backendName }),
|
||||
backendName,
|
||||
id: objectHash({ dependencyName }),
|
||||
dependencyName,
|
||||
spanType: sample[SPAN_TYPE] as string,
|
||||
spanSubtype: (sample[SPAN_SUBTYPE] || '') as string,
|
||||
type: NodeType.backend as const,
|
||||
type: NodeType.dependency as const,
|
||||
},
|
||||
value: {
|
||||
count: sum(
|
||||
|
|
|
@ -53,7 +53,8 @@ export function getConnectionStats({
|
|||
|
||||
const statsWithLocationIds = allMetrics.map((statsItem) => {
|
||||
const { from, timeseries, value } = statsItem;
|
||||
const to = destinationMap.get(statsItem.to.backendName) ?? statsItem.to;
|
||||
const to =
|
||||
destinationMap.get(statsItem.to.dependencyName) ?? statsItem.to;
|
||||
|
||||
const location = collapseBy === 'upstream' ? from : to;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import type {
|
|||
import { PickByValue } from 'utility-types';
|
||||
import { agentKeysRouteRepository } from '../agent_keys/route';
|
||||
import { alertsChartPreviewRouteRepository } from '../alerts/route';
|
||||
import { backendsRouteRepository } from '../backends/route';
|
||||
import { dependencisRouteRepository } from '../dependencies/route';
|
||||
import { correlationsRouteRepository } from '../correlations/route';
|
||||
import { dataViewRouteRepository } from '../data_view/route';
|
||||
import { debugTelemetryRoute } from '../debug_telemetry/route';
|
||||
|
@ -63,7 +63,7 @@ function getTypedGlobalApmServerRouteRepository() {
|
|||
...customLinkRouteRepository,
|
||||
...sourceMapsRouteRepository,
|
||||
...apmFleetRouteRepository,
|
||||
...backendsRouteRepository,
|
||||
...dependencisRouteRepository,
|
||||
...correlationsRouteRepository,
|
||||
...fallbackToTransactionsRouteRepository,
|
||||
...historicalDataRouteRepository,
|
||||
|
|
|
@ -1,145 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
kqlQuery,
|
||||
rangeQuery,
|
||||
termQuery,
|
||||
} from '@kbn/observability-plugin/server';
|
||||
import { EventOutcome } from '../../../common/event_outcome';
|
||||
import {
|
||||
EVENT_OUTCOME,
|
||||
SPAN_DESTINATION_SERVICE_RESOURCE,
|
||||
SPAN_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { environmentQuery } from '../../../common/utils/environment_query';
|
||||
import { Setup } from '../../lib/helpers/setup_request';
|
||||
import { getMetricsDateHistogramParams } from '../../lib/helpers/metrics';
|
||||
import { getOffsetInMs } from '../../../common/utils/get_offset_in_ms';
|
||||
import {
|
||||
getDocCountFieldForServiceDestinationStatistics,
|
||||
getDocumentTypeFilterForServiceDestinationStatistics,
|
||||
getProcessorEventForServiceDestinationStatistics,
|
||||
} from '../../lib/helpers/spans/get_is_using_service_destination_metrics';
|
||||
|
||||
export async function getErrorRateChartsForBackend({
|
||||
backendName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
environment,
|
||||
kuery,
|
||||
searchServiceDestinationMetrics,
|
||||
offset,
|
||||
}: {
|
||||
backendName: string;
|
||||
spanName: string;
|
||||
setup: Setup;
|
||||
start: number;
|
||||
end: number;
|
||||
environment: string;
|
||||
kuery: string;
|
||||
searchServiceDestinationMetrics: boolean;
|
||||
offset?: string;
|
||||
}) {
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const { offsetInMs, startWithOffset, endWithOffset } = getOffsetInMs({
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
});
|
||||
|
||||
const response = await apmEventClient.search('get_error_rate_for_backend', {
|
||||
apm: {
|
||||
events: [
|
||||
getProcessorEventForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...termQuery(SPAN_NAME, spanName || null),
|
||||
...getDocumentTypeFilterForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } },
|
||||
{
|
||||
terms: {
|
||||
[EVENT_OUTCOME]: [EventOutcome.success, EventOutcome.failure],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
timeseries: {
|
||||
date_histogram: getMetricsDateHistogramParams({
|
||||
start: startWithOffset,
|
||||
end: endWithOffset,
|
||||
metricsInterval: 60,
|
||||
}),
|
||||
aggs: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
total_count: {
|
||||
sum: {
|
||||
field: getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
failures: {
|
||||
filter: {
|
||||
term: {
|
||||
[EVENT_OUTCOME]: EventOutcome.failure,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
total_count: {
|
||||
sum: {
|
||||
field:
|
||||
getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
response.aggregations?.timeseries.buckets.map((bucket) => {
|
||||
const totalCount = bucket.total_count?.value ?? bucket.doc_count;
|
||||
const failureCount =
|
||||
bucket.failures.total_count?.value ?? bucket.failures.doc_count;
|
||||
|
||||
return {
|
||||
x: bucket.key + offsetInMs,
|
||||
y: failureCount / totalCount,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
}
|
|
@ -18,9 +18,9 @@ import { Setup } from '../../lib/helpers/setup_request';
|
|||
import { getOverallLatencyDistribution } from '../latency_distribution/get_overall_latency_distribution';
|
||||
import { OverallLatencyDistributionResponse } from '../latency_distribution/types';
|
||||
|
||||
export async function getBackendLatencyDistribution({
|
||||
export async function getDependencyLatencyDistribution({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
kuery,
|
||||
environment,
|
||||
|
@ -29,7 +29,7 @@ export async function getBackendLatencyDistribution({
|
|||
percentileThreshold,
|
||||
}: {
|
||||
setup: Setup;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
kuery: string;
|
||||
environment: Environment;
|
||||
|
@ -54,7 +54,7 @@ export async function getBackendLatencyDistribution({
|
|||
bool: {
|
||||
filter: [
|
||||
...termQuery(SPAN_NAME, spanName),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, backendName),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, dependencyName),
|
||||
],
|
||||
},
|
||||
};
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import {
|
||||
kqlQuery,
|
||||
rangeQuery,
|
||||
termQuery,
|
||||
} from '@kbn/observability-plugin/server';
|
||||
import { EventOutcome } from '../../../common/event_outcome';
|
||||
import {
|
||||
EVENT_OUTCOME,
|
||||
SPAN_DESTINATION_SERVICE_RESOURCE,
|
||||
SPAN_NAME,
|
||||
} from '../../../common/elasticsearch_fieldnames';
|
||||
import { environmentQuery } from '../../../common/utils/environment_query';
|
||||
import { Setup } from '../../lib/helpers/setup_request';
|
||||
import { getMetricsDateHistogramParams } from '../../lib/helpers/metrics';
|
||||
import { getOffsetInMs } from '../../../common/utils/get_offset_in_ms';
|
||||
import {
|
||||
getDocCountFieldForServiceDestinationStatistics,
|
||||
getDocumentTypeFilterForServiceDestinationStatistics,
|
||||
getProcessorEventForServiceDestinationStatistics,
|
||||
} from '../../lib/helpers/spans/get_is_using_service_destination_metrics';
|
||||
|
||||
export async function getErrorRateChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
environment,
|
||||
kuery,
|
||||
searchServiceDestinationMetrics,
|
||||
offset,
|
||||
}: {
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
setup: Setup;
|
||||
start: number;
|
||||
end: number;
|
||||
environment: string;
|
||||
kuery: string;
|
||||
searchServiceDestinationMetrics: boolean;
|
||||
offset?: string;
|
||||
}) {
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const { offsetInMs, startWithOffset, endWithOffset } = getOffsetInMs({
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
});
|
||||
|
||||
const response = await apmEventClient.search(
|
||||
'get_error_rate_for_dependency',
|
||||
{
|
||||
apm: {
|
||||
events: [
|
||||
getProcessorEventForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...termQuery(SPAN_NAME, spanName || null),
|
||||
...getDocumentTypeFilterForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName } },
|
||||
{
|
||||
terms: {
|
||||
[EVENT_OUTCOME]: [EventOutcome.success, EventOutcome.failure],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
timeseries: {
|
||||
date_histogram: getMetricsDateHistogramParams({
|
||||
start: startWithOffset,
|
||||
end: endWithOffset,
|
||||
metricsInterval: 60,
|
||||
}),
|
||||
aggs: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
total_count: {
|
||||
sum: {
|
||||
field: getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
failures: {
|
||||
filter: {
|
||||
term: {
|
||||
[EVENT_OUTCOME]: EventOutcome.failure,
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
total_count: {
|
||||
sum: {
|
||||
field:
|
||||
getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
response.aggregations?.timeseries.buckets.map((bucket) => {
|
||||
const totalCount = bucket.total_count?.value ?? bucket.doc_count;
|
||||
const failureCount =
|
||||
bucket.failures.total_count?.value ?? bucket.failures.doc_count;
|
||||
|
||||
return {
|
||||
x: bucket.key + offsetInMs,
|
||||
y: failureCount / totalCount,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
}
|
|
@ -25,8 +25,8 @@ import {
|
|||
getProcessorEventForServiceDestinationStatistics,
|
||||
} from '../../lib/helpers/spans/get_is_using_service_destination_metrics';
|
||||
|
||||
export async function getLatencyChartsForBackend({
|
||||
backendName,
|
||||
export async function getLatencyChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
searchServiceDestinationMetrics,
|
||||
setup,
|
||||
|
@ -36,7 +36,7 @@ export async function getLatencyChartsForBackend({
|
|||
kuery,
|
||||
offset,
|
||||
}: {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
searchServiceDestinationMetrics: boolean;
|
||||
setup: Setup;
|
||||
|
@ -54,7 +54,7 @@ export async function getLatencyChartsForBackend({
|
|||
offset,
|
||||
});
|
||||
|
||||
const response = await apmEventClient.search('get_latency_for_backend', {
|
||||
const response = await apmEventClient.search('get_latency_for_dependency', {
|
||||
apm: {
|
||||
events: [
|
||||
getProcessorEventForServiceDestinationStatistics(
|
||||
|
@ -74,7 +74,7 @@ export async function getLatencyChartsForBackend({
|
|||
...getDocumentTypeFilterForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } },
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName } },
|
||||
],
|
||||
},
|
||||
},
|
|
@ -11,42 +11,45 @@ import { ProcessorEvent } from '../../../common/processor_event';
|
|||
import { SPAN_DESTINATION_SERVICE_RESOURCE } from '../../../common/elasticsearch_fieldnames';
|
||||
import { Setup } from '../../lib/helpers/setup_request';
|
||||
|
||||
export async function getMetadataForBackend({
|
||||
export async function getMetadataForDependency({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
}: {
|
||||
setup: Setup;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
start: number;
|
||||
end: number;
|
||||
}) {
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const sampleResponse = await apmEventClient.search('get_backend_sample', {
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
[SPAN_DESTINATION_SERVICE_RESOURCE]: backendName,
|
||||
const sampleResponse = await apmEventClient.search(
|
||||
'get_metadata_for_dependency',
|
||||
{
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
body: {
|
||||
size: 1,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
[SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName,
|
||||
},
|
||||
},
|
||||
},
|
||||
...rangeQuery(start, end),
|
||||
],
|
||||
...rangeQuery(start, end),
|
||||
],
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
'@timestamp': 'desc',
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const sample = maybe(sampleResponse.hits.hits[0])?._source;
|
||||
|
|
@ -24,8 +24,8 @@ import {
|
|||
getProcessorEventForServiceDestinationStatistics,
|
||||
} from '../../lib/helpers/spans/get_is_using_service_destination_metrics';
|
||||
|
||||
export async function getThroughputChartsForBackend({
|
||||
backendName,
|
||||
export async function getThroughputChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
|
@ -35,7 +35,7 @@ export async function getThroughputChartsForBackend({
|
|||
searchServiceDestinationMetrics,
|
||||
offset,
|
||||
}: {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
setup: Setup;
|
||||
start: number;
|
||||
|
@ -59,56 +59,59 @@ export async function getThroughputChartsForBackend({
|
|||
minBucketSize: 60,
|
||||
});
|
||||
|
||||
const response = await apmEventClient.search('get_throughput_for_backend', {
|
||||
apm: {
|
||||
events: [
|
||||
getProcessorEventForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...termQuery(SPAN_NAME, spanName || null),
|
||||
...getDocumentTypeFilterForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } },
|
||||
],
|
||||
},
|
||||
const response = await apmEventClient.search(
|
||||
'get_throughput_for_dependency',
|
||||
{
|
||||
apm: {
|
||||
events: [
|
||||
getProcessorEventForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
],
|
||||
},
|
||||
aggs: {
|
||||
timeseries: {
|
||||
date_histogram: {
|
||||
field: '@timestamp',
|
||||
fixed_interval: intervalString,
|
||||
min_doc_count: 0,
|
||||
extended_bounds: { min: startWithOffset, max: endWithOffset },
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...termQuery(SPAN_NAME, spanName || null),
|
||||
...getDocumentTypeFilterForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName } },
|
||||
],
|
||||
},
|
||||
aggs: {
|
||||
throughput: {
|
||||
rate: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
field: getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
unit: 'minute',
|
||||
},
|
||||
aggs: {
|
||||
timeseries: {
|
||||
date_histogram: {
|
||||
field: '@timestamp',
|
||||
fixed_interval: intervalString,
|
||||
min_doc_count: 0,
|
||||
extended_bounds: { min: startWithOffset, max: endWithOffset },
|
||||
},
|
||||
aggs: {
|
||||
throughput: {
|
||||
rate: {
|
||||
...(searchServiceDestinationMetrics
|
||||
? {
|
||||
field: getDocCountFieldForServiceDestinationStatistics(
|
||||
searchServiceDestinationMetrics
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
unit: 'minute',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
response.aggregations?.timeseries.buckets.map((bucket) => {
|
|
@ -12,7 +12,7 @@ import { getConnectionStats } from '../../lib/connections/get_connection_stats';
|
|||
import { getConnectionStatsItemsWithRelativeImpact } from '../../lib/connections/get_connection_stats/get_connection_stats_items_with_relative_impact';
|
||||
import { Setup } from '../../lib/helpers/setup_request';
|
||||
|
||||
export async function getTopBackends({
|
||||
export async function getTopDependencies({
|
||||
setup,
|
||||
start,
|
||||
end,
|
|
@ -31,7 +31,7 @@ import { calculateImpactBuilder } from '../traces/calculate_impact_builder';
|
|||
|
||||
const MAX_NUM_OPERATIONS = 500;
|
||||
|
||||
export interface BackendOperation {
|
||||
export interface DependencyOperation {
|
||||
spanName: string;
|
||||
latency: number | null;
|
||||
throughput: number;
|
||||
|
@ -43,9 +43,9 @@ export interface BackendOperation {
|
|||
>;
|
||||
}
|
||||
|
||||
export async function getTopBackendOperations({
|
||||
export async function getTopDependencyOperations({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -53,7 +53,7 @@ export async function getTopBackendOperations({
|
|||
kuery,
|
||||
}: {
|
||||
setup: Setup;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
start: number;
|
||||
end: number;
|
||||
offset?: string;
|
||||
|
@ -90,48 +90,51 @@ export async function getTopBackendOperations({
|
|||
},
|
||||
};
|
||||
|
||||
const response = await apmEventClient.search('get_top_backend_operations', {
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, backendName),
|
||||
],
|
||||
},
|
||||
const response = await apmEventClient.search(
|
||||
'get_top_dependency_operations',
|
||||
{
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
aggs: {
|
||||
operationName: {
|
||||
terms: {
|
||||
field: SPAN_NAME,
|
||||
size: MAX_NUM_OPERATIONS,
|
||||
body: {
|
||||
size: 0,
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, dependencyName),
|
||||
],
|
||||
},
|
||||
aggs: {
|
||||
over_time: {
|
||||
date_histogram: getMetricsDateHistogramParams({
|
||||
start: startWithOffset,
|
||||
end: endWithOffset,
|
||||
metricsInterval: 60,
|
||||
}),
|
||||
aggs,
|
||||
},
|
||||
aggs: {
|
||||
operationName: {
|
||||
terms: {
|
||||
field: SPAN_NAME,
|
||||
size: MAX_NUM_OPERATIONS,
|
||||
},
|
||||
...aggs,
|
||||
total_time: {
|
||||
sum: {
|
||||
field: SPAN_DURATION,
|
||||
aggs: {
|
||||
over_time: {
|
||||
date_histogram: getMetricsDateHistogramParams({
|
||||
start: startWithOffset,
|
||||
end: endWithOffset,
|
||||
metricsInterval: 60,
|
||||
}),
|
||||
aggs,
|
||||
},
|
||||
...aggs,
|
||||
total_time: {
|
||||
sum: {
|
||||
field: SPAN_DURATION,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const getImpact = calculateImpactBuilder(
|
||||
response.aggregations?.operationName.buckets.map(
|
||||
|
@ -141,8 +144,8 @@ export async function getTopBackendOperations({
|
|||
|
||||
return (
|
||||
response.aggregations?.operationName.buckets.map(
|
||||
(bucket): BackendOperation => {
|
||||
const timeseries: BackendOperation['timeseries'] = {
|
||||
(bucket): DependencyOperation => {
|
||||
const timeseries: DependencyOperation['timeseries'] = {
|
||||
latency: [],
|
||||
throughput: [],
|
||||
failureRate: [],
|
|
@ -34,7 +34,7 @@ import { Setup } from '../../lib/helpers/setup_request';
|
|||
|
||||
const MAX_NUM_SPANS = 1000;
|
||||
|
||||
export interface BackendSpan {
|
||||
export interface DependencySpan {
|
||||
'@timestamp': number;
|
||||
spanName: string;
|
||||
serviceName: string;
|
||||
|
@ -47,9 +47,9 @@ export interface BackendSpan {
|
|||
outcome: EventOutcome;
|
||||
}
|
||||
|
||||
export async function getTopBackendSpans({
|
||||
export async function getTopDependencySpans({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
start,
|
||||
end,
|
||||
|
@ -59,7 +59,7 @@ export async function getTopBackendSpans({
|
|||
sampleRangeTo,
|
||||
}: {
|
||||
setup: Setup;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
start: number;
|
||||
end: number;
|
||||
|
@ -67,11 +67,11 @@ export async function getTopBackendSpans({
|
|||
kuery: string;
|
||||
sampleRangeFrom?: number;
|
||||
sampleRangeTo?: number;
|
||||
}): Promise<BackendSpan[]> {
|
||||
}): Promise<DependencySpan[]> {
|
||||
const { apmEventClient } = setup;
|
||||
|
||||
const spans = (
|
||||
await apmEventClient.search('get_top_backend_spans', {
|
||||
await apmEventClient.search('get_top_dependency_spans', {
|
||||
apm: {
|
||||
events: [ProcessorEvent.span],
|
||||
},
|
||||
|
@ -83,7 +83,7 @@ export async function getTopBackendSpans({
|
|||
...rangeQuery(start, end),
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, backendName),
|
||||
...termQuery(SPAN_DESTINATION_SERVICE_RESOURCE, dependencyName),
|
||||
...termQuery(SPAN_NAME, spanName),
|
||||
...((sampleRangeFrom ?? 0) >= 0 && (sampleRangeTo ?? 0) > 0
|
||||
? [
|
||||
|
@ -118,7 +118,7 @@ export async function getTopBackendSpans({
|
|||
const transactionIds = compact(spans.map((span) => span.transaction?.id));
|
||||
|
||||
const transactions = (
|
||||
await apmEventClient.search('get_transactions_for_backend_spans', {
|
||||
await apmEventClient.search('get_transactions_for_dependency_spans', {
|
||||
apm: {
|
||||
events: [ProcessorEvent.transaction],
|
||||
},
|
||||
|
@ -142,7 +142,7 @@ export async function getTopBackendSpans({
|
|||
(transaction) => transaction.transaction.id
|
||||
);
|
||||
|
||||
return spans.map((span): BackendSpan => {
|
||||
return spans.map((span): DependencySpan => {
|
||||
const transaction = span.transaction
|
||||
? transactionsById[span.transaction.id]
|
||||
: undefined;
|
|
@ -12,11 +12,11 @@ import { getConnectionStats } from '../../lib/connections/get_connection_stats';
|
|||
import { getConnectionStatsItemsWithRelativeImpact } from '../../lib/connections/get_connection_stats/get_connection_stats_items_with_relative_impact';
|
||||
import { Setup } from '../../lib/helpers/setup_request';
|
||||
|
||||
export async function getUpstreamServicesForBackend({
|
||||
export async function getUpstreamServicesForDependency({
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
backendName,
|
||||
dependencyName,
|
||||
numBuckets,
|
||||
kuery,
|
||||
environment,
|
||||
|
@ -25,7 +25,7 @@ export async function getUpstreamServicesForBackend({
|
|||
setup: Setup;
|
||||
start: number;
|
||||
end: number;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
numBuckets: number;
|
||||
kuery: string;
|
||||
environment: string;
|
||||
|
@ -36,7 +36,7 @@ export async function getUpstreamServicesForBackend({
|
|||
start,
|
||||
end,
|
||||
filter: [
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } },
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName } },
|
||||
...environmentQuery(environment),
|
||||
...kqlQuery(kuery),
|
||||
],
|
|
@ -10,24 +10,27 @@ import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
|||
import { setupRequest } from '../../lib/helpers/setup_request';
|
||||
import { environmentRt, kueryRt, rangeRt } from '../default_api_types';
|
||||
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
|
||||
import { getMetadataForBackend } from './get_metadata_for_backend';
|
||||
import { getLatencyChartsForBackend } from './get_latency_charts_for_backend';
|
||||
import { getTopBackends } from './get_top_backends';
|
||||
import { getUpstreamServicesForBackend } from './get_upstream_services_for_backend';
|
||||
import { getThroughputChartsForBackend } from './get_throughput_charts_for_backend';
|
||||
import { getErrorRateChartsForBackend } from './get_error_rate_charts_for_backend';
|
||||
import { getMetadataForDependency } from './get_metadata_for_dependency';
|
||||
import { getLatencyChartsForDependency } from './get_latency_charts_for_dependency';
|
||||
import { getTopDependencies } from './get_top_dependencies';
|
||||
import { getUpstreamServicesForDependency } from './get_upstream_services_for_dependency';
|
||||
import { getThroughputChartsForDependency } from './get_throughput_charts_for_dependency';
|
||||
import { getErrorRateChartsForDependency } from './get_error_rate_charts_for_dependency';
|
||||
import { ConnectionStatsItemWithImpact } from '../../../common/connections';
|
||||
import { offsetRt } from '../../../common/comparison_rt';
|
||||
import {
|
||||
BackendOperation,
|
||||
getTopBackendOperations,
|
||||
} from './get_top_backend_operations';
|
||||
import { getBackendLatencyDistribution } from './get_backend_latency_distribution';
|
||||
DependencyOperation,
|
||||
getTopDependencyOperations,
|
||||
} from './get_top_dependency_operations';
|
||||
import { getDependencyLatencyDistribution } from './get_dependency_latency_distribution';
|
||||
import { OverallLatencyDistributionResponse } from '../latency_distribution/types';
|
||||
import { BackendSpan, getTopBackendSpans } from './get_top_backend_spans';
|
||||
import {
|
||||
DependencySpan,
|
||||
getTopDependencySpans,
|
||||
} from './get_top_dependency_spans';
|
||||
|
||||
const topBackendsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/top_backends',
|
||||
const topDependenciesRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/top_dependencies',
|
||||
params: t.intersection([
|
||||
t.type({
|
||||
query: t.intersection([
|
||||
|
@ -47,7 +50,7 @@ const topBackendsRoute = createApmServerRoute({
|
|||
handler: async (
|
||||
resources
|
||||
): Promise<{
|
||||
backends: Array<{
|
||||
dependencies: Array<{
|
||||
currentStats: {
|
||||
latency: {
|
||||
value: number | null;
|
||||
|
@ -103,17 +106,17 @@ const topBackendsRoute = createApmServerRoute({
|
|||
|
||||
const opts = { setup, start, end, numBuckets, environment, kuery };
|
||||
|
||||
const [currentBackends, previousBackends] = await Promise.all([
|
||||
getTopBackends(opts),
|
||||
offset ? getTopBackends({ ...opts, offset }) : Promise.resolve([]),
|
||||
const [currentDependencies, previousDependencies] = await Promise.all([
|
||||
getTopDependencies(opts),
|
||||
offset ? getTopDependencies({ ...opts, offset }) : Promise.resolve([]),
|
||||
]);
|
||||
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
backends: currentBackends.map((backend) => {
|
||||
const { stats, ...rest } = backend;
|
||||
const prev = previousBackends.find(
|
||||
(item): boolean => item.location.id === backend.location.id
|
||||
dependencies: currentDependencies.map((dependency) => {
|
||||
const { stats, ...rest } = dependency;
|
||||
const prev = previousDependencies.find(
|
||||
(item): boolean => item.location.id === dependency.location.id
|
||||
);
|
||||
return {
|
||||
...rest,
|
||||
|
@ -125,12 +128,12 @@ const topBackendsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const upstreamServicesForBackendRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/upstream_services',
|
||||
const upstreamServicesForDependencyRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/upstream_services',
|
||||
params: t.intersection([
|
||||
t.type({
|
||||
query: t.intersection([
|
||||
t.type({ backendName: t.string }),
|
||||
t.type({ dependencyName: t.string }),
|
||||
rangeRt,
|
||||
t.type({ numBuckets: toNumberRt }),
|
||||
]),
|
||||
|
@ -198,7 +201,7 @@ const upstreamServicesForBackendRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment,
|
||||
offset,
|
||||
numBuckets,
|
||||
|
@ -209,7 +212,7 @@ const upstreamServicesForBackendRoute = createApmServerRoute({
|
|||
} = resources.params;
|
||||
|
||||
const opts = {
|
||||
backendName,
|
||||
dependencyName,
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
|
@ -219,9 +222,9 @@ const upstreamServicesForBackendRoute = createApmServerRoute({
|
|||
};
|
||||
|
||||
const [currentServices, previousServices] = await Promise.all([
|
||||
getUpstreamServicesForBackend(opts),
|
||||
getUpstreamServicesForDependency(opts),
|
||||
offset
|
||||
? getUpstreamServicesForBackend({ ...opts, offset })
|
||||
? getUpstreamServicesForDependency({ ...opts, offset })
|
||||
: Promise.resolve([]),
|
||||
]);
|
||||
|
||||
|
@ -248,10 +251,10 @@ const upstreamServicesForBackendRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendMetadataRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/metadata',
|
||||
const dependencyMetadataRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/metadata',
|
||||
params: t.type({
|
||||
query: t.intersection([t.type({ backendName: t.string }), rangeRt]),
|
||||
query: t.intersection([t.type({ dependencyName: t.string }), rangeRt]),
|
||||
}),
|
||||
options: {
|
||||
tags: ['access:apm'],
|
||||
|
@ -264,10 +267,10 @@ const backendMetadataRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const { params } = resources;
|
||||
|
||||
const { backendName, start, end } = params.query;
|
||||
const { dependencyName, start, end } = params.query;
|
||||
|
||||
const metadata = await getMetadataForBackend({
|
||||
backendName,
|
||||
const metadata = await getMetadataForDependency({
|
||||
dependencyName,
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
|
@ -277,12 +280,12 @@ const backendMetadataRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendLatencyChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/charts/latency',
|
||||
const dependencyLatencyChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/charts/latency',
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
backendName: t.string,
|
||||
dependencyName: t.string,
|
||||
spanName: t.string,
|
||||
searchServiceDestinationMetrics: toBooleanRt,
|
||||
}),
|
||||
|
@ -304,7 +307,7 @@ const backendLatencyChartsRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const { params } = resources;
|
||||
const {
|
||||
backendName,
|
||||
dependencyName,
|
||||
searchServiceDestinationMetrics,
|
||||
spanName,
|
||||
kuery,
|
||||
|
@ -315,8 +318,8 @@ const backendLatencyChartsRoute = createApmServerRoute({
|
|||
} = params.query;
|
||||
|
||||
const [currentTimeseries, comparisonTimeseries] = await Promise.all([
|
||||
getLatencyChartsForBackend({
|
||||
backendName,
|
||||
getLatencyChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
searchServiceDestinationMetrics,
|
||||
setup,
|
||||
|
@ -326,8 +329,8 @@ const backendLatencyChartsRoute = createApmServerRoute({
|
|||
environment,
|
||||
}),
|
||||
offset
|
||||
? getLatencyChartsForBackend({
|
||||
backendName,
|
||||
? getLatencyChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
searchServiceDestinationMetrics,
|
||||
setup,
|
||||
|
@ -344,12 +347,12 @@ const backendLatencyChartsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendThroughputChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/charts/throughput',
|
||||
const dependencyThroughputChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/charts/throughput',
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
backendName: t.string,
|
||||
dependencyName: t.string,
|
||||
spanName: t.string,
|
||||
searchServiceDestinationMetrics: toBooleanRt,
|
||||
}),
|
||||
|
@ -371,7 +374,7 @@ const backendThroughputChartsRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const { params } = resources;
|
||||
const {
|
||||
backendName,
|
||||
dependencyName,
|
||||
searchServiceDestinationMetrics,
|
||||
spanName,
|
||||
kuery,
|
||||
|
@ -382,8 +385,8 @@ const backendThroughputChartsRoute = createApmServerRoute({
|
|||
} = params.query;
|
||||
|
||||
const [currentTimeseries, comparisonTimeseries] = await Promise.all([
|
||||
getThroughputChartsForBackend({
|
||||
backendName,
|
||||
getThroughputChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
|
@ -393,8 +396,8 @@ const backendThroughputChartsRoute = createApmServerRoute({
|
|||
searchServiceDestinationMetrics,
|
||||
}),
|
||||
offset
|
||||
? getThroughputChartsForBackend({
|
||||
backendName,
|
||||
? getThroughputChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
|
@ -411,12 +414,12 @@ const backendThroughputChartsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendFailedTransactionRateChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/charts/error_rate',
|
||||
const dependencyFailedTransactionRateChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/charts/error_rate',
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
backendName: t.string,
|
||||
dependencyName: t.string,
|
||||
spanName: t.string,
|
||||
searchServiceDestinationMetrics: toBooleanRt,
|
||||
}),
|
||||
|
@ -438,7 +441,7 @@ const backendFailedTransactionRateChartsRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const { params } = resources;
|
||||
const {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
searchServiceDestinationMetrics,
|
||||
kuery,
|
||||
|
@ -449,8 +452,8 @@ const backendFailedTransactionRateChartsRoute = createApmServerRoute({
|
|||
} = params.query;
|
||||
|
||||
const [currentTimeseries, comparisonTimeseries] = await Promise.all([
|
||||
getErrorRateChartsForBackend({
|
||||
backendName,
|
||||
getErrorRateChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
|
@ -460,8 +463,8 @@ const backendFailedTransactionRateChartsRoute = createApmServerRoute({
|
|||
searchServiceDestinationMetrics,
|
||||
}),
|
||||
offset
|
||||
? getErrorRateChartsForBackend({
|
||||
backendName,
|
||||
? getErrorRateChartsForDependency({
|
||||
dependencyName,
|
||||
spanName,
|
||||
setup,
|
||||
start,
|
||||
|
@ -478,8 +481,8 @@ const backendFailedTransactionRateChartsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendOperationsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/operations',
|
||||
const dependencyOperationsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/operations',
|
||||
options: {
|
||||
tags: ['access:apm'],
|
||||
},
|
||||
|
@ -489,19 +492,21 @@ const backendOperationsRoute = createApmServerRoute({
|
|||
environmentRt,
|
||||
kueryRt,
|
||||
offsetRt,
|
||||
t.type({ backendName: t.string }),
|
||||
t.type({ dependencyName: t.string }),
|
||||
]),
|
||||
}),
|
||||
handler: async (resources): Promise<{ operations: BackendOperation[] }> => {
|
||||
handler: async (
|
||||
resources
|
||||
): Promise<{ operations: DependencyOperation[] }> => {
|
||||
const setup = await setupRequest(resources);
|
||||
|
||||
const {
|
||||
query: { backendName, start, end, environment, kuery, offset },
|
||||
query: { dependencyName, start, end, environment, kuery, offset },
|
||||
} = resources.params;
|
||||
|
||||
const operations = await getTopBackendOperations({
|
||||
const operations = await getTopDependencyOperations({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
|
@ -513,12 +518,12 @@ const backendOperationsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const backendLatencyDistributionChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/charts/distribution',
|
||||
const dependencyLatencyDistributionChartsRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/charts/distribution',
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({
|
||||
backendName: t.string,
|
||||
dependencyName: t.string,
|
||||
spanName: t.string,
|
||||
percentileThreshold: toNumberRt,
|
||||
}),
|
||||
|
@ -539,7 +544,7 @@ const backendLatencyDistributionChartsRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
const { params } = resources;
|
||||
const {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
percentileThreshold,
|
||||
kuery,
|
||||
|
@ -548,9 +553,9 @@ const backendLatencyDistributionChartsRoute = createApmServerRoute({
|
|||
end,
|
||||
} = params.query;
|
||||
|
||||
return getBackendLatencyDistribution({
|
||||
return getDependencyLatencyDistribution({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
percentileThreshold,
|
||||
kuery,
|
||||
|
@ -561,8 +566,8 @@ const backendLatencyDistributionChartsRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const topBackendSpansRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/backends/operations/spans',
|
||||
const topDependencySpansRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/dependencies/operations/spans',
|
||||
options: {
|
||||
tags: ['access:apm'],
|
||||
},
|
||||
|
@ -571,16 +576,16 @@ const topBackendSpansRoute = createApmServerRoute({
|
|||
rangeRt,
|
||||
environmentRt,
|
||||
kueryRt,
|
||||
t.type({ backendName: t.string, spanName: t.string }),
|
||||
t.type({ dependencyName: t.string, spanName: t.string }),
|
||||
t.partial({ sampleRangeFrom: toNumberRt, sampleRangeTo: toNumberRt }),
|
||||
]),
|
||||
}),
|
||||
handler: async (resources): Promise<{ spans: BackendSpan[] }> => {
|
||||
handler: async (resources): Promise<{ spans: DependencySpan[] }> => {
|
||||
const setup = await setupRequest(resources);
|
||||
|
||||
const {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
start,
|
||||
end,
|
||||
|
@ -591,9 +596,9 @@ const topBackendSpansRoute = createApmServerRoute({
|
|||
},
|
||||
} = resources.params;
|
||||
|
||||
const spans = await getTopBackendSpans({
|
||||
const spans = await getTopDependencySpans({
|
||||
setup,
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
start,
|
||||
end,
|
||||
|
@ -607,14 +612,14 @@ const topBackendSpansRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
export const backendsRouteRepository = {
|
||||
...topBackendsRoute,
|
||||
...upstreamServicesForBackendRoute,
|
||||
...backendMetadataRoute,
|
||||
...backendLatencyChartsRoute,
|
||||
...backendThroughputChartsRoute,
|
||||
...backendFailedTransactionRateChartsRoute,
|
||||
...backendOperationsRoute,
|
||||
...backendLatencyDistributionChartsRoute,
|
||||
...topBackendSpansRoute,
|
||||
export const dependencisRouteRepository = {
|
||||
...topDependenciesRoute,
|
||||
...upstreamServicesForDependencyRoute,
|
||||
...dependencyMetadataRoute,
|
||||
...dependencyLatencyChartsRoute,
|
||||
...dependencyThroughputChartsRoute,
|
||||
...dependencyFailedTransactionRateChartsRoute,
|
||||
...dependencyOperationsRoute,
|
||||
...dependencyLatencyDistributionChartsRoute,
|
||||
...topDependencySpansRoute,
|
||||
};
|
|
@ -26,21 +26,21 @@ import { getOffsetInMs } from '../../../common/utils/get_offset_in_ms';
|
|||
interface Options {
|
||||
setup: Setup;
|
||||
environment: string;
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
start: number;
|
||||
end: number;
|
||||
offset?: string;
|
||||
}
|
||||
|
||||
export function getServiceMapBackendNodeInfo({
|
||||
export function getServiceMapDependencyNodeInfo({
|
||||
environment,
|
||||
backendName,
|
||||
dependencyName,
|
||||
setup,
|
||||
start,
|
||||
end,
|
||||
offset,
|
||||
}: Options): Promise<NodeStats> {
|
||||
return withApmSpan('get_service_map_backend_node_stats', async () => {
|
||||
return withApmSpan('get_service_map_dependency_node_stats', async () => {
|
||||
const { apmEventClient } = setup;
|
||||
const { offsetInMs, startWithOffset, endWithOffset } = getOffsetInMs({
|
||||
start,
|
||||
|
@ -67,7 +67,7 @@ export function getServiceMapBackendNodeInfo({
|
|||
};
|
||||
|
||||
const response = await apmEventClient.search(
|
||||
'get_service_map_backend_node_stats',
|
||||
'get_service_map_dependency_node_stats',
|
||||
{
|
||||
apm: {
|
||||
events: [ProcessorEvent.metric],
|
||||
|
@ -77,7 +77,9 @@ export function getServiceMapBackendNodeInfo({
|
|||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: backendName } },
|
||||
{
|
||||
term: { [SPAN_DESTINATION_SERVICE_RESOURCE]: dependencyName },
|
||||
},
|
||||
...rangeQuery(startWithOffset, endWithOffset),
|
||||
...environmentQuery(environment),
|
||||
],
|
|
@ -13,7 +13,7 @@ import { notifyFeatureUsage } from '../../feature';
|
|||
import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions';
|
||||
import { setupRequest } from '../../lib/helpers/setup_request';
|
||||
import { getServiceMap } from './get_service_map';
|
||||
import { getServiceMapBackendNodeInfo } from './get_service_map_backend_node_info';
|
||||
import { getServiceMapDependencyNodeInfo } from './get_service_map_dependency_node_info';
|
||||
import { getServiceMapServiceNodeInfo } from './get_service_map_service_node_info';
|
||||
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
|
||||
import { environmentRt, rangeRt } from '../default_api_types';
|
||||
|
@ -206,11 +206,11 @@ const serviceMapServiceNodeRoute = createApmServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const serviceMapBackendNodeRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/service-map/backend',
|
||||
const serviceMapDependencyNodeRoute = createApmServerRoute({
|
||||
endpoint: 'GET /internal/apm/service-map/dependency',
|
||||
params: t.type({
|
||||
query: t.intersection([
|
||||
t.type({ backendName: t.string }),
|
||||
t.type({ dependencyName: t.string }),
|
||||
environmentRt,
|
||||
rangeRt,
|
||||
offsetRt,
|
||||
|
@ -237,15 +237,15 @@ const serviceMapBackendNodeRoute = createApmServerRoute({
|
|||
const setup = await setupRequest(resources);
|
||||
|
||||
const {
|
||||
query: { backendName, environment, start, end, offset },
|
||||
query: { dependencyName, environment, start, end, offset },
|
||||
} = params;
|
||||
|
||||
const commonProps = { environment, setup, backendName, start, end };
|
||||
const commonProps = { environment, setup, dependencyName, start, end };
|
||||
|
||||
const [currentPeriod, previousPeriod] = await Promise.all([
|
||||
getServiceMapBackendNodeInfo(commonProps),
|
||||
getServiceMapDependencyNodeInfo(commonProps),
|
||||
offset
|
||||
? getServiceMapBackendNodeInfo({ ...commonProps, offset })
|
||||
? getServiceMapDependencyNodeInfo({ ...commonProps, offset })
|
||||
: undefined,
|
||||
]);
|
||||
|
||||
|
@ -256,5 +256,5 @@ const serviceMapBackendNodeRoute = createApmServerRoute({
|
|||
export const serviceMapRouteRepository = {
|
||||
...serviceMapRoute,
|
||||
...serviceMapServiceNodeRoute,
|
||||
...serviceMapBackendNodeRoute,
|
||||
...serviceMapDependencyNodeRoute,
|
||||
};
|
||||
|
|
|
@ -7555,15 +7555,6 @@
|
|||
"xpack.apm.apmSchema.index": "Schéma du serveur APM - Index",
|
||||
"xpack.apm.apmServiceGroups.index": "Groupes de services APM - Index",
|
||||
"xpack.apm.apmSettings.index": "Paramètres APM - Index",
|
||||
"xpack.apm.backendDetail.dependenciesTableColumnBackend": "Service",
|
||||
"xpack.apm.backendDetail.dependenciesTableTitle": "Services en amont",
|
||||
"xpack.apm.backendDetailFailedTransactionRateChartTitle": "Taux de transactions ayant échoué",
|
||||
"xpack.apm.backendDetailLatencyChartTitle": "Latence",
|
||||
"xpack.apm.backendDetailThroughputChartTitle": "Rendement",
|
||||
"xpack.apm.backendErrorRateChart.chartTitle": "Taux de transactions ayant échoué",
|
||||
"xpack.apm.backendInventory.dependencyTableColumn": "Dépendance",
|
||||
"xpack.apm.backendLatencyChart.chartTitle": "Latence",
|
||||
"xpack.apm.backendThroughputChart.chartTitle": "Rendement",
|
||||
"xpack.apm.chart.annotation.version": "Version",
|
||||
"xpack.apm.chart.cpuSeries.processAverageLabel": "Moyenne de processus",
|
||||
"xpack.apm.chart.cpuSeries.processMaxLabel": "Max de processus",
|
||||
|
|
|
@ -7549,15 +7549,6 @@
|
|||
"xpack.apm.apmSchema.index": "APMサーバースキーマ - インデックス",
|
||||
"xpack.apm.apmServiceGroups.index": "APMサービスグループ - インデックス",
|
||||
"xpack.apm.apmSettings.index": "APM 設定 - インデックス",
|
||||
"xpack.apm.backendDetail.dependenciesTableColumnBackend": "サービス",
|
||||
"xpack.apm.backendDetail.dependenciesTableTitle": "アップストリームサービス",
|
||||
"xpack.apm.backendDetailFailedTransactionRateChartTitle": "失敗したトランザクション率",
|
||||
"xpack.apm.backendDetailLatencyChartTitle": "レイテンシ",
|
||||
"xpack.apm.backendDetailThroughputChartTitle": "スループット",
|
||||
"xpack.apm.backendErrorRateChart.chartTitle": "失敗したトランザクション率",
|
||||
"xpack.apm.backendInventory.dependencyTableColumn": "依存関係",
|
||||
"xpack.apm.backendLatencyChart.chartTitle": "レイテンシ",
|
||||
"xpack.apm.backendThroughputChart.chartTitle": "スループット",
|
||||
"xpack.apm.chart.annotation.version": "バージョン",
|
||||
"xpack.apm.chart.cpuSeries.processAverageLabel": "プロセス平均",
|
||||
"xpack.apm.chart.cpuSeries.processMaxLabel": "プロセス最大",
|
||||
|
|
|
@ -7561,15 +7561,6 @@
|
|||
"xpack.apm.apmSchema.index": "APM Server 架构 - 索引",
|
||||
"xpack.apm.apmServiceGroups.index": "APM 服务组 - 索引",
|
||||
"xpack.apm.apmSettings.index": "APM 设置 - 索引",
|
||||
"xpack.apm.backendDetail.dependenciesTableColumnBackend": "服务",
|
||||
"xpack.apm.backendDetail.dependenciesTableTitle": "上游服务",
|
||||
"xpack.apm.backendDetailFailedTransactionRateChartTitle": "失败事务率",
|
||||
"xpack.apm.backendDetailLatencyChartTitle": "延迟",
|
||||
"xpack.apm.backendDetailThroughputChartTitle": "吞吐量",
|
||||
"xpack.apm.backendErrorRateChart.chartTitle": "失败事务率",
|
||||
"xpack.apm.backendInventory.dependencyTableColumn": "依赖项",
|
||||
"xpack.apm.backendLatencyChart.chartTitle": "延迟",
|
||||
"xpack.apm.backendThroughputChart.chartTitle": "吞吐量",
|
||||
"xpack.apm.chart.annotation.version": "版本",
|
||||
"xpack.apm.chart.cpuSeries.processAverageLabel": "进程平均值",
|
||||
"xpack.apm.chart.cpuSeries.processMaxLabel": "进程最大值",
|
||||
|
|
|
@ -33,27 +33,27 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
|
||||
async function callApi<TMetricName extends 'latency' | 'throughput' | 'error_rate'>({
|
||||
backendName,
|
||||
dependencyName,
|
||||
searchServiceDestinationMetrics,
|
||||
spanName = '',
|
||||
metric,
|
||||
kuery = '',
|
||||
environment = ENVIRONMENT_ALL.value,
|
||||
}: {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
searchServiceDestinationMetrics: boolean;
|
||||
spanName?: string;
|
||||
metric: TMetricName;
|
||||
kuery?: string;
|
||||
environment?: string;
|
||||
}): Promise<SupertestReturnType<`GET /internal/apm/backends/charts/${TMetricName}`>> {
|
||||
}): Promise<SupertestReturnType<`GET /internal/apm/dependencies/charts/${TMetricName}`>> {
|
||||
return await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/charts/${
|
||||
endpoint: `GET /internal/apm/dependencies/charts/${
|
||||
metric as 'latency' | 'throughput' | 'error_rate'
|
||||
}`,
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
environment,
|
||||
|
@ -80,7 +80,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
() => {
|
||||
it('handles empty state', async () => {
|
||||
const { body, status } = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
metric: 'latency',
|
||||
searchServiceDestinationMetrics: true,
|
||||
});
|
||||
|
@ -110,7 +110,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('without a kuery or environment', () => {
|
||||
it('returns the correct latency', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'latency',
|
||||
|
@ -131,7 +131,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct throughput', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'redis',
|
||||
dependencyName: 'redis',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'throughput',
|
||||
|
@ -142,7 +142,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct failure rate', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'error_rate',
|
||||
|
@ -158,7 +158,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('with a kuery', () => {
|
||||
it('returns the correct latency', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'latency',
|
||||
|
@ -179,7 +179,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct throughput', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'throughput',
|
||||
|
@ -194,7 +194,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct failure rate', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'error_rate',
|
||||
|
@ -208,7 +208,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('with an environment', () => {
|
||||
it('returns the correct latency', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'latency',
|
||||
|
@ -229,7 +229,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct throughput', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'throughput',
|
||||
|
@ -245,7 +245,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct failure rate', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: true,
|
||||
spanName: '',
|
||||
metric: 'error_rate',
|
||||
|
@ -260,7 +260,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('with spanName', () => {
|
||||
it('returns the correct latency', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: false,
|
||||
spanName: '/_search',
|
||||
metric: 'latency',
|
||||
|
@ -281,7 +281,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct throughput', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'redis',
|
||||
dependencyName: 'redis',
|
||||
searchServiceDestinationMetrics: false,
|
||||
spanName: 'SET',
|
||||
metric: 'throughput',
|
||||
|
@ -292,7 +292,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
it('returns the correct failure rate', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
searchServiceDestinationMetrics: false,
|
||||
spanName: '/_bulk',
|
||||
metric: 'error_rate',
|
||||
|
|
|
@ -18,10 +18,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
async function callApi() {
|
||||
return await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/metadata`,
|
||||
endpoint: `GET /internal/apm/dependencies/metadata`,
|
||||
params: {
|
||||
query: {
|
||||
backendName: dataConfig.span.destination,
|
||||
dependencyName: dataConfig.span.destination,
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import expect from '@kbn/expect';
|
||||
import { BackendNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { DependencyNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { generateData } from './generate_data';
|
||||
|
||||
|
@ -15,7 +15,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const registry = getService('registry');
|
||||
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
|
||||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
const backendName = 'elasticsearch';
|
||||
const dependencyName = 'elasticsearch';
|
||||
const serviceName = 'synth-go';
|
||||
|
||||
async function callApi() {
|
||||
|
@ -62,8 +62,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
expect(status).to.be(200);
|
||||
expect(
|
||||
body.serviceDependencies.map(({ location }) => (location as BackendNode).backendName)
|
||||
).to.eql([backendName]);
|
||||
body.serviceDependencies.map(
|
||||
({ location }) => (location as DependencyNode).dependencyName
|
||||
)
|
||||
).to.eql([dependencyName]);
|
||||
|
||||
const currentStatsLatencyValues =
|
||||
body.serviceDependencies[0].currentStats.latency.timeseries;
|
||||
|
@ -101,8 +103,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
expect(status).to.be(200);
|
||||
expect(
|
||||
body.serviceDependencies.map(({ location }) => (location as BackendNode).backendName)
|
||||
).to.eql([backendName]);
|
||||
body.serviceDependencies.map(
|
||||
({ location }) => (location as DependencyNode).dependencyName
|
||||
)
|
||||
).to.eql([dependencyName]);
|
||||
|
||||
const currentStatsLatencyValues =
|
||||
body.serviceDependencies[0].currentStats.latency.timeseries;
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
*/
|
||||
import expect from '@kbn/expect';
|
||||
import { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
|
||||
import { NodeType, BackendNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { NodeType, DependencyNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { dataConfig, generateData } from './generate_data';
|
||||
import { roundNumber } from '../../utils';
|
||||
|
||||
type TopDependencies = APIReturnType<'GET /internal/apm/backends/top_backends'>;
|
||||
type TopDependencies = APIReturnType<'GET /internal/apm/dependencies/top_dependencies'>;
|
||||
|
||||
export default function ApiTest({ getService }: FtrProviderContext) {
|
||||
const registry = getService('registry');
|
||||
|
@ -23,7 +23,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
async function callApi() {
|
||||
return await apmApiClient.readUser({
|
||||
endpoint: 'GET /internal/apm/backends/top_backends',
|
||||
endpoint: 'GET /internal/apm/dependencies/top_dependencies',
|
||||
params: {
|
||||
query: {
|
||||
start: new Date(start).toISOString(),
|
||||
|
@ -44,7 +44,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('handles empty state', async () => {
|
||||
const { status, body } = await callApi();
|
||||
expect(status).to.be(200);
|
||||
expect(body.backends).to.empty();
|
||||
expect(body.dependencies).to.empty();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -65,40 +65,40 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
after(() => synthtraceEsClient.clean());
|
||||
|
||||
it('returns an array of dependencies', () => {
|
||||
expect(topDependencies).to.have.property('backends');
|
||||
expect(topDependencies.backends).to.have.length(1);
|
||||
expect(topDependencies).to.have.property('dependencies');
|
||||
expect(topDependencies.dependencies).to.have.length(1);
|
||||
});
|
||||
|
||||
it('returns correct dependency information', () => {
|
||||
const location = topDependencies.backends[0].location as BackendNode;
|
||||
const location = topDependencies.dependencies[0].location as DependencyNode;
|
||||
const { span } = dataConfig;
|
||||
|
||||
expect(location.type).to.be(NodeType.backend);
|
||||
expect(location.backendName).to.be(span.destination);
|
||||
expect(location.type).to.be(NodeType.dependency);
|
||||
expect(location.dependencyName).to.be(span.destination);
|
||||
expect(location.spanType).to.be(span.type);
|
||||
expect(location.spanSubtype).to.be(span.subType);
|
||||
expect(location).to.have.property('id');
|
||||
});
|
||||
|
||||
describe('returns the correct stats', () => {
|
||||
let backends: TopDependencies['backends'][number];
|
||||
let dependencies: TopDependencies['dependencies'][number];
|
||||
|
||||
before(() => {
|
||||
backends = topDependencies.backends[0];
|
||||
dependencies = topDependencies.dependencies[0];
|
||||
});
|
||||
|
||||
it("doesn't have previous stats", () => {
|
||||
expect(backends.previousStats).to.be(null);
|
||||
expect(dependencies.previousStats).to.be(null);
|
||||
});
|
||||
|
||||
it('has an "impact" property', () => {
|
||||
expect(backends.currentStats).to.have.property('impact');
|
||||
expect(dependencies.currentStats).to.have.property('impact');
|
||||
});
|
||||
|
||||
it('returns the correct latency', () => {
|
||||
const {
|
||||
currentStats: { latency },
|
||||
} = backends;
|
||||
} = dependencies;
|
||||
|
||||
const { transaction } = dataConfig;
|
||||
|
||||
|
@ -111,7 +111,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('returns the correct throughput', () => {
|
||||
const {
|
||||
currentStats: { throughput },
|
||||
} = backends;
|
||||
} = dependencies;
|
||||
const { rate } = dataConfig;
|
||||
|
||||
expect(roundNumber(throughput.value)).to.be(roundNumber(rate));
|
||||
|
@ -120,7 +120,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('returns the correct total time', () => {
|
||||
const {
|
||||
currentStats: { totalTime },
|
||||
} = backends;
|
||||
} = dependencies;
|
||||
const { rate, transaction } = dataConfig;
|
||||
|
||||
expect(
|
||||
|
@ -131,7 +131,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
it('returns the correct error rate', () => {
|
||||
const {
|
||||
currentStats: { errorRate },
|
||||
} = backends;
|
||||
} = dependencies;
|
||||
expect(errorRate.value).to.be(0);
|
||||
expect(errorRate.timeseries.every(({ y }) => y === 0)).to.be(true);
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../common/ftr_provider_context';
|
|||
import { roundNumber } from '../../utils';
|
||||
import { generateOperationData, generateOperationDataConfig } from './generate_operation_data';
|
||||
|
||||
type TopOperations = APIReturnType<'GET /internal/apm/backends/operations'>['operations'];
|
||||
type TopOperations = APIReturnType<'GET /internal/apm/dependencies/operations'>['operations'];
|
||||
|
||||
const {
|
||||
ES_BULK_DURATION,
|
||||
|
@ -34,24 +34,24 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
|
||||
async function callApi({
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment = ENVIRONMENT_ALL.value,
|
||||
kuery = '',
|
||||
}: {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
environment?: string;
|
||||
kuery?: string;
|
||||
}) {
|
||||
return await apmApiClient
|
||||
.readUser({
|
||||
endpoint: 'GET /internal/apm/backends/operations',
|
||||
endpoint: 'GET /internal/apm/dependencies/operations',
|
||||
params: {
|
||||
query: {
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
environment,
|
||||
kuery,
|
||||
backendName,
|
||||
dependencyName,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -60,7 +60,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
registry.when('Top operations when data is not loaded', { config: 'basic', archives: [] }, () => {
|
||||
it('handles empty state', async () => {
|
||||
const operations = await callApi({ backendName: 'elasticsearch' });
|
||||
const operations = await callApi({ dependencyName: 'elasticsearch' });
|
||||
expect(operations).to.empty();
|
||||
});
|
||||
});
|
||||
|
@ -85,7 +85,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
let bulkOperation: ValuesType<TopOperations>;
|
||||
|
||||
before(async () => {
|
||||
response = await callApi({ backendName: 'elasticsearch' });
|
||||
response = await callApi({ dependencyName: 'elasticsearch' });
|
||||
searchOperation = response.find((op) => op.spanName === '/_search')!;
|
||||
bulkOperation = response.find((op) => op.spanName === '/_bulk')!;
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
let setOperation: ValuesType<TopOperations>;
|
||||
|
||||
before(async () => {
|
||||
response = await callApi({ backendName: 'redis' });
|
||||
response = await callApi({ dependencyName: 'redis' });
|
||||
setOperation = response.find((op) => op.spanName === 'SET')!;
|
||||
});
|
||||
|
||||
|
@ -177,7 +177,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
before(async () => {
|
||||
response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
kuery: `service.name:"synth-go"`,
|
||||
});
|
||||
searchOperation = response.find((op) => op.spanName === '/_search')!;
|
||||
|
@ -199,7 +199,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
before(async () => {
|
||||
response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
environment: 'development',
|
||||
});
|
||||
searchOperation = response.find((op) => op.spanName === '/_search');
|
||||
|
|
|
@ -19,14 +19,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
|
||||
async function callApi({
|
||||
backendName,
|
||||
dependencyName,
|
||||
spanName,
|
||||
kuery = '',
|
||||
environment = ENVIRONMENT_ALL.value,
|
||||
sampleRangeFrom,
|
||||
sampleRangeTo,
|
||||
}: {
|
||||
backendName: string;
|
||||
dependencyName: string;
|
||||
spanName: string;
|
||||
kuery?: string;
|
||||
environment?: string;
|
||||
|
@ -34,10 +34,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
sampleRangeTo?: number;
|
||||
}) {
|
||||
return await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/operations/spans`,
|
||||
endpoint: `GET /internal/apm/dependencies/operations/spans`,
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
environment,
|
||||
|
@ -51,12 +51,12 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
}
|
||||
|
||||
registry.when(
|
||||
'Top backend spans when data is not loaded',
|
||||
'Top dependency spans when data is not loaded',
|
||||
{ config: 'basic', archives: [] },
|
||||
() => {
|
||||
it('handles empty state', async () => {
|
||||
const { body, status } = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: '/_search',
|
||||
});
|
||||
|
||||
|
@ -67,7 +67,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
registry.when(
|
||||
'Top backend spans when data is loaded',
|
||||
'Top dependency spans when data is loaded',
|
||||
{ config: 'basic', archives: ['apm_mappings_only_8.0.0'] },
|
||||
() => {
|
||||
const javaInstance = apm.service('java', 'production', 'java').instance('instance-a');
|
||||
|
@ -126,7 +126,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('without a kuery or environment', () => {
|
||||
it('returns the correct spans for the requested spanName', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: '/_search',
|
||||
});
|
||||
|
||||
|
@ -170,7 +170,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('with a kuery', () => {
|
||||
it('returns the correct spans for the requested spanName', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: '/_search',
|
||||
kuery: 'service.name:go',
|
||||
});
|
||||
|
@ -192,7 +192,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('with an environment', () => {
|
||||
it('returns the correct spans for the requested spanName', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: '/_search',
|
||||
environment: 'development',
|
||||
});
|
||||
|
@ -214,7 +214,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('when requesting spans without a transaction', () => {
|
||||
it('should return the spans without transaction metadata', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: 'without transaction',
|
||||
});
|
||||
|
||||
|
@ -242,7 +242,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
describe('when requesting spans within a specific sample range', () => {
|
||||
it('returns only spans whose duration falls into the requested range', async () => {
|
||||
const response = await callApi({
|
||||
backendName: 'elasticsearch',
|
||||
dependencyName: 'elasticsearch',
|
||||
spanName: '/_search',
|
||||
sampleRangeFrom: 50000,
|
||||
sampleRangeTo: 99999,
|
||||
|
|
|
@ -15,14 +15,14 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const registry = getService('registry');
|
||||
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
|
||||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
const backendName = 'elasticsearch';
|
||||
const dependencyName = 'elasticsearch';
|
||||
|
||||
async function callApi() {
|
||||
return await apmApiClient.readUser({
|
||||
endpoint: 'GET /internal/apm/backends/upstream_services',
|
||||
endpoint: 'GET /internal/apm/dependencies/upstream_services',
|
||||
params: {
|
||||
query: {
|
||||
backendName,
|
||||
dependencyName,
|
||||
environment: 'production',
|
||||
kuery: '',
|
||||
numBuckets: 20,
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ApmApiError, SupertestReturnType } from '../../common/apm_api_supertest
|
|||
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
|
||||
type BackendResponse = SupertestReturnType<'GET /internal/apm/service-map/backend'>;
|
||||
type DependencyResponse = SupertestReturnType<'GET /internal/apm/service-map/dependency'>;
|
||||
type ServiceNodeResponse =
|
||||
SupertestReturnType<'GET /internal/apm/service-map/service/{serviceName}'>;
|
||||
type ServiceMapResponse = SupertestReturnType<'GET /internal/apm/service-map'>;
|
||||
|
@ -101,14 +101,14 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
|
|||
});
|
||||
});
|
||||
|
||||
describe('/internal/apm/service-map/backend', () => {
|
||||
let response: BackendResponse;
|
||||
describe('/internal/apm/service-map/dependency', () => {
|
||||
let response: DependencyResponse;
|
||||
before(async () => {
|
||||
response = await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/service-map/backend`,
|
||||
endpoint: `GET /internal/apm/service-map/dependency`,
|
||||
params: {
|
||||
query: {
|
||||
backendName: 'postgres',
|
||||
dependencyName: 'postgres',
|
||||
start: metadata.start,
|
||||
end: metadata.end,
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
|
@ -371,14 +371,14 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
|
|||
});
|
||||
});
|
||||
|
||||
describe('/internal/apm/service-map/backend', () => {
|
||||
let response: BackendResponse;
|
||||
describe('/internal/apm/service-map/dependency', () => {
|
||||
let response: DependencyResponse;
|
||||
before(async () => {
|
||||
response = await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/service-map/backend`,
|
||||
endpoint: `GET /internal/apm/service-map/dependency`,
|
||||
params: {
|
||||
query: {
|
||||
backendName: 'postgresql',
|
||||
dependencyName: 'postgresql',
|
||||
start: metadata.start,
|
||||
end: metadata.end,
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
|
@ -416,14 +416,14 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
|
|||
});
|
||||
|
||||
describe('With comparison', () => {
|
||||
describe('/internal/apm/service-map/backend', () => {
|
||||
let response: BackendResponse;
|
||||
describe('/internal/apm/service-map/dependency', () => {
|
||||
let response: DependencyResponse;
|
||||
before(async () => {
|
||||
response = await apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/service-map/backend`,
|
||||
endpoint: `GET /internal/apm/service-map/dependency`,
|
||||
params: {
|
||||
query: {
|
||||
backendName: 'postgresql',
|
||||
dependencyName: 'postgresql',
|
||||
start: metadata.start,
|
||||
end: metadata.end,
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
|
|
|
@ -28,7 +28,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const { start, end } = archives[archiveName];
|
||||
|
||||
function getName(node: Node) {
|
||||
return node.type === NodeType.service ? node.serviceName : node.backendName;
|
||||
return node.type === NodeType.service ? node.serviceName : node.dependencyName;
|
||||
}
|
||||
|
||||
registry.when(
|
||||
|
@ -282,7 +282,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
throughput: roundNumber(postgres?.currentStats.throughput.value),
|
||||
errorRate: roundNumber(postgres?.currentStats.errorRate.value),
|
||||
impact: postgres?.currentStats.impact,
|
||||
...pick(postgres?.location, 'spanType', 'spanSubtype', 'backendName', 'type'),
|
||||
...pick(postgres?.location, 'spanType', 'spanSubtype', 'dependencyName', 'type'),
|
||||
};
|
||||
|
||||
const count = 1;
|
||||
|
@ -292,8 +292,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
expect(values).to.eql({
|
||||
spanType: 'external',
|
||||
spanSubtype: 'http',
|
||||
backendName: 'postgres',
|
||||
type: 'backend',
|
||||
dependencyName: 'postgres',
|
||||
type: 'dependency',
|
||||
errorRate: roundNumber(errors / count),
|
||||
latency: roundNumber(sum / count),
|
||||
throughput: roundNumber(count / ((endTime - startTime) / 1000 / 60)),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { apm, timerange } from '@elastic/apm-synthtrace';
|
||||
import expect from '@kbn/expect';
|
||||
import { meanBy, sumBy } from 'lodash';
|
||||
import { BackendNode, ServiceNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { DependencyNode, ServiceNode } from '@kbn/apm-plugin/common/connections';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { roundNumber } from '../../utils';
|
||||
|
||||
|
@ -19,51 +19,57 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
|
||||
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
|
||||
|
||||
async function getThroughputValues(overrides?: { serviceName?: string; backendName?: string }) {
|
||||
async function getThroughputValues(overrides?: {
|
||||
serviceName?: string;
|
||||
dependencyName?: string;
|
||||
}) {
|
||||
const commonQuery = {
|
||||
start: new Date(start).toISOString(),
|
||||
end: new Date(end).toISOString(),
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
};
|
||||
const [topBackendsAPIResponse, backendThroughputChartAPIResponse, upstreamServicesApiResponse] =
|
||||
await Promise.all([
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/top_backends`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
numBuckets: 20,
|
||||
kuery: '',
|
||||
},
|
||||
const [
|
||||
topDependenciesAPIResponse,
|
||||
dependencyThroughputChartAPIResponse,
|
||||
upstreamServicesApiResponse,
|
||||
] = await Promise.all([
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/dependencies/top_dependencies`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
numBuckets: 20,
|
||||
kuery: '',
|
||||
},
|
||||
}),
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/charts/throughput`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
backendName: overrides?.backendName || 'elasticsearch',
|
||||
spanName: '',
|
||||
searchServiceDestinationMetrics: false,
|
||||
kuery: '',
|
||||
},
|
||||
},
|
||||
}),
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/dependencies/charts/throughput`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
dependencyName: overrides?.dependencyName || 'elasticsearch',
|
||||
spanName: '',
|
||||
searchServiceDestinationMetrics: false,
|
||||
kuery: '',
|
||||
},
|
||||
}),
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/backends/upstream_services`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
backendName: overrides?.backendName || 'elasticsearch',
|
||||
numBuckets: 20,
|
||||
offset: '1d',
|
||||
kuery: '',
|
||||
},
|
||||
},
|
||||
}),
|
||||
apmApiClient.readUser({
|
||||
endpoint: `GET /internal/apm/dependencies/upstream_services`,
|
||||
params: {
|
||||
query: {
|
||||
...commonQuery,
|
||||
dependencyName: overrides?.dependencyName || 'elasticsearch',
|
||||
numBuckets: 20,
|
||||
offset: '1d',
|
||||
kuery: '',
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const backendThroughputChartMean = roundNumber(
|
||||
meanBy(backendThroughputChartAPIResponse.body.currentTimeseries, 'y')
|
||||
},
|
||||
}),
|
||||
]);
|
||||
const dependencyThroughputChartMean = roundNumber(
|
||||
meanBy(dependencyThroughputChartAPIResponse.body.currentTimeseries, 'y')
|
||||
);
|
||||
|
||||
const upstreamServicesThroughput = upstreamServicesApiResponse.body.services.map(
|
||||
|
@ -76,11 +82,11 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
return {
|
||||
topBackends: topBackendsAPIResponse.body.backends.map((item) => [
|
||||
(item.location as BackendNode).backendName,
|
||||
topDependencies: topDependenciesAPIResponse.body.dependencies.map((item) => [
|
||||
(item.location as DependencyNode).dependencyName,
|
||||
roundNumber(item.currentStats.throughput.value),
|
||||
]),
|
||||
backendThroughputChartMean,
|
||||
dependencyThroughputChartMean,
|
||||
upstreamServicesThroughput,
|
||||
};
|
||||
}
|
||||
|
@ -166,34 +172,34 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('returns elasticsearch and postgresql as dependencies', () => {
|
||||
const { topBackends } = throughputValues;
|
||||
const topBackendsAsObj = Object.fromEntries(topBackends);
|
||||
expect(topBackendsAsObj.elasticsearch).to.equal(
|
||||
const { topDependencies } = throughputValues;
|
||||
const topDependenciesAsObj = Object.fromEntries(topDependencies);
|
||||
expect(topDependenciesAsObj.elasticsearch).to.equal(
|
||||
roundNumber(JAVA_PROD_RATE + GO_PROD_RATE)
|
||||
);
|
||||
expect(topBackendsAsObj.postgresql).to.equal(roundNumber(GO_PROD_RATE));
|
||||
expect(topDependenciesAsObj.postgresql).to.equal(roundNumber(GO_PROD_RATE));
|
||||
});
|
||||
});
|
||||
|
||||
describe('compare throughput value between top backends, backend throughput chart and upstream services apis', () => {
|
||||
describe('elasticsearch dependency', () => {
|
||||
before(async () => {
|
||||
throughputValues = await getThroughputValues({ backendName: 'elasticsearch' });
|
||||
throughputValues = await getThroughputValues({ dependencyName: 'elasticsearch' });
|
||||
});
|
||||
|
||||
it('matches throughput values between throughput chart and top dependency', () => {
|
||||
const { topBackends, backendThroughputChartMean } = throughputValues;
|
||||
const topBackendsAsObj = Object.fromEntries(topBackends);
|
||||
const elasticsearchDependency = topBackendsAsObj.elasticsearch;
|
||||
[elasticsearchDependency, backendThroughputChartMean].forEach((value) =>
|
||||
const { topDependencies, dependencyThroughputChartMean } = throughputValues;
|
||||
const topDependenciesAsObj = Object.fromEntries(topDependencies);
|
||||
const elasticsearchDependency = topDependenciesAsObj.elasticsearch;
|
||||
[elasticsearchDependency, dependencyThroughputChartMean].forEach((value) =>
|
||||
expect(value).to.be.equal(roundNumber(JAVA_PROD_RATE + GO_PROD_RATE))
|
||||
);
|
||||
});
|
||||
|
||||
it('matches throughput values between upstream services and top dependency', () => {
|
||||
const { topBackends, upstreamServicesThroughput } = throughputValues;
|
||||
const topBackendsAsObj = Object.fromEntries(topBackends);
|
||||
const elasticsearchDependency = topBackendsAsObj.elasticsearch;
|
||||
const { topDependencies, upstreamServicesThroughput } = throughputValues;
|
||||
const topDependenciesAsObj = Object.fromEntries(topDependencies);
|
||||
const elasticsearchDependency = topDependenciesAsObj.elasticsearch;
|
||||
const upstreamServiceThroughputSum = roundNumber(
|
||||
sumBy(upstreamServicesThroughput, 'throughput')
|
||||
);
|
||||
|
@ -204,22 +210,22 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
describe('postgresql dependency', () => {
|
||||
before(async () => {
|
||||
throughputValues = await getThroughputValues({ backendName: 'postgresql' });
|
||||
throughputValues = await getThroughputValues({ dependencyName: 'postgresql' });
|
||||
});
|
||||
|
||||
it('matches throughput values between throughput chart and top dependency', () => {
|
||||
const { topBackends, backendThroughputChartMean } = throughputValues;
|
||||
const topBackendsAsObj = Object.fromEntries(topBackends);
|
||||
const postgresqlDependency = topBackendsAsObj.postgresql;
|
||||
[postgresqlDependency, backendThroughputChartMean].forEach((value) =>
|
||||
const { topDependencies, dependencyThroughputChartMean } = throughputValues;
|
||||
const topDependenciesAsObj = Object.fromEntries(topDependencies);
|
||||
const postgresqlDependency = topDependenciesAsObj.postgresql;
|
||||
[postgresqlDependency, dependencyThroughputChartMean].forEach((value) =>
|
||||
expect(value).to.be.equal(roundNumber(GO_PROD_RATE))
|
||||
);
|
||||
});
|
||||
|
||||
it('matches throughput values between upstream services and top dependency', () => {
|
||||
const { topBackends, upstreamServicesThroughput } = throughputValues;
|
||||
const topBackendsAsObj = Object.fromEntries(topBackends);
|
||||
const postgresqlDependency = topBackendsAsObj.postgresql;
|
||||
const { topDependencies, upstreamServicesThroughput } = throughputValues;
|
||||
const topDependenciesAsObj = Object.fromEntries(topDependencies);
|
||||
const postgresqlDependency = topDependenciesAsObj.postgresql;
|
||||
const upstreamServiceThroughputSum = roundNumber(
|
||||
sumBy(upstreamServicesThroughput, 'throughput')
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue