[Inventory][ECO] APM url generated with invalid environment (#200987)

closes https://github.com/elastic/kibana/issues/200913

The service environment can be `null`, when that's the case we should
not pass it to the service locator, we must instead pass `undefined`.

<img width="1238" alt="Screenshot 2024-11-20 at 16 26 18"
src="https://github.com/user-attachments/assets/ced1f3c2-b7e2-4acf-8d87-4e4caa01095c">
This commit is contained in:
Cauê Marcondes 2024-11-21 09:15:04 +00:00 committed by GitHub
parent 7f880cce09
commit dde84ef67c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 19 deletions

View file

@ -13,7 +13,7 @@ interface BuiltinEntityMap {
container: InventoryEntity & { cloud?: { provider?: string[] } };
service: InventoryEntity & {
agent?: { name: AgentName[] };
service?: { environment?: string };
service?: { environment?: string | string[] | null };
};
}

View file

@ -9,10 +9,12 @@ import { apm, entities, log, timerange } from '@kbn/apm-synthtrace-client';
import { generateLongIdWithSeed } from '@kbn/apm-synthtrace-client/src/lib/utils/generate_id';
const SYNTH_NODE_TRACES_LOGS_ENTITY_ID = generateLongIdWithSeed('service');
const SERVICE_LOGS_ONLY_ENTITY_ID = generateLongIdWithSeed('service-logs-only');
const HOST_SERVER_1_LOGS_ENTITY_ID = generateLongIdWithSeed('host');
const CONTAINER_ID_METRICS_ENTITY_ID = generateLongIdWithSeed('container');
const SYNTH_NODE_TRACE_LOGS = 'synth-node-trace-logs';
const SERVICE_LOGS_ONLY = 'service-logs-only';
const HOST_NAME = 'server1';
const CONTAINER_ID = 'foo';
@ -27,6 +29,13 @@ export function generateEntities({ from, to }: { from: number; to: number }) {
entityId: SYNTH_NODE_TRACES_LOGS_ENTITY_ID,
});
const serviceLogsOnly = entities.serviceEntity({
serviceName: SERVICE_LOGS_ONLY,
agentName: ['host'],
dataStreamType: ['logs'],
entityId: SERVICE_LOGS_ONLY_ENTITY_ID,
});
const hostServer1Logs = entities.hostEntity({
hostName: HOST_NAME,
agentName: ['nodejs'],
@ -49,6 +58,7 @@ export function generateEntities({ from, to }: { from: number; to: number }) {
.generator((timestamp) => {
return [
serviceSynthNodeTracesLogs.timestamp(timestamp),
serviceLogsOnly.timestamp(timestamp),
hostServer1Logs.timestamp(timestamp),
containerMetrics.timestamp(timestamp),
];
@ -90,23 +100,43 @@ export function generateLogs({ from, to }: { from: number; to: number }) {
.interval('1m')
.rate(1)
.generator((timestamp) => {
return Array(3)
.fill(0)
.map(() => {
const index = Math.floor(Math.random() * 3);
const logMessage = MESSAGE_LOG_LEVELS[index];
return [
...Array(3)
.fill(0)
.map(() => {
const index = Math.floor(Math.random() * 3);
const logMessage = MESSAGE_LOG_LEVELS[index];
return log
.create({ isLogsDb: false })
.service(SYNTH_NODE_TRACE_LOGS)
.message(logMessage.message)
.logLevel(logMessage.level)
.setGeoLocation([1])
.setHostIp('223.72.43.22')
.defaults({
'agent.name': 'nodejs',
})
.timestamp(timestamp);
});
return log
.create({ isLogsDb: false })
.service(SYNTH_NODE_TRACE_LOGS)
.message(logMessage.message)
.logLevel(logMessage.level)
.setGeoLocation([1])
.setHostIp('223.72.43.22')
.defaults({
'agent.name': 'nodejs',
})
.timestamp(timestamp);
}),
...Array(3)
.fill(0)
.map(() => {
const index = Math.floor(Math.random() * 3);
const logMessage = MESSAGE_LOG_LEVELS[index];
return log
.create({ isLogsDb: false })
.service(SERVICE_LOGS_ONLY)
.message(logMessage.message)
.logLevel(logMessage.level)
.setGeoLocation([1])
.setHostIp('223.72.43.22')
.defaults({
'agent.name': 'nodejs',
})
.timestamp(timestamp);
}),
];
});
}

View file

@ -110,6 +110,18 @@ describe('Home page', () => {
cy.url().should('include', '/app/apm/services/synth-node-trace-logs/overview');
});
it('Navigates to apm when clicking on a logs only service', () => {
cy.intercept('GET', '/internal/entities/managed/enablement', {
fixture: 'eem_enabled.json',
}).as('getEEMStatus');
cy.visitKibana('/app/inventory');
cy.wait('@getEEMStatus');
cy.contains('service').click();
cy.contains('service-logs-only').click();
cy.url().should('include', '/app/apm/services/service-logs-only/overview');
cy.contains('Detect and resolve issues faster with deep visibility into your application');
});
it('Navigates to hosts when clicking on a host type entity', () => {
cy.intercept('GET', '/internal/entities/managed/enablement', {
fixture: 'eem_enabled.json',

View file

@ -61,7 +61,9 @@ export const useDetailViewRedirect = () => {
if (isBuiltinEntityOfType('service', entity)) {
return serviceOverviewLocator?.getRedirectUrl({
serviceName: identityFieldsValue[identityFields[0]],
environment: entity.service?.environment,
environment: entity.service?.environment
? castArray(entity.service?.environment)[0]
: undefined,
});
}