From bfc2d7523147941b7f667e44f800d56cb9cd45bb Mon Sep 17 00:00:00 2001 From: Marco Antonio Ghiani Date: Wed, 10 Apr 2024 11:51:20 +0200 Subject: [PATCH] feature(unified-doc-viewer): register and consume ai assistant --- package.json | 1 + .../features_registry/features_registry.ts | 2 +- src/plugins/discover_shared/README.md | 4 +-- src/plugins/discover_shared/public/index.ts | 2 +- src/plugins/discover_shared/public/mocks.ts | 33 +++++++++++++++++++ src/plugins/discover_shared/public/plugin.ts | 4 +-- .../discover_features_service.mock.ts | 8 +++-- .../services/discover_features/types.ts | 6 ++-- src/plugins/discover_shared/public/types.ts | 18 +++++----- src/plugins/unified_doc_viewer/kibana.jsonc | 2 +- .../public/__mocks__/services.ts | 2 ++ .../logs_overview.tsx | 2 ++ .../logs_overview_ai_assistant.tsx | 24 ++++++++++++++ .../unified_doc_viewer/public/plugin.tsx | 14 ++++++-- .../unified_doc_viewer/public/types.ts | 2 ++ tsconfig.base.json | 2 ++ .../logs_shared/kibana.jsonc | 1 + .../components/log_ai_assistant/index.tsx | 23 +++++++++++-- .../logs_shared/public/plugin.ts | 9 +++-- .../logs_shared/public/types.ts | 2 ++ yarn.lock | 4 +++ 21 files changed, 137 insertions(+), 28 deletions(-) create mode 100644 src/plugins/discover_shared/public/mocks.ts create mode 100644 src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_ai_assistant.tsx diff --git a/package.json b/package.json index 816332219392a..0494c47a79691 100644 --- a/package.json +++ b/package.json @@ -412,6 +412,7 @@ "@kbn/discover-customization-examples-plugin": "link:examples/discover_customization_examples", "@kbn/discover-enhanced-plugin": "link:x-pack/plugins/discover_enhanced", "@kbn/discover-plugin": "link:src/plugins/discover", + "@kbn/discover-shared-plugin": "link:src/plugins/discover_shared", "@kbn/discover-utils": "link:packages/kbn-discover-utils", "@kbn/doc-links": "link:packages/kbn-doc-links", "@kbn/dom-drag-drop": "link:packages/kbn-dom-drag-drop", diff --git a/packages/kbn-discover-utils/src/services/features_registry/features_registry.ts b/packages/kbn-discover-utils/src/services/features_registry/features_registry.ts index c54cf5b30dccc..ae2b5c75cfca6 100644 --- a/packages/kbn-discover-utils/src/services/features_registry/features_registry.ts +++ b/packages/kbn-discover-utils/src/services/features_registry/features_registry.ts @@ -8,7 +8,7 @@ import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { BaseFeature, FeaturesMap } from './types'; -export class FeaturesRegistry { +export class FeaturesRegistry { private readonly features = new BehaviorSubject>(new Map()); /** diff --git a/src/plugins/discover_shared/README.md b/src/plugins/discover_shared/README.md index e2bcff56511db..8a8867238d624 100755 --- a/src/plugins/discover_shared/README.md +++ b/src/plugins/discover_shared/README.md @@ -31,7 +31,7 @@ export interface SecurityAIAssistantFeature { export interface ObservabilityLogsAIAssistantFeature { id: 'observability-logs-ai-assistant'; - render: (deps: {doc: DocumentOverview}) => React.ReactNode; + render: (deps: {doc: DataTableRecord}) => React.ReactNode; // Add any prop required for the feature } @@ -49,7 +49,7 @@ Once we have an interface for the feature, Discover can now retrieve it and use function LogsOverviewAIAssistant ({ doc }) { const { discoverShared } = getUnifiedDocViewerServices(); - const discoverShared = discoverShared.features.registry.getById('observability-logs-ai-assistant') + const logsAIAssistantFeature = discoverShared.features.registry.getById('observability-logs-ai-assistant') if (logsAIAssistantFeature) { return logsAIAssistantFeature.render({ doc }) diff --git a/src/plugins/discover_shared/public/index.ts b/src/plugins/discover_shared/public/index.ts index c6b15310c50e7..43f26c645a92c 100644 --- a/src/plugins/discover_shared/public/index.ts +++ b/src/plugins/discover_shared/public/index.ts @@ -12,7 +12,7 @@ export function plugin() { return new DiscoverSharedPlugin(); } -export type { DiscoverSharedClientSetupExports, DiscoverSharedClientStartExports } from './types'; +export type { DiscoverSharedPublicSetup, DiscoverSharedPublicStart } from './types'; export type { ObservabilityLogsAIAssistantFeatureRenderDeps, ObservabilityLogsAIAssistantFeature, diff --git a/src/plugins/discover_shared/public/mocks.ts b/src/plugins/discover_shared/public/mocks.ts new file mode 100644 index 0000000000000..78eb8011384c9 --- /dev/null +++ b/src/plugins/discover_shared/public/mocks.ts @@ -0,0 +1,33 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + createDiscoverFeaturesServiceSetupMock, + createDiscoverFeaturesServiceStartMock, +} from './services/discover_features/discover_features_service.mock'; +import { DiscoverSharedPublicSetup, DiscoverSharedPublicStart } from './types'; + +export type Setup = jest.Mocked; +export type Start = jest.Mocked; + +const createSetupContract = (): Setup => { + return { + features: createDiscoverFeaturesServiceSetupMock(), + }; +}; + +const createStartContract = (): Start => { + return { + features: createDiscoverFeaturesServiceStartMock(), + }; +}; + +export const discoverSharedPluginMock = { + createSetupContract, + createStartContract, +}; diff --git a/src/plugins/discover_shared/public/plugin.ts b/src/plugins/discover_shared/public/plugin.ts index c2f65675569a4..2761149c4d0b5 100644 --- a/src/plugins/discover_shared/public/plugin.ts +++ b/src/plugins/discover_shared/public/plugin.ts @@ -7,9 +7,9 @@ */ import { DiscoverFeaturesService } from './services/discover_features'; -import { DiscoverSharedClientPlugin } from './types'; +import { DiscoverSharedPublicPlugin } from './types'; -export class DiscoverSharedPlugin implements DiscoverSharedClientPlugin { +export class DiscoverSharedPlugin implements DiscoverSharedPublicPlugin { private discoverFeaturesService: DiscoverFeaturesService = new DiscoverFeaturesService(); public setup() { diff --git a/src/plugins/discover_shared/public/services/discover_features/discover_features_service.mock.ts b/src/plugins/discover_shared/public/services/discover_features/discover_features_service.mock.ts index 9a8d64decfa76..62f556f0f34f1 100644 --- a/src/plugins/discover_shared/public/services/discover_features/discover_features_service.mock.ts +++ b/src/plugins/discover_shared/public/services/discover_features/discover_features_service.mock.ts @@ -7,7 +7,9 @@ */ import { FeaturesRegistry } from '@kbn/discover-utils'; +import { DiscoverFeature } from './types'; -export const createDiscoverFeaturesServiceStartMock = () => ({ - registry: new FeaturesRegistry(), -}); +const registry = new FeaturesRegistry(); + +export const createDiscoverFeaturesServiceSetupMock = () => ({ registry }); +export const createDiscoverFeaturesServiceStartMock = () => ({ registry }); diff --git a/src/plugins/discover_shared/public/services/discover_features/types.ts b/src/plugins/discover_shared/public/services/discover_features/types.ts index 07b61b114aaf7..17c9ef8229418 100644 --- a/src/plugins/discover_shared/public/services/discover_features/types.ts +++ b/src/plugins/discover_shared/public/services/discover_features/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { DocumentOverview, FeaturesRegistry } from '@kbn/discover-utils'; +import { DataTableRecord, FeaturesRegistry } from '@kbn/discover-utils'; /** * Features types @@ -21,11 +21,11 @@ import { DocumentOverview, FeaturesRegistry } from '@kbn/discover-utils'; */ export interface ObservabilityLogsAIAssistantFeatureRenderDeps { - doc: DocumentOverview; + doc: DataTableRecord; } export interface ObservabilityLogsAIAssistantFeature { id: 'observability-logs-ai-assistant'; - render: (deps: ObservabilityLogsAIAssistantFeatureRenderDeps) => React.ReactNode; + render: (deps: ObservabilityLogsAIAssistantFeatureRenderDeps) => JSX.Element; } // This should be a union of all the available client features. diff --git a/src/plugins/discover_shared/public/types.ts b/src/plugins/discover_shared/public/types.ts index 685ba25140976..bda1cc4683465 100644 --- a/src/plugins/discover_shared/public/types.ts +++ b/src/plugins/discover_shared/public/types.ts @@ -12,22 +12,22 @@ import { DiscoverFeaturesServiceStart, } from './services/discover_features'; -export interface DiscoverSharedClientSetupExports { +export interface DiscoverSharedPublicSetup { features: DiscoverFeaturesServiceSetup; } -export interface DiscoverSharedClientStartExports { +export interface DiscoverSharedPublicStart { features: DiscoverFeaturesServiceStart; } // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface DiscoverSharedClientPluginSetupDeps {} +export interface DiscoverSharedPublicSetupDeps {} // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface DiscoverSharedClientPluginStartDeps {} +export interface DiscoverSharedPublicStartDeps {} -export type DiscoverSharedClientPlugin = Plugin< - DiscoverSharedClientSetupExports, - DiscoverSharedClientStartExports, - DiscoverSharedClientPluginSetupDeps, - DiscoverSharedClientPluginStartDeps +export type DiscoverSharedPublicPlugin = Plugin< + DiscoverSharedPublicSetup, + DiscoverSharedPublicStart, + DiscoverSharedPublicSetupDeps, + DiscoverSharedPublicStartDeps >; diff --git a/src/plugins/unified_doc_viewer/kibana.jsonc b/src/plugins/unified_doc_viewer/kibana.jsonc index ddb12c887b63f..c5ab9f0c4e632 100644 --- a/src/plugins/unified_doc_viewer/kibana.jsonc +++ b/src/plugins/unified_doc_viewer/kibana.jsonc @@ -8,6 +8,6 @@ "server": false, "browser": true, "requiredBundles": ["kibanaUtils"], - "requiredPlugins": ["data", "fieldFormats"], + "requiredPlugins": ["data", "discoverShared", "fieldFormats"], } } diff --git a/src/plugins/unified_doc_viewer/public/__mocks__/services.ts b/src/plugins/unified_doc_viewer/public/__mocks__/services.ts index a101104e2283d..e9dc74697f358 100644 --- a/src/plugins/unified_doc_viewer/public/__mocks__/services.ts +++ b/src/plugins/unified_doc_viewer/public/__mocks__/services.ts @@ -8,6 +8,7 @@ import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { discoverSharedPluginMock } from '@kbn/discover-shared-plugin/public/mocks'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import type { UnifiedDocViewerServices, UnifiedDocViewerStart } from '../types'; @@ -21,6 +22,7 @@ export const mockUnifiedDocViewer: jest.Mocked = { export const mockUnifiedDocViewerServices: jest.Mocked = { analytics: analyticsServiceMock.createAnalyticsServiceStart(), data: dataPluginMock.createStartContract(), + discoverShared: discoverSharedPluginMock.createStartContract(), fieldFormats: fieldFormatsMock, storage: new Storage(localStorage), uiSettings: uiSettingsServiceMock.createStartContract(), diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview.tsx index 078cf2807a552..641f2fc9cbc94 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview.tsx @@ -14,6 +14,7 @@ import { LogsOverviewHeader } from './logs_overview_header'; import { LogsOverviewHighlights } from './logs_overview_highlights'; import { FieldActionsProvider } from '../../hooks/use_field_actions'; import { getUnifiedDocViewerServices } from '../../plugin'; +import { LogsOverviewAIAssistant } from './logs_overview_ai_assistant'; export function LogsOverview({ columns, @@ -36,6 +37,7 @@ export function LogsOverview({ + ); } diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_ai_assistant.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_ai_assistant.tsx new file mode 100644 index 0000000000000..0e2627a1054fd --- /dev/null +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview/logs_overview_ai_assistant.tsx @@ -0,0 +1,24 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataTableRecord } from '@kbn/discover-utils'; +import { getUnifiedDocViewerServices } from '../../plugin'; + +export function LogsOverviewAIAssistant({ doc }: { doc: DataTableRecord }) { + const { discoverShared } = getUnifiedDocViewerServices(); + + const logsAIAssistantFeature = discoverShared.features.registry.getById( + 'observability-logs-ai-assistant' + ); + + if (!logsAIAssistantFeature) { + return null; + } + + return logsAIAssistantFeature.render({ doc }); +} diff --git a/src/plugins/unified_doc_viewer/public/plugin.tsx b/src/plugins/unified_doc_viewer/public/plugin.tsx index 9e8570ba349ca..dd0743eacc2e2 100644 --- a/src/plugins/unified_doc_viewer/public/plugin.tsx +++ b/src/plugins/unified_doc_viewer/public/plugin.tsx @@ -17,6 +17,7 @@ import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { CoreStart } from '@kbn/core/public'; import { dynamic } from '@kbn/shared-ux-utility'; +import { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; import type { UnifiedDocViewerServices } from './types'; export const [getUnifiedDocViewerServices, setUnifiedDocViewerServices] = @@ -47,6 +48,7 @@ export interface UnifiedDocViewerStart { export interface UnifiedDocViewerStartDeps { data: DataPublicPluginStart; + discoverShared: DiscoverSharedPublicStart; fieldFormats: FieldFormatsStart; } @@ -111,12 +113,20 @@ export class UnifiedDocViewerPublicPlugin public start(core: CoreStart, deps: UnifiedDocViewerStartDeps) { const { analytics, uiSettings } = core; - const { data, fieldFormats } = deps; + const { data, discoverShared, fieldFormats } = deps; const storage = new Storage(localStorage); const unifiedDocViewer = { registry: this.docViewsRegistry, }; - const services = { analytics, data, fieldFormats, storage, uiSettings, unifiedDocViewer }; + const services = { + analytics, + data, + discoverShared, + fieldFormats, + storage, + uiSettings, + unifiedDocViewer, + }; setUnifiedDocViewerServices(services); return unifiedDocViewer; } diff --git a/src/plugins/unified_doc_viewer/public/types.ts b/src/plugins/unified_doc_viewer/public/types.ts index 5a89a6037bec8..8a2f7d1f1a736 100644 --- a/src/plugins/unified_doc_viewer/public/types.ts +++ b/src/plugins/unified_doc_viewer/public/types.ts @@ -12,6 +12,7 @@ export type { UnifiedDocViewerSetup, UnifiedDocViewerStart } from './plugin'; import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; @@ -20,6 +21,7 @@ import type { UnifiedDocViewerStart } from './plugin'; export interface UnifiedDocViewerServices { analytics: AnalyticsServiceStart; data: DataPublicPluginStart; + discoverShared: DiscoverSharedPublicStart; fieldFormats: FieldFormatsStart; storage: Storage; uiSettings: IUiSettingsClient; diff --git a/tsconfig.base.json b/tsconfig.base.json index fef6173947031..5c0948d480d0f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -718,6 +718,8 @@ "@kbn/discover-enhanced-plugin/*": ["x-pack/plugins/discover_enhanced/*"], "@kbn/discover-plugin": ["src/plugins/discover"], "@kbn/discover-plugin/*": ["src/plugins/discover/*"], + "@kbn/discover-shared-plugin": ["src/plugins/discover_shared"], + "@kbn/discover-shared-plugin/*": ["src/plugins/discover_shared/*"], "@kbn/discover-utils": ["packages/kbn-discover-utils"], "@kbn/discover-utils/*": ["packages/kbn-discover-utils/*"], "@kbn/doc-links": ["packages/kbn-doc-links"], diff --git a/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc b/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc index 83400bb476a0a..7e79614b56e5a 100644 --- a/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc +++ b/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc @@ -11,6 +11,7 @@ "requiredPlugins": [ "data", "dataViews", + "discoverShared", "usageCollection", "observabilityShared", "share" diff --git a/x-pack/plugins/observability_solution/logs_shared/public/components/log_ai_assistant/index.tsx b/x-pack/plugins/observability_solution/logs_shared/public/components/log_ai_assistant/index.tsx index 881df3fcacd55..43e067b579542 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/components/log_ai_assistant/index.tsx +++ b/x-pack/plugins/observability_solution/logs_shared/public/components/log_ai_assistant/index.tsx @@ -4,9 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { dynamic } from '@kbn/shared-ux-utility'; -import { LogAIAssistantProps } from './log_ai_assistant'; +import { ObservabilityLogsAIAssistantFeatureRenderDeps } from '@kbn/discover-shared-plugin/public'; +import { LogAIAssistantDocument, LogAIAssistantProps } from './log_ai_assistant'; export const LogAIAssistant = dynamic(() => import('./log_ai_assistant')); @@ -17,3 +18,21 @@ export function createLogAIAssistant({ ); } + +export const createLogsAIAssistantRenderer = + (LogAIAssistantRender: ReturnType) => + ({ doc }: ObservabilityLogsAIAssistantFeatureRenderDeps) => { + if (!doc) return; + + const mappedDoc = useMemo( + () => ({ + fields: Object.entries(doc.flattened).map(([field, value]) => ({ + field, + value, + })) as LogAIAssistantDocument['fields'], + }), + [doc] + ); + + return ; + }; diff --git a/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts b/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts index 83ce8c2a951fa..4655a7a62f087 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts @@ -11,7 +11,7 @@ import { NodeLogsLocatorDefinition, TraceLogsLocatorDefinition, } from '../common/locators'; -import { createLogAIAssistant } from './components/log_ai_assistant'; +import { createLogAIAssistant, createLogsAIAssistantRenderer } from './components/log_ai_assistant'; import { LogViewsService } from './services/log_views'; import { LogsSharedClientCoreSetup, @@ -52,7 +52,7 @@ export class LogsSharedPlugin implements LogsSharedClientPluginClass { public start(core: CoreStart, plugins: LogsSharedClientStartDeps) { const { http } = core; - const { data, dataViews, observabilityAIAssistant } = plugins; + const { data, dataViews, discoverShared, observabilityAIAssistant } = plugins; const logViews = this.logViews.start({ http, @@ -68,6 +68,11 @@ export class LogsSharedPlugin implements LogsSharedClientPluginClass { const LogAIAssistant = createLogAIAssistant({ observabilityAIAssistant }); + discoverShared.features.registry.register({ + id: 'observability-logs-ai-assistant', + render: createLogsAIAssistantRenderer(LogAIAssistant), + }); + return { logViews, LogAIAssistant, diff --git a/x-pack/plugins/observability_solution/logs_shared/public/types.ts b/x-pack/plugins/observability_solution/logs_shared/public/types.ts index a41453cf6652d..0e89358d2e0fa 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/types.ts @@ -8,6 +8,7 @@ import type { CoreSetup, CoreStart, Plugin as PluginClass } from '@kbn/core/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public'; import { SharePluginSetup } from '@kbn/share-plugin/public'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; @@ -35,6 +36,7 @@ export interface LogsSharedClientSetupDeps { export interface LogsSharedClientStartDeps { data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; + discoverShared: DiscoverSharedPublicStart; observabilityAIAssistant?: ObservabilityAIAssistantPublicStart; uiActions: UiActionsStart; } diff --git a/yarn.lock b/yarn.lock index 01a86c1aa0031..df71fa1e727a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4488,6 +4488,10 @@ version "0.0.0" uid "" +"@kbn/discover-shared-plugin@link:src/plugins/discover_shared": + version "0.0.0" + uid "" + "@kbn/discover-utils@link:packages/kbn-discover-utils": version "0.0.0" uid ""