[Performance] Report scale dimensions for service-map and hosts (#205607)

closes https://github.com/elastic/observability-dev/issues/3777 

## Summary

This PR provides scale dimensions for the service map and infra host
pages without introducing any additional requests.

### Global Service Map and Per-service APM Service Map 


| Metric         | Description                        |
|----------------|------------------------------------|
| `num_of_nodes` | Total number of discovered nodes (services +
dependenies |
| `num_of_traces`   | Total number of traces             |

### Infra


| Metric        | Description                     | default
|---------------|---------------------------------| -----------------
| `num_of_hosts`  | Total number of hosts          |
| `max_hosts_per_page` | Maximum number of host returne `50/100/500` |
100


| Page | Screenshot |

|-------------------------------|-------------------------------------------------------------------------------------------|
| Global Service Map | ![Screenshot 2025-01-08 at 12 54
43](https://github.com/user-attachments/assets/478b1f7b-bbd7-4ed5-8a7f-b041e6dab3b5)
|
| Per-service APM Service Map | ![Screenshot 2025-01-08 at 12 53
07](https://github.com/user-attachments/assets/62ee7852-6410-4dfc-9da2-5fc849ec18bc)
|
| Infra | !![Screenshot 2025-01-08 at 12 56
00](https://github.com/user-attachments/assets/e8b28a9c-14f7-4296-83cb-ddc25047f508)
|

 





### How to test
- Open any of the above pages
- In the network tab, look for `kibana:plugin_render_time`
This commit is contained in:
Katerina 2025-01-08 16:16:24 +02:00 committed by GitHub
parent 20eb87d778
commit 24f8888aae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 44 additions and 11 deletions

View file

@ -110,7 +110,7 @@ export function ServiceMap({
const { onPageReady } = usePerformanceContext();
const {
data = { elements: [] },
data = { elements: [], nodesCount: 0, tracesCount: 0 },
status,
error,
} = useFetcher(
@ -187,6 +187,12 @@ export function ServiceMap({
if (status === FETCH_STATUS.SUCCESS) {
onPageReady({
customMetrics: {
key1: 'num_of_nodes',
value1: data.nodesCount,
key2: 'num_of_traces',
value2: data.tracesCount,
},
meta: { rangeFrom: start, rangeTo: end },
});
}

View file

@ -32,6 +32,11 @@ export interface IEnvOptions {
kuery?: string;
}
export interface ServiceMapTelemetry {
tracesCount: number;
nodesCount: number;
}
async function getConnectionData({
config,
apmEventClient,
@ -63,6 +68,8 @@ async function getConnectionData({
const init = {
connections: [],
discoveredServices: [],
tracesCount: 0,
servicesCount: 0,
};
if (!traceIds.length) {
@ -99,16 +106,17 @@ async function getConnectionData({
logger.debug('Merged responses');
return mergedResponses;
return { ...mergedResponses, tracesCount: traceIds.length };
});
}
export type ConnectionsResponse = Awaited<ReturnType<typeof getConnectionData>>;
export type ServicesResponse = Awaited<ReturnType<typeof getServiceStats>>;
export type ServiceMapResponse = TransformServiceMapResponse & ServiceMapTelemetry;
export function getServiceMap(
options: IEnvOptions & { maxNumberOfServices: number }
): Promise<TransformServiceMapResponse> {
): Promise<ServiceMapResponse> {
return withApmSpan('get_service_map', async () => {
const { logger } = options;
const anomaliesPromise = getServiceAnomalies(
@ -137,8 +145,10 @@ export function getServiceMap(
},
});
logger.debug('Transformed service map response');
return transformedResponse;
return {
...transformedResponse,
tracesCount: connectionData.tracesCount,
nodesCount: transformedResponse.nodesCount,
};
});
}

View file

@ -39,6 +39,7 @@ interface GroupedEdge {
export interface GroupResourceNodesResponse {
elements: Array<GroupedNode | GroupedEdge | ConnectionElement>;
nodesCount: number;
}
export function groupResourceNodes(responseData: {
@ -151,5 +152,6 @@ export function groupResourceNodes(responseData: {
return {
elements: [...ungroupedNodes, ...groupedNodes, ...ungroupedEdges, ...groupedEdges],
nodesCount: ungroupedNodes.length,
};
}

View file

@ -23,7 +23,7 @@ import { environmentRt, rangeRt, kueryRt } from '../default_api_types';
import { getServiceGroup } from '../service_groups/get_service_group';
import { offsetRt } from '../../../common/comparison_rt';
import { getApmEventClient } from '../../lib/helpers/get_apm_event_client';
import type { TransformServiceMapResponse } from './transform_service_map_responses';
import type { ServiceMapResponse } from './get_service_map';
const serviceMapRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/service-map',
@ -39,7 +39,7 @@ const serviceMapRoute = createApmServerRoute({
]),
}),
security: { authz: { requiredPrivileges: ['apm'] } },
handler: async (resources): Promise<TransformServiceMapResponse> => {
handler: async (resources): Promise<ServiceMapResponse> => {
const { config, context, params, logger } = resources;
if (!config.serviceMapEnabled) {
throw Boom.notFound();

View file

@ -73,6 +73,7 @@ describe('transformServiceMapResponses', () => {
},
],
anomalies,
tracesCount: 10,
};
const { elements } = transformServiceMapResponses({ response });
@ -106,6 +107,7 @@ describe('transformServiceMapResponses', () => {
},
],
anomalies,
tracesCount: 10,
};
const { elements } = transformServiceMapResponses({ response });
@ -165,6 +167,7 @@ describe('transformServiceMapResponses', () => {
},
],
anomalies,
tracesCount: 10,
};
const { elements } = transformServiceMapResponses({ response });
@ -203,6 +206,7 @@ describe('transformServiceMapResponses', () => {
},
],
anomalies,
tracesCount: 10,
};
const { elements } = transformServiceMapResponses({ response });
@ -228,6 +232,7 @@ describe('transformServiceMapResponses', () => {
},
],
anomalies,
tracesCount: 10,
};
const { elements } = transformServiceMapResponses({ response });

View file

@ -17,10 +17,13 @@ import { useHostCountContext } from '../hooks/use_host_count';
import { FlyoutWrapper } from './host_details_flyout/flyout_wrapper';
import { DEFAULT_PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../constants';
import { FilterAction } from './table/filter_action';
import { useUnifiedSearchContext } from '../hooks/use_unified_search';
export const HostsTable = () => {
const { loading } = useHostsViewContext();
const { loading: hostCountLoading } = useHostCountContext();
const { loading: hostCountLoading, count } = useHostCountContext();
const { searchCriteria } = useUnifiedSearchContext();
const { onPageReady } = usePerformanceContext();
const {
@ -40,9 +43,16 @@ export const HostsTable = () => {
useEffect(() => {
if (!loading && !hostCountLoading) {
onPageReady();
onPageReady({
customMetrics: {
key1: 'num_of_hosts',
value1: count,
key2: `max_hosts_per_page`,
value2: searchCriteria.limit,
},
});
}
}, [loading, hostCountLoading, onPageReady]);
}, [loading, hostCountLoading, onPageReady, count, searchCriteria]);
return (
<>