Skip to content

[Core] Expose isFeatureAvailable method from pricing API server setup#223525

Merged
tonyghiani merged 9 commits intoelastic:mainfrom
tonyghiani:core/expose-pricing-methods
Jul 1, 2025
Merged

[Core] Expose isFeatureAvailable method from pricing API server setup#223525
tonyghiani merged 9 commits intoelastic:mainfrom
tonyghiani:core/expose-pricing-methods

Conversation

@tonyghiani
Copy link
Copy Markdown
Contributor

@tonyghiani tonyghiani commented Jun 12, 2025

📓 Summary

This work exposes an asynchronous coreSetup.pricing.isFeatureAvailable() method to assert whether Kibana is running on a given pricing product during a plugin server setup lifecycle step.

Why do we need it?

Some feature registrations are synchronous in the plugin setup, and until all the plugins have registered their features, knowing features availability at the server setup step is not possible.

How does this fix it?

To guarantee we have access to all the registered features during the setup lifecycle, the process works so that:

  1. All the plugins are set up and the product features are registered synchronously.
  2. Once all the plugins are set, the core pricing service emits a signal.
  3. The isFeatureAvailable method on setup, if invoked previously, resolves asynchronously, reacting to the emitted signal.

This guarantees access to the product feature model anywhere in Kibana, without having to rely on the raw tier configuration values.

public setup(core: CoreSetup) {
    core.pricing.registerProductFeatures([
      {
        id: 'my-plugin:feature1',
        description: 'A feature for observability products',
        products: [
          { name: 'observability', tier: 'complete' },
        ],
      }
    ]);

    core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete) => {
      if (isActiveObservabilityComplete) {
        // Enable feature1
      }
    });
  }

@tonyghiani tonyghiani added Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// release_note:skip Skip the PR/issue when compiling release notes backport:version Backport to applied version labels v9.1.0 v8.19.0 labels Jun 12, 2025
@tonyghiani tonyghiani changed the title [Core] Expose isActiveProduct method from pricing API server setup [Core] Expose isFeatureAvailable method from pricing API server setup Jun 30, 2025
@tonyghiani tonyghiani marked this pull request as ready for review June 30, 2025 07:42
@tonyghiani tonyghiani requested a review from a team as a code owner June 30, 2025 07:42
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/kibana-core (Team:Core)


const isActiveObservabilityComplete = await setup.isFeatureAvailable('feature1');
expect(isActiveObservabilityComplete).toBe(true);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally this test should call isFeatureAvailable before the feature is registered (and before evaluteProductFeatures) is called to fully exercise the async blocking behavior

it('should block isFeatureAvailable until evaluateProductFeatures is called', async () => {
  const service = new PricingService(coreContext);
  const { isFeatureAvailable, evaluateProductFeatures, registerProductFeatures } = await service.preboot({ http: prebootHttp });

  // Start calling isFeatureAvailable, before said feature was registered or evaluateProductFeatures is called
  let resolved = false;
  const promise = isFeatureAvailable('testFeature').then(() => {
    resolved = true;
  });
  
  // Now register the feature
  registerProductFeatures([
    {
      id: 'testFeature',
      description: 'Test Feature',
      products: [{ name: 'observability', tier: 'complete' }],
    },
  ]);

  // Wait a short bit to ensure it doesn't resolve prematurely
  await new Promise((r) => setTimeout(r, 100));
  expect(resolved).toBe(false);

  // Now "unlock" the gate
  evaluateProductFeatures();

  // Now it should resolve
  await promise;
  expect(resolved).toBe(true);
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are absolutely right, good catch!
Addressed with test(pricing): udpate test for setup isfeatureAvailable

@tonyghiani tonyghiani requested a review from rudolf June 30, 2025 12:12
@tonyghiani tonyghiani merged commit 44c11da into elastic:main Jul 1, 2025
10 checks passed
@tonyghiani tonyghiani deleted the core/expose-pricing-methods branch July 1, 2025 09:40
@kibanamachine
Copy link
Copy Markdown
Contributor

Starting backport for target branches: 8.19, 9.1

https://github.com/elastic/kibana/actions/runs/15995692033

@elasticmachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/core-pricing-server 2 3 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
core 471.8KB 471.8KB +51.0B
Unknown metric groups

API count

id before after diff
@kbn/core-pricing-common 23 25 +2
@kbn/core-pricing-server 6 8 +2
total +4

History

@kibanamachine
Copy link
Copy Markdown
Contributor

Starting backport for target branches: 8.19, 9.1

https://github.com/elastic/kibana/actions/runs/15995700196

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jul 1, 2025
…elastic#223525)

## 📓 Summary

This work exposes an asynchronous
`coreSetup.pricing.isFeatureAvailable()` method to assert whether Kibana
is running on a given pricing product during a plugin server setup
lifecycle step.

##  Why do we need it?

Some feature registrations are synchronous in the plugin setup, and
until all the plugins have registered their features, knowing features
availability at the server setup step is not possible.

## How does this fix it?

To guarantee we have access to all the registered features during the
setup lifecycle, the process works so that:
1. All the plugins are set up and the product features are registered
synchronously.
2. Once all the plugins are set, the core pricing service emits a
signal.
3. The `isFeatureAvailable` method on setup, if invoked previously,
resolves asynchronously, reacting to the emitted signal.

This guarantees access to the product feature model anywhere in Kibana,
without having to rely on the raw tier configuration values.

```ts
public setup(core: CoreSetup) {
    core.pricing.registerProductFeatures([
      {
        id: 'my-plugin:feature1',
        description: 'A feature for observability products',
        products: [
          { name: 'observability', tier: 'complete' },
        ],
      }
    ]);

    core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete) => {
      if (isActiveObservabilityComplete) {
        // Enable feature1
      }
    });
  }
```

(cherry picked from commit 44c11da)
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jul 1, 2025
…elastic#223525)

## 📓 Summary

This work exposes an asynchronous
`coreSetup.pricing.isFeatureAvailable()` method to assert whether Kibana
is running on a given pricing product during a plugin server setup
lifecycle step.

##  Why do we need it?

Some feature registrations are synchronous in the plugin setup, and
until all the plugins have registered their features, knowing features
availability at the server setup step is not possible.

## How does this fix it?

To guarantee we have access to all the registered features during the
setup lifecycle, the process works so that:
1. All the plugins are set up and the product features are registered
synchronously.
2. Once all the plugins are set, the core pricing service emits a
signal.
3. The `isFeatureAvailable` method on setup, if invoked previously,
resolves asynchronously, reacting to the emitted signal.

This guarantees access to the product feature model anywhere in Kibana,
without having to rely on the raw tier configuration values.

```ts
public setup(core: CoreSetup) {
    core.pricing.registerProductFeatures([
      {
        id: 'my-plugin:feature1',
        description: 'A feature for observability products',
        products: [
          { name: 'observability', tier: 'complete' },
        ],
      }
    ]);

    core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete) => {
      if (isActiveObservabilityComplete) {
        // Enable feature1
      }
    });
  }
```

(cherry picked from commit 44c11da)
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jul 1, 2025
…elastic#223525)

## 📓 Summary

This work exposes an asynchronous
`coreSetup.pricing.isFeatureAvailable()` method to assert whether Kibana
is running on a given pricing product during a plugin server setup
lifecycle step.

##  Why do we need it?

Some feature registrations are synchronous in the plugin setup, and
until all the plugins have registered their features, knowing features
availability at the server setup step is not possible.

## How does this fix it?

To guarantee we have access to all the registered features during the
setup lifecycle, the process works so that:
1. All the plugins are set up and the product features are registered
synchronously.
2. Once all the plugins are set, the core pricing service emits a
signal.
3. The `isFeatureAvailable` method on setup, if invoked previously,
resolves asynchronously, reacting to the emitted signal.

This guarantees access to the product feature model anywhere in Kibana,
without having to rely on the raw tier configuration values.

```ts
public setup(core: CoreSetup) {
    core.pricing.registerProductFeatures([
      {
        id: 'my-plugin:feature1',
        description: 'A feature for observability products',
        products: [
          { name: 'observability', tier: 'complete' },
        ],
      }
    ]);

    core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete) => {
      if (isActiveObservabilityComplete) {
        // Enable feature1
      }
    });
  }
```

(cherry picked from commit 44c11da)
@kibanamachine
Copy link
Copy Markdown
Contributor

💚 All backports created successfully

Status Branch Result
8.19
9.1

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jul 1, 2025
…elastic#223525)

## 📓 Summary

This work exposes an asynchronous
`coreSetup.pricing.isFeatureAvailable()` method to assert whether Kibana
is running on a given pricing product during a plugin server setup
lifecycle step.

##  Why do we need it?

Some feature registrations are synchronous in the plugin setup, and
until all the plugins have registered their features, knowing features
availability at the server setup step is not possible.

## How does this fix it?

To guarantee we have access to all the registered features during the
setup lifecycle, the process works so that:
1. All the plugins are set up and the product features are registered
synchronously.
2. Once all the plugins are set, the core pricing service emits a
signal.
3. The `isFeatureAvailable` method on setup, if invoked previously,
resolves asynchronously, reacting to the emitted signal.

This guarantees access to the product feature model anywhere in Kibana,
without having to rely on the raw tier configuration values.

```ts
public setup(core: CoreSetup) {
    core.pricing.registerProductFeatures([
      {
        id: 'my-plugin:feature1',
        description: 'A feature for observability products',
        products: [
          { name: 'observability', tier: 'complete' },
        ],
      }
    ]);

    core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete) => {
      if (isActiveObservabilityComplete) {
        // Enable feature1
      }
    });
  }
```

(cherry picked from commit 44c11da)
@kibanamachine
Copy link
Copy Markdown
Contributor

💚 All backports created successfully

Status Branch Result
8.19
9.1

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Jul 1, 2025
… setup (#223525) (#225967)

# Backport

This will backport the following commits from `main` to `9.1`:
- [[Core] Expose isFeatureAvailable method from pricing API server setup
(#223525)](#223525)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Marco Antonio
Ghiani","email":"marcoantonio.ghiani01@gmail.com"},"sourceCommit":{"committedDate":"2025-07-01T09:40:40Z","message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n
}\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:version","v9.1.0","v8.19.0","v9.2.0"],"title":"[Core]
Expose isFeatureAvailable method from pricing API server
setup","number":223525,"url":"https://github.com/elastic/kibana/pull/223525","mergeCommit":{"message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n
}\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143"}},"sourceBranch":"main","suggestedTargetBranches":["9.1","8.19"],"targetPullRequestStates":[{"branch":"9.1","label":"v9.1.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/223525","number":223525,"mergeCommit":{"message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n }\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143"}}]}]
BACKPORT-->

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani01@gmail.com>
kibanamachine added a commit that referenced this pull request Jul 1, 2025
…r setup (#223525) (#225966)

# Backport

This will backport the following commits from `main` to `8.19`:
- [[Core] Expose isFeatureAvailable method from pricing API server setup
(#223525)](#223525)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Marco Antonio
Ghiani","email":"marcoantonio.ghiani01@gmail.com"},"sourceCommit":{"committedDate":"2025-07-01T09:40:40Z","message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n
}\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:version","v9.1.0","v8.19.0","v9.2.0"],"title":"[Core]
Expose isFeatureAvailable method from pricing API server
setup","number":223525,"url":"https://github.com/elastic/kibana/pull/223525","mergeCommit":{"message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n
}\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143"}},"sourceBranch":"main","suggestedTargetBranches":["9.1","8.19"],"targetPullRequestStates":[{"branch":"9.1","label":"v9.1.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/223525","number":223525,"mergeCommit":{"message":"[Core]
Expose isFeatureAvailable method from pricing API server setup
(#223525)\n\n## 📓 Summary\n\nThis work exposes an
asynchronous\n`coreSetup.pricing.isFeatureAvailable()` method to assert
whether Kibana\nis running on a given pricing product during a plugin
server setup\nlifecycle step.\n\n## Why do we need it?\n\nSome feature
registrations are synchronous in the plugin setup, and\nuntil all the
plugins have registered their features, knowing features\navailability
at the server setup step is not possible.\n\n## How does this fix
it?\n\nTo guarantee we have access to all the registered features during
the\nsetup lifecycle, the process works so that:\n1. All the plugins are
set up and the product features are registered\nsynchronously.\n2. Once
all the plugins are set, the core pricing service emits a\nsignal.\n3.
The `isFeatureAvailable` method on setup, if invoked
previously,\nresolves asynchronously, reacting to the emitted
signal.\n\nThis guarantees access to the product feature model anywhere
in Kibana,\nwithout having to rely on the raw tier configuration
values.\n\n```ts\npublic setup(core: CoreSetup) {\n
core.pricing.registerProductFeatures([\n {\n id: 'my-plugin:feature1',\n
description: 'A feature for observability products',\n products: [\n {
name: 'observability', tier: 'complete' },\n ],\n }\n ]);\n\n
core.pricing.isFeatureAvailable('my-plugin:feature1').then((isActiveObservabilityComplete)
=> {\n if (isActiveObservabilityComplete) {\n // Enable feature1\n }\n
});\n }\n```","sha":"44c11da5a82d1c73e99fe46f2e409889af1bd143"}}]}]
BACKPORT-->

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani01@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels release_note:skip Skip the PR/issue when compiling release notes Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// v8.19.0 v9.1.0 v9.2.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants