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

[eem] _search endpoint / initial entity manager UI #199609

Merged
merged 47 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
cbc7c06
initial commit
klacabane Nov 11, 2024
6f10eb4
unneeded array.from
klacabane Nov 11, 2024
2092eda
should not be added
klacabane Nov 11, 2024
87a3c55
tweaks
klacabane Nov 12, 2024
63ce569
include es metadata
klacabane Nov 12, 2024
79338d8
slice result set
klacabane Nov 12, 2024
2df44ce
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 18, 2024
69b4900
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 18, 2024
4f9aca5
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Nov 18, 2024
31640ed
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 18, 2024
8926c24
fix imports and add @timestamp as required field
klacabane Nov 18, 2024
fcfc507
configurable timestamp
klacabane Nov 18, 2024
1678d83
mandatory timestamp field
klacabane Nov 18, 2024
6d80b81
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Nov 18, 2024
5449825
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 18, 2024
7451b89
fetch sources from kibana_entity_definitions
klacabane Nov 19, 2024
83db43a
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Nov 19, 2024
40b4dc7
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 19, 2024
6f07b1c
move ui to entity_manager_app
klacabane Nov 19, 2024
2872334
add start/end to _search
klacabane Nov 19, 2024
a64dccf
non optional start/end
klacabane Nov 19, 2024
00c0ec8
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 19, 2024
39f7758
[CI] Auto-commit changed files from 'node scripts/build_plugin_list_d…
kibanamachine Nov 19, 2024
535622e
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Nov 19, 2024
1a02de8
add timestamp_field to form
klacabane Nov 19, 2024
820f381
fix configs
klacabane Nov 19, 2024
19b6bb6
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 19, 2024
832297e
remove usagecollection
klacabane Nov 20, 2024
59ab759
register entity_manager in application_usage
klacabane Nov 20, 2024
6035b27
update oss_plugins
klacabane Nov 20, 2024
698debf
remove queryclient
klacabane Nov 20, 2024
7616c10
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 20, 2024
506ce78
fix merge and tests
klacabane Nov 20, 2024
ad1c530
query test
klacabane Nov 20, 2024
48add74
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 20, 2024
720d421
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 21, 2024
79a1c20
Update x-pack/plugins/entity_manager/server/lib/queries/index.test.ts
klacabane Nov 21, 2024
9a14b77
Update x-pack/plugins/entity_manager/server/lib/queries/utils.test.ts
klacabane Nov 21, 2024
26bf3d8
add type level metadata/filters
klacabane Nov 21, 2024
5898952
v2 routes
klacabane Nov 21, 2024
baab5b3
add searchEntitiesBySources
klacabane Nov 21, 2024
51af524
update search module path
klacabane Nov 21, 2024
a1ae809
types
klacabane Nov 21, 2024
67902d9
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 21, 2024
2606a06
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 21, 2024
f904abb
rename entityv2
klacabane Nov 22, 2024
a49c97e
Merge branch 'main' into 188-entity-definition-v2-type-source
klacabane Nov 22, 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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,7 @@ x-pack/plugins/observability_solution/apm_data_access @elastic/obs-knowledge-tea
x-pack/plugins/observability_solution/apm/ftr_e2e @elastic/obs-ux-infra_services-team
x-pack/plugins/observability_solution/dataset_quality @elastic/obs-ux-logs-team
x-pack/plugins/observability_solution/entities_data_access @elastic/obs-entities
x-pack/plugins/observability_solution/entity_manager_app @elastic/obs-entities
x-pack/plugins/observability_solution/exploratory_view @elastic/obs-ux-management-team
x-pack/plugins/observability_solution/infra @elastic/obs-ux-logs-team @elastic/obs-ux-infra_services-team
x-pack/plugins/observability_solution/inventory @elastic/obs-ux-infra_services-team
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,10 @@ security and spaces filtering.
|This plugin provides access to observed entity data, such as information about hosts, pods, containers, services, and more.


|{kib-repo}blob/{branch}/x-pack/plugins/observability_solution/entity_manager_app/README.md[entityManagerApp]
|This plugin provides a user interface to interact with the Entity Manager.


|{kib-repo}blob/{branch}/x-pack/plugins/event_log/README.md[eventLog]
|The event log plugin provides a persistent history of alerting and action
activities.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@
"@kbn/entities-data-access-plugin": "link:x-pack/plugins/observability_solution/entities_data_access",
"@kbn/entities-schema": "link:x-pack/packages/kbn-entities-schema",
"@kbn/entity-manager-fixture-plugin": "link:x-pack/test/api_integration/apis/entity_manager/fixture_plugin",
"@kbn/entityManager-app-plugin": "link:x-pack/plugins/observability_solution/entity_manager_app",
"@kbn/entityManager-plugin": "link:x-pack/plugins/entity_manager",
"@kbn/error-boundary-example-plugin": "link:examples/error_boundary",
"@kbn/es-errors": "link:packages/kbn-es-errors",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pageLoadAssetSize:
embeddableEnhanced: 22107
enterpriseSearch: 66810
entityManager: 17175
entityManagerApp: 20378
esql: 37000
esqlDataGrid: 24582
esUiShared: 326654
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export const applicationUsageSchema = {
enterpriseSearchSemanticSearch: commonSchema,
enterpriseSearchVectorSearch: commonSchema,
enterpriseSearchElasticsearch: commonSchema,
entity_manager: commonSchema,
appSearch: commonSchema,
workplaceSearch: commonSchema,
searchExperiences: commonSchema,
Expand Down
131 changes: 131 additions & 0 deletions src/plugins/telemetry/schema/oss_plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3015,6 +3015,137 @@
}
}
},
"entity_manager": {
"properties": {
"appId": {
"type": "keyword",
"_meta": {
"description": "The application being tracked"
}
},
"viewId": {
"type": "keyword",
"_meta": {
"description": "Always `main`"
}
},
"clicks_total": {
"type": "long",
"_meta": {
"description": "General number of clicks in the application since we started counting them"
}
},
"clicks_7_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the application over the last 7 days"
}
},
"clicks_30_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the application over the last 30 days"
}
},
"clicks_90_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the application over the last 90 days"
}
},
"minutes_on_screen_total": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen since we started counting them."
}
},
"minutes_on_screen_7_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen over the last 7 days"
}
},
"minutes_on_screen_30_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen over the last 30 days"
}
},
"minutes_on_screen_90_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen over the last 90 days"
}
},
"views": {
"type": "array",
"items": {
"properties": {
"appId": {
"type": "keyword",
"_meta": {
"description": "The application being tracked"
}
},
"viewId": {
"type": "keyword",
"_meta": {
"description": "The application view being tracked"
}
},
"clicks_total": {
"type": "long",
"_meta": {
"description": "General number of clicks in the application sub view since we started counting them"
}
},
"clicks_7_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the active application sub view over the last 7 days"
}
},
"clicks_30_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the active application sub view over the last 30 days"
}
},
"clicks_90_days": {
"type": "long",
"_meta": {
"description": "General number of clicks in the active application sub view over the last 90 days"
}
},
"minutes_on_screen_total": {
"type": "float",
"_meta": {
"description": "Minutes the application sub view is active and on-screen since we started counting them."
}
},
"minutes_on_screen_7_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen active application sub view over the last 7 days"
}
},
"minutes_on_screen_30_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen active application sub view over the last 30 days"
}
},
"minutes_on_screen_90_days": {
"type": "float",
"_meta": {
"description": "Minutes the application is active and on-screen active application sub view over the last 90 days"
}
}
}
}
}
}
},
"appSearch": {
"properties": {
"appId": {
Expand Down
2 changes: 2 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,8 @@
"@kbn/entities-schema/*": ["x-pack/packages/kbn-entities-schema/*"],
"@kbn/entity-manager-fixture-plugin": ["x-pack/test/api_integration/apis/entity_manager/fixture_plugin"],
"@kbn/entity-manager-fixture-plugin/*": ["x-pack/test/api_integration/apis/entity_manager/fixture_plugin/*"],
"@kbn/entityManager-app-plugin": ["x-pack/plugins/observability_solution/entity_manager_app"],
"@kbn/entityManager-app-plugin/*": ["x-pack/plugins/observability_solution/entity_manager_app/*"],
"@kbn/entityManager-plugin": ["x-pack/plugins/entity_manager"],
"@kbn/entityManager-plugin/*": ["x-pack/plugins/entity_manager/*"],
"@kbn/error-boundary-example-plugin": ["examples/error_boundary"],
Expand Down
7 changes: 7 additions & 0 deletions x-pack/packages/kbn-entities-schema/src/schema/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export interface MetadataRecord {
[key: string]: string[] | MetadataRecord | string;
}

export interface Entity {
klacabane marked this conversation as resolved.
Show resolved Hide resolved
'entity.id': string;
'entity.last_seen_timestamp': string;
'entity.type': string;
[metadata: string]: any;
}

const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);

type Literal = z.infer<typeof literalSchema>;
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/entity_manager/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
"plugin": {
"id": "entityManager",
"configPath": ["xpack", "entityManager"],
"requiredPlugins": ["security", "encryptedSavedObjects", "licensing"],
"browser": true,
"server": true,
"requiredPlugins": [
"security",
"encryptedSavedObjects",
"licensing"
],
"requiredBundles": []
}
}
2 changes: 2 additions & 0 deletions x-pack/plugins/entity_manager/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const plugin: PluginInitializer<
return new Plugin(context);
};

export { EntityClient } from './lib/entity_client';

export type { EntityManagerPublicPluginSetup, EntityManagerPublicPluginStart };
export type EntityManagerAppId = 'entityManager';

Expand Down
6 changes: 2 additions & 4 deletions x-pack/plugins/entity_manager/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ export class Plugin implements EntityManagerPluginClass {
}

setup(core: CoreSetup) {
const entityClient = new EntityClient(core);
return {
entityClient,
entityClient: new EntityClient(core),
};
}

start(core: CoreStart) {
const entityClient = new EntityClient(core);
return {
entityClient,
entityClient: new EntityClient(core),
};
}

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/entity_manager/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { EntityClient } from './lib/entity_client';
export interface EntityManagerPublicPluginSetup {
entityClient: EntityClient;
}

export interface EntityManagerPublicPluginStart {
entityClient: EntityClient;
}
Expand Down
74 changes: 71 additions & 3 deletions x-pack/plugins/entity_manager/server/lib/entity_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { EntityDefinition, EntityDefinitionUpdate } from '@kbn/entities-schema';
import { Entity, EntityDefinition, EntityDefinitionUpdate } from '@kbn/entities-schema';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { Logger } from '@kbn/logging';
Expand All @@ -23,6 +23,8 @@ import { stopTransforms } from './entities/stop_transforms';
import { deleteIndices } from './entities/delete_index';
import { EntityDefinitionWithState } from './entities/types';
import { EntityDefinitionUpdateConflict } from './entities/errors/entity_definition_update_conflict';
import { EntitySource, getEntityInstancesQuery } from './queries';
import { mergeEntitiesList, runESQLQuery } from './queries/utils';

export class EntityClient {
constructor(
Expand Down Expand Up @@ -126,8 +128,6 @@ export class EntityClient {
});

if (deleteData) {
// delete data with current user as system user does not have
// .entities privileges
await deleteIndices(this.options.esClient, definition, this.options.logger);
}
}
Expand Down Expand Up @@ -170,4 +170,72 @@ export class EntityClient {
this.options.logger.info(`Stopping transforms for definition [${definition.id}]`);
return stopTransforms(this.options.esClient, definition, this.options.logger);
}

async getEntitySources({ type }: { type: string }) {
klacabane marked this conversation as resolved.
Show resolved Hide resolved
const result = await this.options.esClient.search<EntitySource>({
index: 'kibana_entity_definitions',
query: {
bool: {
must: {
term: { entity_type: type },
},
},
},
});

return result.hits.hits.map((hit) => hit._source) as EntitySource[];
}

async searchEntities({
sources,
start,
end,
limit = 10,
}: {
sources: EntitySource[];
start: string;
end: string;
limit?: number;
}) {
const entities = await Promise.all(
sources.map(async (source) => {
const mandatoryFields = [source.timestamp_field, ...source.identity_fields];
const { fields } = await this.options.esClient.fieldCaps({
index: source.index_patterns,
fields: [...mandatoryFields, ...source.metadata_fields],
});

const sourceHasMandatoryFields = mandatoryFields.every((field) => !!fields[field]);
if (!sourceHasMandatoryFields) {
// we can't build entities without id fields so we ignore the source.
// filters should likely behave similarly.
this.options.logger.info(
`Ignoring source for type [${source.type}] with index_patterns [${source.index_patterns}] because some mandatory fields [${mandatoryFields}] are not mapped`
);
return [];
}

// but metadata field not being available is fine
const availableMetadataFields = source.metadata_fields.filter((field) => fields[field]);
miltonhultgren marked this conversation as resolved.
Show resolved Hide resolved

const query = getEntityInstancesQuery({
source: { ...source, metadata_fields: availableMetadataFields },
start,
end,
limit,
});
this.options.logger.debug(`Entity query: ${query}`);

const rawEntities = await runESQLQuery<Entity>({ query, esClient: this.options.esClient });

return rawEntities.map((entity) => {
entity['entity.id'] = source.identity_fields.map((field) => entity[field]).join(':');
entity['entity.type'] = source.type;
return entity;
});
})
).then((results) => results.flat());

return mergeEntitiesList(entities).slice(0, limit);
}
}
38 changes: 38 additions & 0 deletions x-pack/plugins/entity_manager/server/lib/queries/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 { getEntityInstancesQuery } from '.';

describe(__filename, () => {
klacabane marked this conversation as resolved.
Show resolved Hide resolved
describe('getEntityInstancesQuery', () => {
it('generates a valid esql query', () => {
const query = getEntityInstancesQuery({
source: {
type: 'service',
index_patterns: ['logs-*', 'metrics-*'],
identity_fields: ['service.name'],
metadata_fields: ['host.name'],
filters: [],
timestamp_field: 'custom_timestamp_field',
},
limit: 5,
start: '2024-11-20T19:00:00.000Z',
end: '2024-11-20T20:00:00.000Z',
});

expect(query).toEqual(
klacabane marked this conversation as resolved.
Show resolved Hide resolved
'FROM logs-*,metrics-*|' +
'WHERE custom_timestamp_field >= "2024-11-20T19:00:00.000Z"|' +
'WHERE custom_timestamp_field <= "2024-11-20T20:00:00.000Z"|' +
'WHERE service.name IS NOT NULL|' +
'STATS entity.last_seen_timestamp=MAX(custom_timestamp_field),metadata.host.name=VALUES(host.name) BY service.name|' +
'SORT entity.last_seen_timestamp DESC|' +
'LIMIT 5'
);
});
});
});
Loading