mirror of
https://github.com/elastic/kibana.git
synced 2025-04-18 23:21:39 -04:00
## Summary Start relocating Kibana modules (packages and plugins) to the new folder structure, according to the _Kibana Sustainable Architecture_ initiative. #### 16 plugin(s) are going to be relocated: | Id | Target folder | | -- | ------------- | | `@kbn/cloud-chat-plugin` | `x-pack/platform/plugins/private/cloud_integrations/cloud_chat` | | `@kbn/cloud-experiments-plugin` | `x-pack/platform/plugins/shared/cloud_integrations/cloud_experiments` | | `@kbn/cloud-full-story-plugin` | `x-pack/platform/plugins/private/cloud_integrations/cloud_full_story` | | `@kbn/cloud-links-plugin` | `x-pack/platform/plugins/private/cloud_integrations/cloud_links` | | `@kbn/cloud-plugin` | `x-pack/platform/plugins/shared/cloud` | | `@kbn/features-plugin` | `x-pack/platform/plugins/shared/features` | | `@kbn/ftr-apis-plugin` | `src/platform/plugins/private/ftr_apis` | | `@kbn/kibana-usage-collection-plugin` | `src/platform/plugins/private/kibana_usage_collection` | | `@kbn/licensing-plugin` | `x-pack/platform/plugins/shared/licensing` | | `@kbn/newsfeed-plugin` | `src/platform/plugins/shared/newsfeed` | | `@kbn/saved-objects-management-plugin` | `src/platform/plugins/shared/saved_objects_management` | | `@kbn/telemetry-collection-manager-plugin` | `src/platform/plugins/shared/telemetry_collection_manager` | | `@kbn/telemetry-collection-xpack-plugin` | `x-pack/platform/plugins/private/telemetry_collection_xpack` | | `@kbn/telemetry-management-section-plugin` | `src/platform/plugins/shared/telemetry_management_section` | | `@kbn/telemetry-plugin` | `src/platform/plugins/shared/telemetry` | | `@kbn/usage-collection-plugin` | `src/platform/plugins/shared/usage_collection` | #### 22 package(s) are going to be relocated: | Id | Target folder | | -- | ------------- | | `@kbn/analytics` | `src/platform/packages/shared/kbn-analytics` | | `@kbn/analytics-collection-utils` | `src/platform/packages/private/analytics/utils/analytics_collection_utils` | | `@kbn/apm-config-loader` | `src/platform/packages/private/kbn-apm-config-loader` | | `@kbn/cloud` | `src/platform/packages/shared/cloud` | | `@kbn/config` | `src/platform/packages/shared/kbn-config` | | `@kbn/config-mocks` | `src/platform/packages/private/kbn-config-mocks` | | `@kbn/config-schema` | `src/platform/packages/shared/kbn-config-schema` | | `@kbn/crypto-browser` | `src/platform/packages/shared/kbn-crypto-browser` | | `@kbn/ebt-tools` | `src/platform/packages/shared/kbn-ebt-tools` | | `@kbn/es-errors` | `src/platform/packages/shared/kbn-es-errors` | | `@kbn/es-types` | `src/platform/packages/shared/kbn-es-types` | | `@kbn/hapi-mocks` | `src/platform/packages/private/kbn-hapi-mocks` | | `@kbn/health-gateway-server` | `src/platform/packages/private/kbn-health-gateway-server` | | `@kbn/i18n` | `src/platform/packages/shared/kbn-i18n` | | `@kbn/i18n-react` | `src/platform/packages/shared/kbn-i18n-react` | | `@kbn/logging` | `src/platform/packages/shared/kbn-logging` | | `@kbn/logging-mocks` | `src/platform/packages/shared/kbn-logging-mocks` | | `@kbn/router-to-openapispec` | `src/platform/packages/shared/kbn-router-to-openapispec` | | `@kbn/server-http-tools` | `src/platform/packages/shared/kbn-server-http-tools` | | `@kbn/std` | `src/platform/packages/shared/kbn-std` | | `@kbn/utility-types` | `src/platform/packages/shared/kbn-utility-types` | | `@kbn/zod` | `src/platform/packages/shared/kbn-zod` | --------- Co-authored-by: Alejandro Fernández Haro <alejandro.haro@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
340 lines
11 KiB
Text
340 lines
11 KiB
Text
[[kibana-platform-plugin-api]]
|
||
== {kib} Plugin API
|
||
|
||
experimental[]
|
||
|
||
{kib} platform plugins are a significant step toward stabilizing {kib} architecture for all the developers.
|
||
We made sure plugins could continue to use most of the same technologies they use today, at least from a technical perspective.
|
||
|
||
=== Anatomy of a plugin
|
||
|
||
Plugins are defined as classes and present themselves to {kib}
|
||
through a simple wrapper function. A plugin can have browser-side code,
|
||
server-side code, or both. There is no architectural difference between
|
||
a plugin in the browser and a plugin on the server.
|
||
In both places, you describe your plugin similarly, and you interact with
|
||
Core and other plugins in the same way.
|
||
|
||
The basic file structure of a {kib} plugin named `demo` that
|
||
has both client-side and server-side code would be:
|
||
|
||
[source,tree]
|
||
----
|
||
plugins/
|
||
demo
|
||
kibana.json [1]
|
||
public
|
||
index.ts [2]
|
||
plugin.ts [3]
|
||
server
|
||
index.ts [4]
|
||
plugin.ts [5]
|
||
----
|
||
|
||
*[1] `kibana.json`* is a static manifest file that is used to identify the
|
||
plugin and to specify if this plugin has server-side code, browser-side code, or both:
|
||
|
||
[source,json]
|
||
----
|
||
{
|
||
"id": "demo",
|
||
"version": "kibana",
|
||
"server": true,
|
||
"ui": true
|
||
}
|
||
----
|
||
|
||
Learn about the {kib-repo}blob/{branch}/src/core/packages/plugins/server/src/types.ts[manifest
|
||
file format].
|
||
|
||
NOTE: `package.json` files are irrelevant to and ignored by {kib} for discovering and loading plugins.
|
||
|
||
*[2] `public/index.ts`* is the entry point into the client-side code of
|
||
this plugin. It must export a function named `plugin`, which will
|
||
receive {kib-repo}blob/{branch}/src/core/packages/plugins/browser/src/plugin_initializer.ts[a standard set of core capabilities] as an argument.
|
||
It should return an instance of its plugin class for
|
||
{kib} to load.
|
||
|
||
[source,typescript]
|
||
----
|
||
import type { PluginInitializerContext } from '@kbn/core/server';
|
||
import { MyPlugin } from './plugin';
|
||
|
||
export function plugin(initializerContext: PluginInitializerContext) {
|
||
return new MyPlugin(initializerContext);
|
||
}
|
||
----
|
||
|
||
*[3] `public/plugin.ts`* is the client-side plugin definition itself.
|
||
Technically speaking, it does not need to be a class or even a separate
|
||
file from the entry point, but _all plugins at Elastic_ should be
|
||
consistent in this way. See all {kib-repo}blob/{branch}/src/core/CONVENTIONS.md[conventions
|
||
for first-party Elastic plugins].
|
||
|
||
[source,typescript]
|
||
----
|
||
import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from '@kbn/core/server';
|
||
|
||
export class MyPlugin implements Plugin {
|
||
constructor(initializerContext: PluginInitializerContext) {}
|
||
|
||
public setup(core: CoreSetup) {
|
||
// called when plugin is setting up during Kibana's startup sequence
|
||
}
|
||
|
||
public start(core: CoreStart) {
|
||
// called after all plugins are set up
|
||
}
|
||
|
||
public stop() {
|
||
// called when plugin is torn down during Kibana's shutdown sequence
|
||
}
|
||
}
|
||
----
|
||
|
||
*[4] `server/index.ts`* is the entry-point into the server-side code of
|
||
this plugin. {kib-repo}blob/{branch}/src/core/packages/plugins/server/src/types.ts[It is identical] in almost every way to the client-side
|
||
entry-point:
|
||
|
||
|
||
[source,typescript]
|
||
----
|
||
import type { PluginInitializerContext } from '@kbn/core/server';
|
||
|
||
export async function plugin(initializerContext: PluginInitializerContext) {
|
||
const { MyPlugin } = await import('./plugin');
|
||
return new MyPlugin(initializerContext);
|
||
}
|
||
----
|
||
|
||
*[5] `server/plugin.ts`* is the server-side plugin definition. The
|
||
shape of this plugin is the same as it’s client-side counter-part:
|
||
|
||
[source,typescript]
|
||
----
|
||
import type { Plugin, PluginInitializerContext, CoreSetup, CoreStart } from '@kbn/core/server';
|
||
|
||
export class MyPlugin implements Plugin {
|
||
constructor(initializerContext: PluginInitializerContext) {}
|
||
|
||
public setup(core: CoreSetup) {
|
||
// called when plugin is setting up during Kibana's startup sequence
|
||
}
|
||
|
||
public start(core: CoreStart) {
|
||
// called after all plugins are set up
|
||
}
|
||
|
||
public stop() {
|
||
// called when plugin is torn down during Kibana's shutdown sequence
|
||
}
|
||
}
|
||
----
|
||
|
||
{kib} does not impose any technical restrictions on how the
|
||
the internals of a plugin are architected, though there are certain
|
||
considerations related to how plugins integrate with core APIs
|
||
and APIs exposed by other plugins that may greatly impact how
|
||
they are built.
|
||
[[plugin-lifecycles]]
|
||
=== Lifecycles & Core Services
|
||
|
||
The various independent domains that makeup `core` are represented by a
|
||
series of services and many of those services expose public interfaces
|
||
that are provided to all plugins. Services expose different features
|
||
at different parts of their lifecycle. We describe the lifecycle of
|
||
core services and plugins with specifically-named functions on the
|
||
service definition.
|
||
|
||
{kib} has three lifecycles: `setup`,
|
||
`start`, and `stop`. Each plugin's `setup` functions is called sequentially
|
||
while Kibana is setting up on the server or when it is being loaded in
|
||
the browser. The `start` functions are called sequentially after `setup`
|
||
has been completed for all plugins. The `stop` functions are called
|
||
sequentially while Kibana is gracefully shutting down the server or
|
||
when the browser tab or window is being closed.
|
||
|
||
The table below explains how each lifecycle relates to the state
|
||
of Kibana.
|
||
|
||
[width="100%",cols="10%, 15%, 37%, 38%",options="header",]
|
||
|===
|
||
|lifecycle | purpose| server |browser
|
||
|_setup_
|
||
|perform "registration" work to setup environment for runtime
|
||
|configure REST API endpoint, register saved object types, etc.
|
||
|configure application routes in SPA, register custom UI elements in extension points, etc.
|
||
|
||
|_start_
|
||
|bootstrap runtime logic
|
||
|respond to an incoming request, request Elasticsearch server, etc.
|
||
|start polling Kibana server, update DOM tree in response to user interactions, etc.
|
||
|
||
|_stop_
|
||
|cleanup runtime
|
||
|dispose of active handles before the server shutdown.
|
||
|store session data in the LocalStorage when the user navigates away from {kib}, etc.
|
||
|===
|
||
|
||
Conversely, there is no equivalent to `uiExports` in Kibana Platform plugins.
|
||
As a general rule of thumb, features that were registered via `uiExports` are
|
||
now registered during the `setup` phase. Most of everything else should move
|
||
to the `start` phase.
|
||
|
||
The lifecycle-specific contracts exposed by core services are always
|
||
passed as the first argument to the equivalent lifecycle function in a
|
||
plugin. For example, the core `http` service exposes a function
|
||
`createRouter` to all plugin `setup` functions. To use this function to register
|
||
an HTTP route handler, a plugin just accesses it off of the first argument:
|
||
|
||
[source, typescript]
|
||
----
|
||
import type { CoreSetup } from '@kbn/core/server';
|
||
|
||
export class MyPlugin {
|
||
public setup(core: CoreSetup) {
|
||
const router = core.http.createRouter();
|
||
// handler is called when '/path' resource is requested with `GET` method
|
||
router.get({ path: '/path', validate: false }, (context, req, res) => res.ok({ content: 'ok' }));
|
||
}
|
||
}
|
||
----
|
||
|
||
Different service interfaces can and will be passed to `setup`, `start`, and
|
||
`stop` because certain functionality makes sense in the context of a
|
||
running plugin while other types of functionality may have restrictions
|
||
or may only make sense in the context of a plugin that is stopping.
|
||
|
||
For example, the `stop` function in the browser gets invoked as part of
|
||
the `window.onbeforeunload` event, which means you can’t necessarily
|
||
execute asynchronous code here reliably. For that reason,
|
||
`core` likely wouldn’t provide any asynchronous functions to plugin
|
||
`stop` functions in the browser.
|
||
|
||
The current lifecycle function for all plugins will be executed before the next
|
||
lifecycle starts. That is to say that all `setup` functions are executed before
|
||
any `start` functions are executed.
|
||
|
||
These are the contracts exposed by the core services for each lifecycle:
|
||
|
||
[cols=",,",options="header",]
|
||
|===
|
||
|lifecycle |server contract|browser contract
|
||
|_constructor_
|
||
|{kib-repo}blob/{branch}/src/core/packages/plugins/server/src/types.ts[PluginInitializerContext]
|
||
|{kib-repo}blob/{branch}/src/core/packages/plugins/browser/src/plugin_initializer.ts[PluginInitializerContext]
|
||
|
||
|_setup_
|
||
|{kib-repo}blob/{branch}/src/core/packages/lifecycle/server/src/core_setup.ts[CoreSetup]
|
||
|{kib-repo}blob/{branch}/src/core/packages/lifecycle/browser-internal/src/internal_core_setup.ts[CoreSetup]
|
||
|
||
|_start_
|
||
|{kib-repo}blob/{branch}/src/core/packages/lifecycle/server/src/core_start.ts[CoreStart]
|
||
|{kib-repo}blob/{branch}/src/core/packages/lifecycle/browser/src/core_start.ts[CoreStart]
|
||
|
||
|_stop_ |
|
||
|===
|
||
|
||
=== Integrating with other plugins
|
||
|
||
Plugins can expose public interfaces for other plugins to consume. Like
|
||
`core`, those interfaces are bound to the lifecycle functions `setup`
|
||
and/or `start`.
|
||
|
||
Anything returned from `setup` or `start` will act as the interface, and
|
||
while not a technical requirement, all first-party Elastic plugins
|
||
will expose types for that interface as well. Third party plugins
|
||
wishing to allow other plugins to integrate with it are also highly
|
||
encouraged to expose types for their plugin interfaces.
|
||
|
||
*foobar plugin.ts:*
|
||
|
||
[source, typescript]
|
||
----
|
||
import type { Plugin } from '@kbn/core/server';
|
||
export interface FoobarPluginSetup { <1>
|
||
getFoo(): string;
|
||
}
|
||
|
||
export interface FoobarPluginStart { <1>
|
||
getBar(): string;
|
||
}
|
||
|
||
export class MyPlugin implements Plugin<FoobarPluginSetup, FoobarPluginStart> {
|
||
public setup(): FoobarPluginSetup {
|
||
return {
|
||
getFoo() {
|
||
return 'foo';
|
||
},
|
||
};
|
||
}
|
||
|
||
public start(): FoobarPluginStart {
|
||
return {
|
||
getBar() {
|
||
return 'bar';
|
||
},
|
||
};
|
||
}
|
||
}
|
||
----
|
||
<1> We highly encourage plugin authors to explicitly declare public interfaces for their plugins.
|
||
|
||
Unlike core, capabilities exposed by plugins are _not_ automatically
|
||
injected into all plugins. Instead, if a plugin wishes to use the public
|
||
interface provided by another plugin, it must first declare that
|
||
plugin as a dependency in it's {kib-repo}blob/{branch}/src/core/packages/plugins/server/src/types.ts[`kibana.json`] manifest file.
|
||
|
||
*demo kibana.json:*
|
||
|
||
[source,json]
|
||
----
|
||
{
|
||
"id": "demo",
|
||
"requiredPlugins": ["foobar"],
|
||
"server": true,
|
||
"ui": true
|
||
}
|
||
----
|
||
|
||
With that specified in the plugin manifest, the appropriate interfaces
|
||
are then available via the second argument of `setup` and/or `start`:
|
||
|
||
*demo plugin.ts:*
|
||
|
||
[source,typescript]
|
||
----
|
||
import type { CoreSetup, CoreStart } from '@kbn/core/server';
|
||
import type { FoobarPluginSetup, FoobarPluginStart } from '../../foobar/server';
|
||
|
||
interface DemoSetupPlugins { <1>
|
||
foobar: FoobarPluginSetup;
|
||
}
|
||
|
||
interface DemoStartPlugins {
|
||
foobar: FoobarPluginStart;
|
||
}
|
||
|
||
export class AnotherPlugin {
|
||
public setup(core: CoreSetup, plugins: DemoSetupPlugins) { <2>
|
||
const { foobar } = plugins;
|
||
foobar.getFoo(); // 'foo'
|
||
foobar.getBar(); // throws because getBar does not exist
|
||
}
|
||
|
||
public start(core: CoreStart, plugins: DemoStartPlugins) { <3>
|
||
const { foobar } = plugins;
|
||
foobar.getFoo(); // throws because getFoo does not exist
|
||
foobar.getBar(); // 'bar'
|
||
}
|
||
|
||
public stop() {}
|
||
}
|
||
----
|
||
<1> The interface for plugin's dependencies must be manually composed. You can
|
||
do this by importing the appropriate type from the plugin and constructing an
|
||
interface where the property name is the plugin's ID.
|
||
<2> These manually constructed types should then be used to specify the type of
|
||
the second argument to the plugin.
|
||
<3> Notice that the type for the setup and start lifecycles are different. Plugin lifecycle
|
||
functions can only access the APIs that are exposed _during_ that lifecycle.
|