diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_flamegraph.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_flamegraph.tsx index 276bfa3e0ee29..dd85fabee454a 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_flamegraph.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_flamegraph.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import type { BaseFlameGraph } from '@kbn/profiling-utils'; import React from 'react'; -import { ProfilingEmbeddable } from './profiling_embeddable'; +import { css } from '@emotion/react'; +import type { BaseFlameGraph } from '@kbn/profiling-utils'; import { EMBEDDABLE_FLAMEGRAPH } from '.'; +import { getProfilingComponent } from '../helpers/component_registry'; interface Props { data?: BaseFlameGraph; @@ -16,6 +17,20 @@ interface Props { height?: string; } -export function EmbeddableFlamegraph(props: Props) { - return ; +export function EmbeddableFlamegraph({ height, ...props }: Props) { + const EmbeddableFlamegraphComponent = getProfilingComponent(EMBEDDABLE_FLAMEGRAPH); + return ( +
+ {EmbeddableFlamegraphComponent && } +
+ ); } diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx index 064d2ce7859bb..813f7c299649e 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import type { TopNFunctions } from '@kbn/profiling-utils'; import React from 'react'; +import { css } from '@emotion/react'; +import type { TopNFunctions } from '@kbn/profiling-utils'; import { EMBEDDABLE_FUNCTIONS } from '.'; -import { ProfilingEmbeddable } from './profiling_embeddable'; +import { getProfilingComponent } from '../helpers/component_registry'; interface Props { data?: TopNFunctions; @@ -18,5 +19,18 @@ interface Props { } export function EmbeddableFunctions(props: Props) { - return ; + const EmbeddableFunctionsComponent = getProfilingComponent(EMBEDDABLE_FUNCTIONS); + return ( +
+ {EmbeddableFunctionsComponent && } +
+ ); } diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_profiling_search_bar.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_profiling_search_bar.tsx index 02908cdf67a0c..aee46946a484d 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_profiling_search_bar.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_profiling_search_bar.tsx @@ -5,11 +5,10 @@ * 2.0. */ +import React from 'react'; import { css } from '@emotion/react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { default as React, useEffect, useRef, useState } from 'react'; import { EMBEDDABLE_PROFILING_SEARCH_BAR } from '.'; -import { ObservabilitySharedStart } from '../../../plugin'; +import { getProfilingComponent } from '../helpers/component_registry'; export interface EmbeddableProfilingSearchBarProps { kuery: string; @@ -24,38 +23,8 @@ export interface EmbeddableProfilingSearchBarProps { } export function EmbeddableProfilingSearchBar(props: EmbeddableProfilingSearchBarProps) { - const { embeddable: embeddablePlugin } = useKibana().services; - const [embeddable, setEmbeddable] = useState(); - const embeddableRoot: React.RefObject = useRef(null); - - useEffect(() => { - async function createEmbeddable() { - const factory = embeddablePlugin?.getEmbeddableFactory(EMBEDDABLE_PROFILING_SEARCH_BAR); - const input = { - id: 'embeddable_profiling', - }; - const embeddableObject = await factory?.create(input); - setEmbeddable(embeddableObject); - } - createEmbeddable(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - if (embeddableRoot.current && embeddable) { - embeddable.render(embeddableRoot.current); - } - }, [embeddable, embeddableRoot]); - - useEffect(() => { - if (embeddable) { - embeddable.updateInput({ - ...props, - }); - embeddable.reload(); - } - }, [embeddable, props]); - + const EmbeddableProfilingSearchBarComponent = + getProfilingComponent(EMBEDDABLE_PROFILING_SEARCH_BAR); return (
+ > + {EmbeddableProfilingSearchBarComponent && ( + + )} +
); } diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_stack_traces.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_stack_traces.tsx index c07f08b517d90..8110410aff697 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_stack_traces.tsx +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_stack_traces.tsx @@ -6,9 +6,10 @@ */ import React from 'react'; +import { css } from '@emotion/react'; import { TopNType } from '@kbn/profiling-utils'; import { EMBEDDABLE_STACK_TRACES } from '.'; -import { ProfilingEmbeddable } from './profiling_embeddable'; +import { getProfilingComponent } from '../helpers/component_registry'; interface Props { type: TopNType; @@ -20,5 +21,18 @@ interface Props { } export function EmbeddableStackTraces(props: Props) { - return ; + const EmbeddableStackTracesComponent = getProfilingComponent(EMBEDDABLE_STACK_TRACES); + return ( +
+ {EmbeddableStackTracesComponent && } +
+ ); } diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/helpers/component_registry.ts b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/helpers/component_registry.ts new file mode 100644 index 0000000000000..90af3dc789b93 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/helpers/component_registry.ts @@ -0,0 +1,34 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +const registry: { [key: string]: React.FC } = {}; + +export const registerProfilingComponent = (key: string, component: React.FC) => { + if (registry[key] !== undefined) { + throw new Error( + i18n.translate('xpack.observabilityShared.profilingComponentAlreadyExists.error', { + defaultMessage: `Component with key {key} already exists`, + values: { key }, + }) + ); + } + registry[key] = component; +}; + +export const getProfilingComponent = (key: string): React.FC => { + if (registry[key] === undefined) { + throw new Error( + i18n.translate('xpack.observabilityShared.profilingComponentNotFound.error', { + defaultMessage: `Component with key {key} not found`, + values: { key }, + }) + ); + } + return registry[key]; +}; diff --git a/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts b/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts index 97808e516f320..94c7d11ad7f69 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts +++ b/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts @@ -18,6 +18,7 @@ import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import { BehaviorSubject } from 'rxjs'; import { createLazyObservabilityPageTemplate } from './components/page_template'; import { createNavigationRegistry } from './components/page_template/helpers/navigation_registry'; +import { registerProfilingComponent } from './components/profiling/helpers/component_registry'; import { type AssetDetailsFlyoutLocator, AssetDetailsFlyoutLocatorDefinition, @@ -102,6 +103,7 @@ export class ObservabilitySharedPlugin implements Plugin { }); return { + registerProfilingComponent, locators: this.createLocators(pluginsSetup.share.url), navigation: { registerSections: this.navigationRegistry.registerSections, diff --git a/x-pack/plugins/observability_solution/profiling/kibana.jsonc b/x-pack/plugins/observability_solution/profiling/kibana.jsonc index e5df7002f4a35..329da8be36f1a 100644 --- a/x-pack/plugins/observability_solution/profiling/kibana.jsonc +++ b/x-pack/plugins/observability_solution/profiling/kibana.jsonc @@ -26,7 +26,6 @@ "observabilityShared", "unifiedSearch", "share", - "embeddable", "profilingDataAccess" ], "requiredBundles": [ diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph.tsx index b7266049b57c4..5eaed16b89953 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph.tsx @@ -4,11 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { Embeddable, EmbeddableOutput, IContainer } from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_FLAMEGRAPH } from '@kbn/observability-shared-plugin/public'; -import { createFlameGraph } from '@kbn/profiling-utils'; +import { BaseFlameGraph, createFlameGraph } from '@kbn/profiling-utils'; import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; import { profilingShowErrorFrames } from '@kbn/observability-plugin/common'; import { FlameGraph } from '../../components/flamegraph'; import { AsyncEmbeddableComponent } from '../async_embeddable_component'; @@ -16,48 +13,26 @@ import { ProfilingEmbeddableProvider, ProfilingEmbeddablesDependencies, } from '../profiling_embeddable_provider'; -import { EmbeddableFlamegraphEmbeddableInput } from './embeddable_flamegraph_factory'; import { useProfilingDependencies } from '../../components/contexts/profiling_dependencies/use_profiling_dependencies'; -export class EmbeddableFlamegraph extends Embeddable< - EmbeddableFlamegraphEmbeddableInput, - EmbeddableOutput -> { - readonly type = EMBEDDABLE_FLAMEGRAPH; - private _domNode?: HTMLElement; +export type EmbeddableFlamegraphProps = FlamegraphProps & ProfilingEmbeddablesDependencies; - constructor( - private deps: ProfilingEmbeddablesDependencies, - initialInput: EmbeddableFlamegraphEmbeddableInput, - parent?: IContainer - ) { - super(initialInput, {}, parent); - } +export type EmbeddableFlamegraphSharedComponent = React.FC; - render(domNode: HTMLElement) { - this._domNode = domNode; - render( - - - , - domNode - ); - } - - public destroy() { - if (this._domNode) { - unmountComponentAtNode(this._domNode); - } - } +export interface FlamegraphProps { + data?: BaseFlameGraph; + isLoading: boolean; +} - reload() { - if (this._domNode) { - this.render(this._domNode); - } - } +export function EmbeddableFlamegraph({ data, isLoading, ...deps }: EmbeddableFlamegraphProps) { + return ( + + + + ); } -function Flamegraph({ isLoading, data }: EmbeddableFlamegraphEmbeddableInput) { +function Flamegraph({ isLoading, data }: FlamegraphProps) { const { core } = useProfilingDependencies().start; const showErrorFrames = core.uiSettings.get(profilingShowErrorFrames); const flamegraph = !isLoading && data ? createFlameGraph(data, showErrorFrames) : undefined; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph_factory.ts b/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph_factory.ts deleted file mode 100644 index 259c61df525e0..0000000000000 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/embeddable_flamegraph_factory.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 { - EmbeddableFactoryDefinition, - EmbeddableInput, - IContainer, -} from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_FLAMEGRAPH } from '@kbn/observability-shared-plugin/public'; -import type { BaseFlameGraph } from '@kbn/profiling-utils'; -import type { GetProfilingEmbeddableDependencies } from '../profiling_embeddable_provider'; - -interface EmbeddableFlamegraphInput { - data?: BaseFlameGraph; - isLoading: boolean; -} - -export type EmbeddableFlamegraphEmbeddableInput = EmbeddableFlamegraphInput & EmbeddableInput; - -export class EmbeddableFlamegraphFactory - implements EmbeddableFactoryDefinition -{ - readonly type = EMBEDDABLE_FLAMEGRAPH; - - constructor(private getProfilingEmbeddableDependencies: GetProfilingEmbeddableDependencies) {} - - async isEditable() { - return false; - } - - async create(input: EmbeddableFlamegraphEmbeddableInput, parent?: IContainer) { - const { EmbeddableFlamegraph } = await import('./embeddable_flamegraph'); - const deps = await this.getProfilingEmbeddableDependencies(); - return new EmbeddableFlamegraph(deps, input, parent); - } - - getDisplayName() { - return 'Universal Profiling Flamegraph'; - } -} diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/index.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/index.tsx new file mode 100644 index 0000000000000..67efb183fd459 --- /dev/null +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/flamegraph/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { dynamic } from '@kbn/shared-ux-utility'; +import type { EmbeddableFlamegraphSharedComponent, FlamegraphProps } from './embeddable_flamegraph'; +import { ProfilingEmbeddablesDependencies } from '../profiling_embeddable_provider'; + +const LazyEmbeddableFlamegraph = dynamic(async () => { + const Component = await import('./embeddable_flamegraph'); + return { default: Component.EmbeddableFlamegraph }; +}); + +export const getEmbeddableFlamegraphComponent = ( + profilingEmbeddableDependencies: ProfilingEmbeddablesDependencies +): EmbeddableFlamegraphSharedComponent => { + return (props: FlamegraphProps) => { + return ; + }; +}; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx index 9a198ae66e262..e281f12224c8f 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx @@ -4,58 +4,42 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { Embeddable, EmbeddableOutput, IContainer } from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_FUNCTIONS } from '@kbn/observability-shared-plugin/public'; -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; + +import React, { useMemo } from 'react'; +import { TopNFunctions } from '@kbn/profiling-utils'; import { AsyncEmbeddableComponent } from '../async_embeddable_component'; import { ProfilingEmbeddableProvider, ProfilingEmbeddablesDependencies, } from '../profiling_embeddable_provider'; -import { EmbeddableFunctionsEmbeddableInput } from './embeddable_functions_factory'; import { EmbeddableFunctionsGrid } from './embeddable_functions_grid'; -export class EmbeddableFunctions extends Embeddable< - EmbeddableFunctionsEmbeddableInput, - EmbeddableOutput -> { - readonly type = EMBEDDABLE_FUNCTIONS; - private _domNode?: HTMLElement; - - constructor( - private deps: ProfilingEmbeddablesDependencies, - initialInput: EmbeddableFunctionsEmbeddableInput, - parent?: IContainer - ) { - super(initialInput, {}, parent); - } +export type EmbeddableFunctionsProps = FunctionsProps & ProfilingEmbeddablesDependencies; - render(domNode: HTMLElement) { - this._domNode = domNode; - const { data, isLoading, rangeFrom, rangeTo } = this.input; - const totalSeconds = (rangeTo - rangeFrom) / 1000; - render( - - -
- -
-
-
, - domNode - ); - } +export type EmbeddableFunctionsSharedComponent = React.FC; - public destroy() { - if (this._domNode) { - unmountComponentAtNode(this._domNode); - } - } +export interface FunctionsProps { + data?: TopNFunctions; + isLoading: boolean; + rangeFrom: number; + rangeTo: number; +} - reload() { - if (this._domNode) { - this.render(this._domNode); - } - } +export function EmbeddableFunctions({ + data, + isLoading, + rangeFrom, + rangeTo, + ...deps +}: EmbeddableFunctionsProps) { + const totalSeconds = useMemo(() => (rangeTo - rangeFrom) / 1000, [rangeFrom, rangeTo]); + return ( + + +
+ +
+
+
+ ); } diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_factory.ts b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_factory.ts deleted file mode 100644 index 99e0d4baa4859..0000000000000 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_factory.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 { - EmbeddableFactoryDefinition, - EmbeddableInput, - IContainer, -} from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_FUNCTIONS } from '@kbn/observability-shared-plugin/public'; -import type { TopNFunctions } from '@kbn/profiling-utils'; -import { GetProfilingEmbeddableDependencies } from '../profiling_embeddable_provider'; - -interface EmbeddableFunctionsInput { - data?: TopNFunctions; - isLoading: boolean; - rangeFrom: number; - rangeTo: number; -} - -export type EmbeddableFunctionsEmbeddableInput = EmbeddableFunctionsInput & EmbeddableInput; - -export class EmbeddableFunctionsFactory - implements EmbeddableFactoryDefinition -{ - readonly type = EMBEDDABLE_FUNCTIONS; - - constructor(private getProfilingEmbeddableDependencies: GetProfilingEmbeddableDependencies) {} - - async isEditable() { - return false; - } - - async create(input: EmbeddableFunctionsEmbeddableInput, parent?: IContainer) { - const { EmbeddableFunctions } = await import('./embeddable_functions'); - const deps = await this.getProfilingEmbeddableDependencies(); - return new EmbeddableFunctions(deps, input, parent); - } - - getDisplayName() { - return 'Universal Profiling Functions'; - } -} diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/index.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/index.tsx new file mode 100644 index 0000000000000..849907c57dab1 --- /dev/null +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { dynamic } from '@kbn/shared-ux-utility'; +import type { EmbeddableFunctionsSharedComponent, FunctionsProps } from './embeddable_functions'; +import { ProfilingEmbeddablesDependencies } from '../profiling_embeddable_provider'; + +const LazyEmbeddableFunctions = dynamic(async () => { + const Component = await import('./embeddable_functions'); + return { default: Component.EmbeddableFunctions }; +}); + +export const getEmbeddableFunctionsComponent = ( + profilingEmbeddableDependencies: ProfilingEmbeddablesDependencies +): EmbeddableFunctionsSharedComponent => { + return (props: FunctionsProps) => { + return ; + }; +}; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/profiling_embeddable_provider.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/profiling_embeddable_provider.tsx index 52000e4783620..3a26ede4faac1 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/profiling_embeddable_provider.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/profiling_embeddable_provider.tsx @@ -15,7 +15,7 @@ import { Services } from '../services'; export interface ProfilingEmbeddablesDependencies { coreStart: CoreStart; - coreSetup: CoreSetup; + coreSetup: CoreSetup; pluginsStart: ProfilingPluginPublicStartDeps; pluginsSetup: ProfilingPluginPublicSetupDeps; profilingFetchServices: Services; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/register_embeddables.ts b/x-pack/plugins/observability_solution/profiling/public/embeddables/register_embeddables.ts index 850ab8998e893..f4a775f007739 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/register_embeddables.ts +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/register_embeddables.ts @@ -5,37 +5,36 @@ * 2.0. */ -import { EmbeddableSetup } from '@kbn/embeddable-plugin/public'; import { EMBEDDABLE_FLAMEGRAPH, EMBEDDABLE_FUNCTIONS, EMBEDDABLE_PROFILING_SEARCH_BAR, EMBEDDABLE_STACK_TRACES, } from '@kbn/observability-shared-plugin/public'; -import { EmbeddableFlamegraphFactory } from './flamegraph/embeddable_flamegraph_factory'; -import { EmbeddableFunctionsFactory } from './functions/embeddable_functions_factory'; -import { GetProfilingEmbeddableDependencies } from './profiling_embeddable_provider'; -import { EmbeddableSearchBarFactory } from './search_bar/embeddable_search_bar_factory'; -import { EmbeddableStackTracesFactory } from './stack_traces/embeddable_stack_traces_factory'; +import { getEmbeddableFlamegraphComponent } from './flamegraph'; +import { getEmbeddableFunctionsComponent } from './functions'; +import { ProfilingEmbeddablesDependencies } from './profiling_embeddable_provider'; +import { getEmbeddableStackTracesComponent } from './stack_traces'; +import { getEmbeddableSearchBarComponent } from './search_bar'; -export function registerEmbeddables( - embeddable: EmbeddableSetup, - getProfilingEmbeddableDependencies: GetProfilingEmbeddableDependencies -) { - embeddable.registerEmbeddableFactory( +export function registerEmbeddables(deps: ProfilingEmbeddablesDependencies) { + const { + pluginsSetup: { observabilityShared }, + } = deps; + observabilityShared.registerProfilingComponent( EMBEDDABLE_FLAMEGRAPH, - new EmbeddableFlamegraphFactory(getProfilingEmbeddableDependencies) + getEmbeddableFlamegraphComponent(deps) ); - embeddable.registerEmbeddableFactory( + observabilityShared.registerProfilingComponent( EMBEDDABLE_FUNCTIONS, - new EmbeddableFunctionsFactory(getProfilingEmbeddableDependencies) + getEmbeddableFunctionsComponent(deps) ); - embeddable.registerEmbeddableFactory( + observabilityShared.registerProfilingComponent( EMBEDDABLE_PROFILING_SEARCH_BAR, - new EmbeddableSearchBarFactory(getProfilingEmbeddableDependencies) + getEmbeddableSearchBarComponent(deps) ); - embeddable.registerEmbeddableFactory( + observabilityShared.registerProfilingComponent( EMBEDDABLE_STACK_TRACES, - new EmbeddableStackTracesFactory(getProfilingEmbeddableDependencies) + getEmbeddableStackTracesComponent(deps) ); } diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar.tsx index e32f514ff5ac5..1c370e96501d0 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar.tsx @@ -5,74 +5,52 @@ * 2.0. */ import { css } from '@emotion/react'; -import { Embeddable, EmbeddableOutput, IContainer } from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_PROFILING_SEARCH_BAR } from '@kbn/observability-shared-plugin/public'; +import { EmbeddableProfilingSearchBarProps } from '@kbn/observability-shared-plugin/public'; import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; import { ProfilingSearchBar } from '../../components/profiling_app_page_template/profiling_search_bar'; import { ProfilingEmbeddableProvider, ProfilingEmbeddablesDependencies, } from '../profiling_embeddable_provider'; -import { EmbeddableSearchBarEmbeddableInput } from './embeddable_search_bar_factory'; -export class EmbeddableSearchBar extends Embeddable< - EmbeddableSearchBarEmbeddableInput, - EmbeddableOutput -> { - readonly type = EMBEDDABLE_PROFILING_SEARCH_BAR; - private _domNode?: HTMLElement; +export type EmbeddableSearchBarProps = EmbeddableProfilingSearchBarProps & + ProfilingEmbeddablesDependencies; - constructor( - private deps: ProfilingEmbeddablesDependencies, - initialInput: EmbeddableSearchBarEmbeddableInput, - parent?: IContainer - ) { - super(initialInput, {}, parent); - } +export type EmbeddableSearchBarSharedComponent = React.FC; - render(domNode: HTMLElement) { - this._domNode = domNode; - const { showDatePicker, kuery, onQuerySubmit, onRefresh, rangeFrom, rangeTo } = this.input; - - render( - -
- { - onQuerySubmit({ - dateRange, - query: typeof query?.query === 'string' ? query.query : '', - }); - }} - onRefresh={onRefresh} - onRefreshClick={onRefresh} - showQueryMenu={false} - rangeFrom={rangeFrom} - rangeTo={rangeTo} - /> -
-
, - domNode - ); - } - - public destroy() { - if (this._domNode) { - unmountComponentAtNode(this._domNode); - } - } - - reload() { - if (this._domNode) { - this.render(this._domNode); - } - } +export function EmbeddableSearchBar({ + showDatePicker, + kuery, + onQuerySubmit, + onRefresh, + rangeFrom, + rangeTo, + ...deps +}: EmbeddableSearchBarProps) { + return ( + +
+ { + onQuerySubmit({ + dateRange, + query: typeof query?.query === 'string' ? query.query : '', + }); + }} + onRefresh={onRefresh} + onRefreshClick={onRefresh} + showQueryMenu={false} + rangeFrom={rangeFrom} + rangeTo={rangeTo} + /> +
+
+ ); } diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar_factory.ts b/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar_factory.ts deleted file mode 100644 index cc7443976e1b1..0000000000000 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/embeddable_search_bar_factory.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 { - EmbeddableFactoryDefinition, - EmbeddableInput, - IContainer, -} from '@kbn/embeddable-plugin/public'; -import { - EmbeddableProfilingSearchBarProps, - EMBEDDABLE_PROFILING_SEARCH_BAR, -} from '@kbn/observability-shared-plugin/public'; -import type { GetProfilingEmbeddableDependencies } from '../profiling_embeddable_provider'; - -export type EmbeddableSearchBarEmbeddableInput = EmbeddableProfilingSearchBarProps & - EmbeddableInput; - -export class EmbeddableSearchBarFactory - implements EmbeddableFactoryDefinition -{ - readonly type = EMBEDDABLE_PROFILING_SEARCH_BAR; - - constructor(private getProfilingEmbeddableDependencies: GetProfilingEmbeddableDependencies) {} - - async isEditable() { - return false; - } - - async create(input: EmbeddableSearchBarEmbeddableInput, parent?: IContainer) { - const { EmbeddableSearchBar } = await import('./embeddable_search_bar'); - const deps = await this.getProfilingEmbeddableDependencies(); - return new EmbeddableSearchBar(deps, input, parent); - } - - getDisplayName() { - return 'Universal Profiling Search bar'; - } -} diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/index.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/index.tsx new file mode 100644 index 0000000000000..f010ade0f2480 --- /dev/null +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/search_bar/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { dynamic } from '@kbn/shared-ux-utility'; +import type { EmbeddableSearchBarSharedComponent } from './embeddable_search_bar'; +import { ProfilingEmbeddablesDependencies } from '../profiling_embeddable_provider'; + +const LazyEmbeddableSearchBar = dynamic(async () => { + const Component = await import('./embeddable_search_bar'); + return { default: Component.EmbeddableSearchBar }; +}); + +export const getEmbeddableSearchBarComponent = ( + profilingEmbeddableDependencies: ProfilingEmbeddablesDependencies +): EmbeddableSearchBarSharedComponent => { + return (props) => { + return ; + }; +}; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces.tsx index 938a2c85810f4..efc9aeda9c6bd 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces.tsx @@ -4,54 +4,39 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { Embeddable, EmbeddableOutput, IContainer } from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_STACK_TRACES } from '@kbn/observability-shared-plugin/public'; + import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; import { ProfilingEmbeddableProvider, ProfilingEmbeddablesDependencies, } from '../profiling_embeddable_provider'; -import { EmbeddableStackTracesEmbeddableInput } from './embeddable_stack_traces_factory'; -import { StackTraces } from './stack_traces'; - -export class EmbeddableStackTraces extends Embeddable< - EmbeddableStackTracesEmbeddableInput, - EmbeddableOutput -> { - readonly type = EMBEDDABLE_STACK_TRACES; - private _domNode?: HTMLElement; - - constructor( - private deps: ProfilingEmbeddablesDependencies, - initialInput: EmbeddableStackTracesEmbeddableInput, - parent?: IContainer - ) { - super(initialInput, {}, parent); - } +import { StackTraces, StackTracesProps } from './stack_traces'; - render(domNode: HTMLElement) { - this._domNode = domNode; - const props = this.input; - render( - -
- -
-
, - domNode - ); - } +export type EmbeddableStackTracesProps = StackTracesProps & ProfilingEmbeddablesDependencies; - public destroy() { - if (this._domNode) { - unmountComponentAtNode(this._domNode); - } - } +export type EmbeddableStackTracesSharedComponent = React.FC; - reload() { - if (this._domNode) { - this.render(this._domNode); - } - } +export function EmbeddableStackTraces({ + type, + kuery, + rangeFrom, + rangeTo, + onClick, + onChartBrushEnd, + ...deps +}: EmbeddableStackTracesProps) { + return ( + +
+ +
+
+ ); } diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces_factory.ts b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces_factory.ts deleted file mode 100644 index e079f1a7c4754..0000000000000 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/embeddable_stack_traces_factory.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 { - EmbeddableFactoryDefinition, - EmbeddableInput, - IContainer, -} from '@kbn/embeddable-plugin/public'; -import { EMBEDDABLE_STACK_TRACES } from '@kbn/observability-shared-plugin/public'; -import { TopNType } from '@kbn/profiling-utils'; -import { GetProfilingEmbeddableDependencies } from '../profiling_embeddable_provider'; - -interface EmbeddableStackTracesInput { - type: TopNType; - kuery: string; - rangeFrom: number; - rangeTo: number; - onClick: (category: string) => void; - onChartBrushEnd: (range: { rangeFrom: string; rangeTo: string }) => void; -} - -export type EmbeddableStackTracesEmbeddableInput = EmbeddableStackTracesInput & EmbeddableInput; - -export class EmbeddableStackTracesFactory - implements EmbeddableFactoryDefinition -{ - readonly type = EMBEDDABLE_STACK_TRACES; - - constructor(private getProfilingEmbeddableDependencies: GetProfilingEmbeddableDependencies) {} - - async isEditable() { - return false; - } - - async create(input: EmbeddableStackTracesEmbeddableInput, parent?: IContainer) { - const { EmbeddableStackTraces } = await import('./embeddable_stack_traces'); - const deps = await this.getProfilingEmbeddableDependencies(); - return new EmbeddableStackTraces(deps, input, parent); - } - - getDisplayName() { - return 'Universal Profiling Threads'; - } -} diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/index.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/index.tsx new file mode 100644 index 0000000000000..29631941cd30e --- /dev/null +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/index.tsx @@ -0,0 +1,25 @@ +/* + * 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 React from 'react'; +import { dynamic } from '@kbn/shared-ux-utility'; +import type { EmbeddableStackTracesSharedComponent } from './embeddable_stack_traces'; +import { ProfilingEmbeddablesDependencies } from '../profiling_embeddable_provider'; +import type { StackTracesProps } from './stack_traces'; + +const LazyEmbeddableStackTraces = dynamic(async () => { + const Component = await import('./embeddable_stack_traces'); + return { default: Component.EmbeddableStackTraces }; +}); + +export const getEmbeddableStackTracesComponent = ( + profilingEmbeddableDependencies: ProfilingEmbeddablesDependencies +): EmbeddableStackTracesSharedComponent => { + return (props: StackTracesProps) => { + return ; + }; +}; diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/stack_traces.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/stack_traces.tsx index 3205f04120012..9aae8b0ecc309 100644 --- a/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/stack_traces.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/stack_traces/stack_traces.tsx @@ -13,7 +13,7 @@ import { AsyncStatus, useAsync } from '../../hooks/use_async'; import { EmptyDataPrompt } from '../empty_data_prompt'; import { ErrorPrompt } from '../error_prompt'; -interface Props { +export interface StackTracesProps { type: TopNType; kuery: string; rangeFrom: number; @@ -22,7 +22,14 @@ interface Props { onChartBrushEnd: (range: { rangeFrom: string; rangeTo: string }) => void; } -export function StackTraces({ type, kuery, rangeFrom, rangeTo, onClick, onChartBrushEnd }: Props) { +export function StackTraces({ + type, + kuery, + rangeFrom, + rangeTo, + onClick, + onChartBrushEnd, +}: StackTracesProps) { const { services: { fetchTopN }, } = useProfilingDependencies(); diff --git a/x-pack/plugins/observability_solution/profiling/public/plugin.tsx b/x-pack/plugins/observability_solution/profiling/public/plugin.tsx index e241d47934730..fca4f8dcb4c6b 100644 --- a/x-pack/plugins/observability_solution/profiling/public/plugin.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/plugin.tsx @@ -13,7 +13,7 @@ import { Plugin, } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import type { NavigationSection } from '@kbn/observability-shared-plugin/public'; +import { NavigationSection } from '@kbn/observability-shared-plugin/public'; import type { Location } from 'history'; import { BehaviorSubject, combineLatest, from, map } from 'rxjs'; import { OBLT_PROFILING_APP_ID } from '@kbn/deeplinks-observability'; @@ -25,8 +25,19 @@ import { ProfilingEmbeddablesDependencies } from './embeddables/profiling_embedd export type ProfilingPluginSetup = void; export type ProfilingPluginStart = void; -export class ProfilingPlugin implements Plugin { - public setup(coreSetup: CoreSetup, pluginsSetup: ProfilingPluginPublicSetupDeps) { +export class ProfilingPlugin + implements + Plugin< + ProfilingPluginSetup, + ProfilingPluginStart, + ProfilingPluginPublicSetupDeps, + ProfilingPluginPublicStartDeps + > +{ + public setup( + coreSetup: CoreSetup, + pluginsSetup: ProfilingPluginPublicSetupDeps + ) { // Register an application into the side navigation menu const links = [ { @@ -93,11 +104,7 @@ export class ProfilingPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.observability, deepLinks: links, async mount({ element, history, theme$, setHeaderActionMenu }: AppMountParameters) { - const [coreStart, pluginsStart] = (await coreSetup.getStartServices()) as [ - CoreStart, - ProfilingPluginPublicStartDeps, - unknown - ]; + const [coreStart, pluginsStart] = await coreSetup.getStartServices(); const { renderApp } = await import('./app'); @@ -133,11 +140,7 @@ export class ProfilingPlugin implements Plugin { const getProfilingEmbeddableDependencies = async (): Promise => { - const [coreStart, pluginsStart] = (await coreSetup.getStartServices()) as [ - CoreStart, - ProfilingPluginPublicStartDeps, - unknown - ]; + const [coreStart, pluginsStart] = await coreSetup.getStartServices(); return { coreStart, coreSetup, @@ -147,7 +150,9 @@ export class ProfilingPlugin implements Plugin { }; }; - registerEmbeddables(pluginsSetup.embeddable, getProfilingEmbeddableDependencies); + getProfilingEmbeddableDependencies().then((deps) => { + registerEmbeddables(deps); + }); return {}; } diff --git a/x-pack/plugins/observability_solution/profiling/public/types.ts b/x-pack/plugins/observability_solution/profiling/public/types.ts index 9a7f959b34bb3..89a8f999010ce 100644 --- a/x-pack/plugins/observability_solution/profiling/public/types.ts +++ b/x-pack/plugins/observability_solution/profiling/public/types.ts @@ -24,7 +24,6 @@ import { ObservabilityAIAssistantPublicSetup, ObservabilityAIAssistantPublicStart, } from '@kbn/observability-ai-assistant-plugin/public'; -import { EmbeddableSetup } from '@kbn/embeddable-plugin/public'; import type { UnifiedSearchPublicPluginStart, UnifiedSearchPluginSetup, @@ -39,7 +38,6 @@ export interface ProfilingPluginPublicSetupDeps { charts: ChartsPluginSetup; licensing: LicensingPluginSetup; share: SharePluginSetup; - embeddable: EmbeddableSetup; unifiedSearch: UnifiedSearchPluginSetup; } diff --git a/x-pack/plugins/observability_solution/profiling/tsconfig.json b/x-pack/plugins/observability_solution/profiling/tsconfig.json index 1f18459455e7e..937eee96641c8 100644 --- a/x-pack/plugins/observability_solution/profiling/tsconfig.json +++ b/x-pack/plugins/observability_solution/profiling/tsconfig.json @@ -48,7 +48,6 @@ "@kbn/usage-collection-plugin", "@kbn/observability-ai-assistant-plugin", "@kbn/profiling-data-access-plugin", - "@kbn/embeddable-plugin", "@kbn/profiling-utils", "@kbn/security-plugin", "@kbn/shared-ux-utility",