diff --git a/x-pack/plugins/observability_solution/inventory/common/utils/entity_type_guards.ts b/x-pack/plugins/observability_solution/inventory/common/utils/entity_type_guards.ts index dccc888abd8dc..f9ace49b20d3a 100644 --- a/x-pack/plugins/observability_solution/inventory/common/utils/entity_type_guards.ts +++ b/x-pack/plugins/observability_solution/inventory/common/utils/entity_type_guards.ts @@ -13,7 +13,7 @@ interface BuiltinEntityMap { container: InventoryEntity & { cloud?: { provider?: string[] } }; service: InventoryEntity & { agent?: { name: AgentName[] }; - service?: { environment?: string }; + service?: { environment?: string | string[] | null }; }; } diff --git a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/generate_data.ts b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/generate_data.ts index 3ddea0d925de2..a75165004a5a2 100644 --- a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/generate_data.ts +++ b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/generate_data.ts @@ -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); + }), + ...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(SERVICE_LOGS_ONLY) + .message(logMessage.message) + .logLevel(logMessage.level) + .setGeoLocation([1]) + .setHostIp('223.72.43.22') + .defaults({ + 'agent.name': 'nodejs', + }) + .timestamp(timestamp); + }), + ]; }); } diff --git a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts index c9d341c708965..ce7bdfd102a40 100644 --- a/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts +++ b/x-pack/plugins/observability_solution/inventory/e2e/cypress/e2e/home.cy.ts @@ -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', diff --git a/x-pack/plugins/observability_solution/inventory/public/hooks/use_detail_view_redirect.ts b/x-pack/plugins/observability_solution/inventory/public/hooks/use_detail_view_redirect.ts index 4df4fa4ca1f96..36fa622e74667 100644 --- a/x-pack/plugins/observability_solution/inventory/public/hooks/use_detail_view_redirect.ts +++ b/x-pack/plugins/observability_solution/inventory/public/hooks/use_detail_view_redirect.ts @@ -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, }); }