From 0559de6678b233da08ea2f532912ee9c61dff212 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cau=C3=AA=20Marcondes?=
<55978943+cauemarcondes@users.noreply.github.com>
Date: Wed, 7 Aug 2024 09:11:49 +0100
Subject: [PATCH] [APM][ECO] Logs callout when logs.level is not available
(#189644)
closes https://github.com/elastic/kibana/issues/189731
- Adding dismiss button to APM section
- Adding logs callout
https://github.com/user-attachments/assets/902409de-7d9b-47bf-b57d-3cdb199301f0
- N/A popover
---
.../apm/common/entities/types.ts | 1 +
.../app/entities/logs/add_apm_callout.tsx | 84 ++++++++++------
.../entities/logs/logs_service_overview.tsx | 97 +++++++++++++++++--
.../table/get_service_columns.tsx | 18 +++-
.../shared/environment_badge/index.tsx | 2 +-
.../not_available_apm_metrics.tsx | 8 +-
.../not_available_environment.tsx | 6 +-
.../not_available_log_metrics.tsx | 53 ++++++++++
.../apm/public/utils/get_signal_type.ts | 2 +-
.../server/routes/entities/get_entities.ts | 12 ++-
.../entities/get_service_entity_summary.ts | 40 ++++++++
.../server/routes/entities/services/routes.ts | 32 ++++++
.../apm/server/routes/entities/types.ts | 2 +
.../utils/calculate_avg_metrics.test.ts | 6 ++
.../entities/utils/merge_entities.test.ts | 22 +++++
.../routes/entities/utils/merge_entities.ts | 2 +
16 files changed, 332 insertions(+), 55 deletions(-)
rename x-pack/plugins/observability_solution/apm/public/components/shared/{ => not_available_popover}/not_available_apm_metrics.tsx (81%)
rename x-pack/plugins/observability_solution/apm/public/components/shared/{ => not_available_popover}/not_available_environment.tsx (92%)
create mode 100644 x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_log_metrics.tsx
create mode 100644 x-pack/plugins/observability_solution/apm/server/routes/entities/get_service_entity_summary.ts
diff --git a/x-pack/plugins/observability_solution/apm/common/entities/types.ts b/x-pack/plugins/observability_solution/apm/common/entities/types.ts
index f953fb5c593ed4..bdca62bc66824f 100644
--- a/x-pack/plugins/observability_solution/apm/common/entities/types.ts
+++ b/x-pack/plugins/observability_solution/apm/common/entities/types.ts
@@ -27,4 +27,5 @@ export interface EntityServiceListItem {
environments: string[];
serviceName: string;
agentName: AgentName;
+ hasLogMetrics: boolean;
}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/add_apm_callout.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/add_apm_callout.tsx
index c73526a5350c5a..49856327dd7034 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/add_apm_callout.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/add_apm_callout.tsx
@@ -16,6 +16,7 @@ import {
EuiTitle,
EuiButtonEmpty,
useEuiTheme,
+ EuiButtonIcon,
} from '@elastic/eui';
import { apmLight } from '@kbn/shared-svg';
import { FormattedMessage } from '@kbn/i18n-react';
@@ -23,7 +24,11 @@ import { useKibana } from '../../../../context/kibana_context/use_kibana';
import { ApmPluginStartDeps, ApmServices } from '../../../../plugin';
import { AddApmData } from '../../../shared/add_data_buttons/buttons';
-export function AddAPMCallOut() {
+interface Props {
+ onClose: () => void;
+}
+
+export function AddAPMCallOut({ onClose }: Props) {
const { euiTheme } = useEuiTheme();
const { services } = useKibana();
@@ -35,41 +40,56 @@ export function AddAPMCallOut() {
return (
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx
index d1f08b16eaf15b..c89487b527fbe3 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/entities/logs/logs_service_overview.tsx
@@ -12,17 +12,29 @@
* 2.0.
*/
+import {
+ EuiCallOut,
+ EuiFlexGroup,
+ EuiFlexGroupProps,
+ EuiFlexItem,
+ EuiLink,
+ EuiLoadingSpinner,
+ EuiSpacer,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n-react';
import React from 'react';
-import { EuiFlexGroupProps, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { AnnotationsContextProvider } from '../../../../context/annotations/annotations_context';
import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context';
-import { useBreakpoints } from '../../../../hooks/use_breakpoints';
import { useApmParams } from '../../../../hooks/use_apm_params';
+import { useBreakpoints } from '../../../../hooks/use_breakpoints';
import { useTimeRange } from '../../../../hooks/use_time_range';
-import { AddAPMCallOut } from './add_apm_callout';
-import { LogRateChart } from '../charts/log_rate_chart';
import { LogErrorRateChart } from '../charts/log_error_rate_chart';
+import { LogRateChart } from '../charts/log_rate_chart';
+import { AddAPMCallOut } from './add_apm_callout';
+import { useLocalStorage } from '../../../../hooks/use_local_storage';
+import { isPending, useFetcher } from '../../../../hooks/use_fetcher';
/**
* The height a chart should be if it's next to a table with 5 rows and a title.
* Add the height of the pagination row.
@@ -32,6 +44,10 @@ const chartHeight = 400;
export function LogsServiceOverview() {
const { serviceName } = useApmServiceContext();
+ const [isLogsApmCalloutEnabled, setIsLogsApmCalloutEnabled] = useLocalStorage(
+ 'apm.isLogsApmCalloutEnabled',
+ true
+ );
const {
query: { environment, rangeFrom, rangeTo },
@@ -39,11 +55,28 @@ export function LogsServiceOverview() {
const { start, end } = useTimeRange({ rangeFrom, rangeTo });
+ const { data, status } = useFetcher(
+ (callAPI) => {
+ return callAPI('GET /internal/apm/entities/services/{serviceName}/summary', {
+ params: { path: { serviceName }, query: { end, environment, start } },
+ });
+ },
+ [end, environment, serviceName, start]
+ );
+
const { isLarge } = useBreakpoints();
const isSingleColumn = isLarge;
const rowDirection: EuiFlexGroupProps['direction'] = isSingleColumn ? 'column' : 'row';
+ if (isPending(status)) {
+ return (
+
+
+
+ );
+ }
+
return (
-
-
+ {isLogsApmCalloutEnabled ? (
+ <>
+ {
+ setIsLogsApmCalloutEnabled(false);
+ }}
+ />
+
+ >
+ ) : null}
+ {data?.entity?.hasLogMetrics === false ? (
+ <>
+
+
+ {i18n.translate('xpack.apm.logsServiceOverview.logLevelLink', {
+ defaultMessage: 'log.level',
+ })}
+
+ ),
+ learnMoreLink: (
+
+ {i18n.translate('xpack.apm.logsServiceOverview.learnMoreLink', {
+ defaultMessage: 'Learn more',
+ })}
+
+ ),
+ }}
+ />
+
+
+ >
+ ) : null}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/service_inventory/multi_signal_inventory/table/get_service_columns.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/service_inventory/multi_signal_inventory/table/get_service_columns.tsx
index d0a2cfa898b792..45e8a9ca859a09 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/app/service_inventory/multi_signal_inventory/table/get_service_columns.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/app/service_inventory/multi_signal_inventory/table/get_service_columns.tsx
@@ -32,13 +32,14 @@ import { EnvironmentBadge } from '../../../../shared/environment_badge';
import { ServiceLink } from '../../../../shared/links/apm/service_link';
import { ListMetric } from '../../../../shared/list_metric';
import { ITableColumn } from '../../../../shared/managed_table';
-import { NotAvailableApmMetrics } from '../../../../shared/not_available_apm_metrics';
+import { NotAvailableApmMetrics } from '../../../../shared/not_available_popover/not_available_apm_metrics';
import { TruncateWithTooltip } from '../../../../shared/truncate_with_tooltip';
import { ServiceInventoryFieldName } from './multi_signal_services_table';
import { EntityServiceListItem, SignalTypes } from '../../../../../../common/entities/types';
-import { isApmSignal } from '../../../../../utils/get_signal_type';
+import { isApmSignal, isLogsSignal } from '../../../../../utils/get_signal_type';
import { ColumnHeader } from './column_header';
import { APIReturnType } from '../../../../../services/rest/create_call_apm_api';
+import { NotAvailableLogsMetrics } from '../../../../shared/not_available_popover/not_available_log_metrics';
type ServicesDetailedStatisticsAPIResponse =
APIReturnType<'POST /internal/apm/entities/services/detailed_statistics'>;
@@ -205,9 +206,12 @@ export function getServiceColumns({
sortable: true,
dataType: 'number',
align: RIGHT_ALIGNMENT,
- render: (_, { metrics, serviceName }) => {
- const { currentPeriodColor } = getTimeSeriesColor(ChartType.LOG_RATE);
+ render: (_, { metrics, serviceName, signalTypes, hasLogMetrics }) => {
+ if (isLogsSignal(signalTypes) && !hasLogMetrics) {
+ return ;
+ }
+ const { currentPeriodColor } = getTimeSeriesColor(ChartType.LOG_RATE);
return (
{
+ render: (_, { metrics, serviceName, signalTypes, hasLogMetrics }) => {
+ if (isLogsSignal(signalTypes) && !hasLogMetrics) {
+ return ;
+ }
+
const { currentPeriodColor } = getTimeSeriesColor(ChartType.LOG_ERROR_RATE);
return (
diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/environment_badge/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/environment_badge/index.tsx
index 135848bae13d4f..8e3752e5ce0bf3 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/shared/environment_badge/index.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/shared/environment_badge/index.tsx
@@ -8,7 +8,7 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { ItemsBadge } from '../item_badge';
-import { NotAvailableEnvironment } from '../not_available_environment';
+import { NotAvailableEnvironment } from '../not_available_popover/not_available_environment';
interface Props {
environments: string[];
diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_apm_metrics.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_apm_metrics.tsx
similarity index 81%
rename from x-pack/plugins/observability_solution/apm/public/components/shared/not_available_apm_metrics.tsx
rename to x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_apm_metrics.tsx
index c4d2eb8563af6a..66c466502bdd1c 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_apm_metrics.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_apm_metrics.tsx
@@ -7,10 +7,10 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { PopoverBadge } from './popover_badge';
-import { useKibana } from '../../context/kibana_context/use_kibana';
-import { ApmPluginStartDeps, ApmServices } from '../../plugin';
-import { AddApmData } from './add_data_buttons/buttons';
+import { PopoverBadge } from '../popover_badge';
+import { useKibana } from '../../../context/kibana_context/use_kibana';
+import { ApmPluginStartDeps, ApmServices } from '../../../plugin';
+import { AddApmData } from '../add_data_buttons/buttons';
export function NotAvailableApmMetrics() {
const { services } = useKibana();
diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_environment.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_environment.tsx
similarity index 92%
rename from x-pack/plugins/observability_solution/apm/public/components/shared/not_available_environment.tsx
rename to x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_environment.tsx
index aecc9f2586e710..af4cdd58ec1f93 100644
--- a/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_environment.tsx
+++ b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_environment.tsx
@@ -9,9 +9,9 @@ import React from 'react';
import { EuiCode, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
-import { PopoverBadge } from './popover_badge';
+import { PopoverBadge } from '../popover_badge';
-export const NotAvailableEnvironment = () => {
+export function NotAvailableEnvironment() {
return (
{
}
/>
);
-};
+}
diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_log_metrics.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_log_metrics.tsx
new file mode 100644
index 00000000000000..480795c5339442
--- /dev/null
+++ b/x-pack/plugins/observability_solution/apm/public/components/shared/not_available_popover/not_available_log_metrics.tsx
@@ -0,0 +1,53 @@
+/*
+ * 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 { EuiLink } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n-react';
+import React from 'react';
+import { PopoverBadge } from '../popover_badge';
+
+export function NotAvailableLogsMetrics() {
+ return (
+
+ {i18n.translate(
+ 'xpack.apm.servicesTable.notAvailableLogsMetrics.content.logLevelLink',
+ { defaultMessage: 'log.level' }
+ )}
+
+ ),
+ }}
+ />
+ }
+ footer={
+
+ {i18n.translate('xpack.apm.servicesTable.notAvailableLogsMetrics.footer.learnMore', {
+ defaultMessage: 'Learn more',
+ })}
+
+ }
+ />
+ );
+}
diff --git a/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts b/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
index a72bb4d782e9c6..e8a3c4c4313dfe 100644
--- a/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
+++ b/x-pack/plugins/observability_solution/apm/public/utils/get_signal_type.ts
@@ -11,5 +11,5 @@ export function isApmSignal(signalTypes: SignalTypes[]) {
return signalTypes.includes(SignalTypes.METRICS) || signalTypes.includes(SignalTypes.TRACES);
}
export function isLogsSignal(signalTypes: SignalTypes[]) {
- return signalTypes.includes(SignalTypes.LOGS) && !isApmSignal(signalTypes);
+ return signalTypes.includes(SignalTypes.LOGS);
}
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/get_entities.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/get_entities.ts
index 40704fd3fed9fd..a69a906454ff74 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/get_entities.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/get_entities.ts
@@ -17,6 +17,7 @@ import { environmentQuery } from '../../../common/utils/environment_query';
import { EntitiesESClient } from '../../lib/helpers/create_es_client/create_assets_es_client/create_assets_es_clients';
import { getServiceEntitiesHistoryMetrics } from './get_service_entities_history_metrics';
import { EntitiesRaw, EntityType, ServiceEntities } from './types';
+import { isFiniteNumber } from '../../../common/utils/is_finite_number';
export function entitiesRangeQuery(start: number, end: number): QueryDslQueryContainer[] {
return [
@@ -44,14 +45,16 @@ export async function getEntities({
environment,
kuery,
size,
+ serviceName,
}: {
entitiesESClient: EntitiesESClient;
start: number;
end: number;
environment: string;
- kuery: string;
+ kuery?: string;
size: number;
-}) {
+ serviceName?: string;
+}): Promise {
const entities = (
await entitiesESClient.searchLatest(`get_entities`, {
body: {
@@ -65,6 +68,7 @@ export async function getEntities({
...environmentQuery(environment, SERVICE_ENVIRONMENT),
...entitiesRangeQuery(start, end),
...termQuery(ENTITY_TYPE, EntityType.SERVICE),
+ ...termQuery(SERVICE_NAME, serviceName),
],
},
},
@@ -82,7 +86,8 @@ export async function getEntities({
})
: undefined;
- return entities.map((entity): ServiceEntities => {
+ return entities.map((entity) => {
+ const historyLogRate = serviceEntitiesHistoryMetricsMap?.[entity.entity.id]?.logRate;
return {
serviceName: entity.service.name,
environment: Array.isArray(entity.service?.environment) // TODO fix this in the EEM
@@ -92,6 +97,7 @@ export async function getEntities({
signalTypes: entity.data_stream.type,
entity: {
...entity.entity,
+ hasLogMetrics: isFiniteNumber(historyLogRate) ? historyLogRate > 0 : false,
// History metrics undefined means that for the selected time range there was no ingestion happening.
metrics: serviceEntitiesHistoryMetricsMap?.[entity.entity.id] || {
latency: null,
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/get_service_entity_summary.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/get_service_entity_summary.ts
new file mode 100644
index 00000000000000..0ea5d27e689716
--- /dev/null
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/get_service_entity_summary.ts
@@ -0,0 +1,40 @@
+/*
+ * 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 { EntitiesESClient } from '../../lib/helpers/create_es_client/create_assets_es_client/create_assets_es_clients';
+import { withApmSpan } from '../../utils/with_apm_span';
+import { getEntities } from './get_entities';
+import { ServiceEntities } from './types';
+
+interface Params {
+ entitiesESClient: EntitiesESClient;
+ serviceName: string;
+ environment: string;
+ start: number;
+ end: number;
+}
+
+export async function getServiceEntitySummary({
+ end,
+ entitiesESClient,
+ environment,
+ serviceName,
+ start,
+}: Params): Promise {
+ return withApmSpan('get_service_entity_summary', async () => {
+ const entities = await getEntities({
+ end,
+ entitiesESClient,
+ environment,
+ size: 1,
+ start,
+ serviceName,
+ });
+
+ return entities[0];
+ });
+}
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/services/routes.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/services/routes.ts
index c3894a38da2c44..0f52a9956af5b4 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/services/routes.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/services/routes.ts
@@ -13,12 +13,43 @@ import { createEntitiesESClient } from '../../../lib/helpers/create_es_client/cr
import { createApmServerRoute } from '../../apm_routes/create_apm_server_route';
import { environmentRt, kueryRt, rangeRt } from '../../default_api_types';
import { getServiceEntities } from './get_service_entities';
+import { getServiceEntitySummary } from '../get_service_entity_summary';
+import { ServiceEntities } from '../types';
import { getServiceEntitiesHistoryTimeseries } from '../get_service_entities_history_timeseries';
export interface EntityServicesResponse {
services: EntityServiceListItem[];
}
+const serviceEntitiesSummaryRoute = createApmServerRoute({
+ endpoint: 'GET /internal/apm/entities/services/{serviceName}/summary',
+ params: t.type({
+ path: t.type({ serviceName: t.string }),
+ query: t.intersection([environmentRt, rangeRt]),
+ }),
+ options: { tags: ['access:apm'] },
+ async handler(resources): Promise {
+ const { context, params, request } = resources;
+ const coreContext = await context.core;
+
+ const entitiesESClient = await createEntitiesESClient({
+ request,
+ esClient: coreContext.elasticsearch.client.asCurrentUser,
+ });
+
+ const { serviceName } = params.path;
+ const { start, end, environment } = params.query;
+
+ return getServiceEntitySummary({
+ entitiesESClient,
+ start,
+ end,
+ serviceName,
+ environment,
+ });
+ },
+});
+
const servicesEntitiesRoute = createApmServerRoute({
endpoint: 'GET /internal/apm/entities/services',
params: t.type({
@@ -161,4 +192,5 @@ export const servicesEntitiesRoutesRepository = {
...serviceLogRateTimeseriesRoute,
...serviceLogErrorRateTimeseriesRoute,
...servicesEntitiesDetailedStatisticsRoute,
+ ...serviceEntitiesSummaryRoute,
};
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/types.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/types.ts
index 35a19a218eea06..f98cef107a3d16 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/types.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/types.ts
@@ -16,6 +16,7 @@ export interface Entity {
latestTimestamp: string;
identityFields: string[];
metrics: EntityMetrics;
+ hasLogMetrics: boolean;
}
export interface TraceMetrics {
@@ -52,4 +53,5 @@ export interface MergedServiceEntities {
signalTypes: SignalTypes[];
environments: string[];
metrics: EntityMetrics[];
+ hasLogMetrics: boolean;
}
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/calculate_avg_metrics.test.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/calculate_avg_metrics.test.ts
index a7d18a93bd854e..f73d8cd5f4f8de 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/calculate_avg_metrics.test.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/calculate_avg_metrics.test.ts
@@ -34,6 +34,7 @@ describe('calculateAverageMetrics', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
{
agentName: 'java' as AgentName,
@@ -57,6 +58,7 @@ describe('calculateAverageMetrics', () => {
},
],
serviceName: 'service-2',
+ hasLogMetrics: true,
},
];
@@ -76,6 +78,7 @@ describe('calculateAverageMetrics', () => {
throughput: 7.5,
},
serviceName: 'service-1',
+ hasLogMetrics: true,
},
{
agentName: 'java' as AgentName,
@@ -90,6 +93,7 @@ describe('calculateAverageMetrics', () => {
throughput: 10,
},
serviceName: 'service-2',
+ hasLogMetrics: true,
},
]);
});
@@ -117,6 +121,7 @@ describe('calculateAverageMetrics', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
];
@@ -135,6 +140,7 @@ describe('calculateAverageMetrics', () => {
throughput: 7.5,
},
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
});
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.test.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.test.ts
index 544513fd501d20..dc52a8369c1cc6 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.test.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.test.ts
@@ -27,6 +27,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
];
@@ -47,6 +48,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
});
@@ -69,6 +71,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-1:env-service-1',
+ hasLogMetrics: true,
},
},
{
@@ -87,6 +90,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'apm-only-1:synthtrace-env-2',
+ hasLogMetrics: true,
},
},
{
@@ -105,6 +109,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-2:env-service-3',
+ hasLogMetrics: true,
},
},
{
@@ -123,6 +128,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-2:env-service-3',
+ hasLogMetrics: true,
},
},
];
@@ -151,6 +157,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
{
agentName: 'java' as AgentName,
@@ -174,6 +181,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-2',
+ hasLogMetrics: true,
},
]);
});
@@ -195,6 +203,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
{
@@ -213,6 +222,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
{
@@ -231,6 +241,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name', 'service.environment'],
id: 'service-1:prod',
+ hasLogMetrics: true,
},
},
];
@@ -265,6 +276,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
});
@@ -286,6 +298,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
];
@@ -306,6 +319,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
@@ -325,6 +339,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
{
@@ -342,6 +357,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
];
@@ -369,6 +385,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
});
@@ -390,6 +407,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
];
@@ -410,6 +428,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
@@ -429,6 +448,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
{
@@ -446,6 +466,7 @@ describe('mergeEntities', () => {
},
identityFields: ['service.name'],
id: 'service-1:test',
+ hasLogMetrics: true,
},
},
];
@@ -473,6 +494,7 @@ describe('mergeEntities', () => {
},
],
serviceName: 'service-1',
+ hasLogMetrics: true,
},
]);
});
diff --git a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.ts b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.ts
index 7dd8bfdace7bfe..6f96a25c63a937 100644
--- a/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.ts
+++ b/x-pack/plugins/observability_solution/apm/server/routes/entities/utils/merge_entities.ts
@@ -36,6 +36,7 @@ function mergeFunc(entity: ServiceEntities, existingEntity?: MergedServiceEntiti
environments: compact([entity?.environment]),
latestTimestamp: entity.entity.latestTimestamp,
metrics: [entity.entity.metrics],
+ hasLogMetrics: entity.entity.hasLogMetrics,
};
}
return {
@@ -45,5 +46,6 @@ function mergeFunc(entity: ServiceEntities, existingEntity?: MergedServiceEntiti
environments: uniq(compact([...existingEntity?.environments, entity?.environment])),
latestTimestamp: entity.entity.latestTimestamp,
metrics: [...existingEntity?.metrics, entity.entity.metrics],
+ hasLogMetrics: entity.entity.hasLogMetrics || existingEntity.hasLogMetrics,
};
}