Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Inventory][ECO] Show alerts for entities #195250

Merged
merged 36 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3d0f6b9
Fetch alerts count for entities
kpatticha Oct 7, 2024
391eb20
Show alerts count
kpatticha Oct 7, 2024
6c45bda
Add some tests
kpatticha Oct 9, 2024
0f5e13d
Sort alertCount
kpatticha Oct 9, 2024
900133b
use locator
kpatticha Oct 10, 2024
4d83595
Merge branch 'main' of github.com:elastic/kibana into 194381-entities…
kpatticha Oct 10, 2024
c4550f9
fix broken path
kpatticha Oct 10, 2024
57598d0
Change app route from `/app/observability/inventory` to `/app/inventory`
kpatticha Oct 10, 2024
a2f4a72
Remove alerts locator and add test
kpatticha Oct 10, 2024
01831a9
Fix sorting with undefined aletsCount entities
kpatticha Oct 10, 2024
0e5b0b6
clean up
kpatticha Oct 10, 2024
72a02ce
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Oct 10, 2024
c284f66
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Oct 10, 2024
b9781e9
clean up
kpatticha Oct 11, 2024
5e16ca9
Merge branch '194381-entities-alerts' of github.com:kpatticha/kibana …
kpatticha Oct 11, 2024
6555f9e
Fix another broken path
kpatticha Oct 11, 2024
b396dae
Fix another broken path
kpatticha Oct 11, 2024
082682b
Fix types
kpatticha Oct 11, 2024
ba8f6eb
Merge branch '194381-entities-alerts' of github.com:kpatticha/kibana …
kpatticha Oct 11, 2024
83b4172
Merge branch 'main' of github.com:elastic/kibana into 194381-entities…
kpatticha Oct 11, 2024
6859e92
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 11, 2024
e51fc2a
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 11, 2024
42ba8a9
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 11, 2024
6800888
Move joinByKey to observability-utils
kpatticha Oct 11, 2024
9197530
Address PR comments
kpatticha Oct 11, 2024
4cc746d
Merge branch '194381-entities-alerts' of github.com:kpatticha/kibana …
kpatticha Oct 11, 2024
b594c5a
Use better function name
kpatticha Oct 11, 2024
00493ec
fix typo
kpatticha Oct 11, 2024
7a856fa
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 14, 2024
3eb46d4
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 14, 2024
702d615
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 14, 2024
638c851
Return kuery expression instead of an array
kpatticha Oct 14, 2024
ca6be0d
Address PR comments
kpatticha Oct 15, 2024
607e882
Merge branch '194381-entities-alerts' of github.com:kpatticha/kibana …
kpatticha Oct 15, 2024
af85ce0
Update x-pack/plugins/observability_solution/inventory/server/routes/…
kpatticha Oct 15, 2024
d152a6b
Merge branch 'main' into 194381-entities-alerts
kpatticha Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,53 @@ describe('joinByKey', () => {
]);
});

it('joins by multiple keys', () => {
const joined = joinByKey(
[
{
serviceName: 'opbeans-node',
environment: 'production',
alertCount: 10,
},
{
serviceName: 'opbeans-node',
environment: 'production',
},
{
serviceName: 'opbeans-node',
environment: 'staging',
},
{
hostName: 'my-host',
cloudProvider: 'aws',
},
{
hostName: 'my-host',
alertCount: 10,
serviceName: 'opbeans-node',
},
],
['serviceName', 'environment', 'hostName']
);

expect(joined).toEqual([
{
serviceName: 'opbeans-node',
environment: 'production',
alertCount: 10,
},
{
serviceName: 'opbeans-node',
environment: 'staging',
},
{
hostName: 'my-host',
cloudProvider: 'aws',
alertCount: 10,
},
]);
});

it('uses the custom merge fn to replace items', () => {
const joined = joinByKey(
[
Expand Down
20 changes: 17 additions & 3 deletions x-pack/plugins/observability_solution/inventory/common/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*/
import { ENTITY_LATEST, entitiesAliasPattern } from '@kbn/entities-schema';
import {
HOST_NAME,
SERVICE_ENVIRONMENT,
SERVICE_NAME,
AGENT_NAME,
CLOUD_PROVIDER,
CONTAINER_ID,
Expand All @@ -15,9 +18,6 @@ import {
ENTITY_IDENTITY_FIELDS,
ENTITY_LAST_SEEN,
ENTITY_TYPE,
HOST_NAME,
SERVICE_ENVIRONMENT,
SERVICE_NAME,
} from '@kbn/observability-shared-plugin/common';
import { isRight } from 'fp-ts/lib/Either';
import * as t from 'io-ts';
Expand All @@ -28,8 +28,19 @@ export const entityTypeRt = t.union([
t.literal('container'),
]);

export const entityColumnIdsRt = t.union([
t.literal(ENTITY_DISPLAY_NAME),
t.literal(ENTITY_LAST_SEEN),
t.literal(ENTITY_TYPE),
t.literal('alertsCount'),
]);

export type EntityColumnIds = t.TypeOf<typeof entityColumnIdsRt>;

export type EntityType = t.TypeOf<typeof entityTypeRt>;

export const DEFAULT_ENTITIES_SORT_FIELD: EntityColumnIds = 'alertsCount';

export const MAX_NUMBER_OF_ENTITIES = 500;

export const ENTITIES_LATEST_ALIAS = entitiesAliasPattern({
Expand All @@ -49,6 +60,8 @@ export const defaultEntityDefinitions = [

export const defaultEntityTypes: EntityType[] = ['service', 'host', 'container'];

export const defaultEntitySortField = ENTITY_LAST_SEEN;
kpatticha marked this conversation as resolved.
Show resolved Hide resolved

const entityArrayRt = t.array(entityTypeRt);
export const entityTypesRt = new t.Type<EntityType[], string, unknown>(
'entityTypesRt',
Expand Down Expand Up @@ -79,6 +92,7 @@ interface BaseEntity {
[ENTITY_DISPLAY_NAME]: string;
[ENTITY_DEFINITION_ID]: string;
[ENTITY_IDENTITY_FIELDS]: string | string[];
alertsCount?: number;
[key: string]: any;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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 {
ENTITY_DEFINITION_ID,
ENTITY_DISPLAY_NAME,
ENTITY_ID,
ENTITY_LAST_SEEN,
} from '@kbn/observability-shared-plugin/common';
import { Entity } from '../entities';
import { getIdentityFieldValues } from './get_identity_fields_values';

const commonEntityFields = {
[ENTITY_LAST_SEEN]: '2023-10-09T00:00:00Z',
[ENTITY_ID]: '1',
[ENTITY_DISPLAY_NAME]: 'entity_name',
[ENTITY_DEFINITION_ID]: 'entity_definition_id',
alertCount: 3,
};

describe('getIdentityFieldValues', () => {
it('should return the value when identityFields is a single string', () => {
const entity: Entity = {
'entity.identityFields': 'service.name',
'service.name': 'my-service',
'entity.type': 'service',
...commonEntityFields,
};

const result = getIdentityFieldValues({ entity });
expect(result).toEqual(['service.name: "my-service"']);
});

it('should return values when identityFields is an array of strings', () => {
const entity: Entity = {
'entity.identityFields': ['service.name', 'service.environment'],
'service.name': 'my-service',
'entity.type': 'service',
'service.environment': 'staging',
...commonEntityFields,
};

const result = getIdentityFieldValues({ entity });
expect(result).toEqual(['service.name: "my-service"', 'service.environment: "staging"']);
});

it('should return an empty array if identityFields is empty string', () => {
const entity: Entity = {
'entity.identityFields': '',
'service.name': 'my-service',
'entity.type': 'service',
...commonEntityFields,
};

const result = getIdentityFieldValues({ entity });
expect(result).toEqual([]);
});
it('should return an empty array if identityFields is empty array', () => {
const entity: Entity = {
'entity.identityFields': [],
'service.name': 'my-service',
'entity.type': 'service',
...commonEntityFields,
};

const result = getIdentityFieldValues({ entity });
expect(result).toEqual([]);
});

it('should ignore fields that are not present in the entity', () => {
const entity: Entity = {
'entity.identityFields': ['host.name', 'foo.bar'],
'host.name': 'my-host',
'entity.type': 'host',
...commonEntityFields,
};

const result = getIdentityFieldValues({ entity });
expect(result).toEqual(['host.name: "my-host"']);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { ENTITY_IDENTITY_FIELDS } from '@kbn/observability-shared-plugin/common';
import { Entity } from '../entities';

export function getIdentityFieldValues({ entity }: { entity: Entity }) {
kpatticha marked this conversation as resolved.
Show resolved Hide resolved
const mapping: string[] = [];

const identityFields = entity[ENTITY_IDENTITY_FIELDS];

if (identityFields) {
const fields = Array.isArray(identityFields) ? identityFields : [identityFields];
kpatticha marked this conversation as resolved.
Show resolved Hide resolved

fields.forEach((field) => {
if (field in entity) {
mapping.push(`${[field]}: "${entity[field as keyof Entity]}"`);
}
});
}

return mapping;
}
Loading