Skip to content

[Synthetics] Honor searchExcludedDataTiers advanced setting in SyntheticsEsClient#273418

Merged
mgiota merged 7 commits into
elastic:mainfrom
shahzad31:synthetics-search-excluded-data-tiers
Jun 18, 2026
Merged

[Synthetics] Honor searchExcludedDataTiers advanced setting in SyntheticsEsClient#273418
mgiota merged 7 commits into
elastic:mainfrom
shahzad31:synthetics-search-excluded-data-tiers

Conversation

@shahzad31

@shahzad31 shahzad31 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses #273086 (fix #1 — the single choke point).

Synthetics issued every Elasticsearch query against the broad synthetics-* wildcard with only ignore_unavailable: true — no data-tier filter. As a result, queries fanned out to all backing indices across hot/warm/frozen tiers. On clusters with long frozen retention (e.g. hot: 3d / warm: 4d / frozen: 365d) this caused high latency (slow screenshots and history) and contributed to cluster-wide search thread pool rejections, because frozen searchable-snapshot shards are slow and deliberately throttled.

This PR makes SyntheticsEsClient honor the existing observability:searchExcludedDataTiers advanced setting — the same mechanism already used by APM and Infrastructure. When configured, a must_not { terms: { _tier: [...] } } filter is injected into every search / msearch / count, so excluded tiers (e.g. data_frozen) are skipped.

What changed

  • SyntheticsEsClient reads observability:searchExcludedDataTiers (cached per instance) and wraps each query via a new exported applyExcludedDataTiersToQuery helper, reusing the shared excludeTiersQuery util from @kbn/observability-utils-common.
  • The client now also accepts a plain IUiSettingsClient (uiSettingsClient option) in addition to the route-handler uiSettings context, so alerting rule executors can resolve the setting.
  • Wired the status and TLS rule executors (and the inspect-TLS route) to pass their uiSettingsClient, so alerting queries are covered too.
  • Updated the advanced-setting description to list Synthetics among the affected apps.

Behavior / risk

  • The setting defaults to [], so behavior is unchanged unless an operator opts in — no functional change for existing deployments.
  • All Synthetics UI queries flow through SyntheticsEsClient via the route wrapper (which already passes uiSettings), so screenshots, history, latest-ping, and overview queries are all covered with no call-site changes.

Follow-ups (tracked in #273086, not in this PR)

  • Add @timestamp lower bounds to the time-less queries (screenshots/steps/network events, latest-ping hooks, get_last_successful_check).
  • Drop the residual 30-day default in fetchMonitorRecentPings.

Testing

  • node scripts/jest x-pack/solutions/observability/plugins/synthetics/server/lib.test.ts — added unit tests for search/msearch/count exclusion and the applyExcludedDataTiersToQuery helper.
  • Status + TLS rule executor jest suites pass unchanged.
  • Manual: set Stack Management → Advanced Settings → Excluded data tiers from search to data_frozen and confirm Synthetics search requests include the must_not _tier filter (visible via the inspector / observability:enableInspectEsQueries).

Checklist

  • Unit tests updated
  • Type-check passes for the synthetics project
  • ESLint + i18n checks pass

Release note

Synthetics now respects the observability:searchExcludedDataTiers advanced setting, allowing operators to exclude slow data tiers (such as data_frozen) from Synthetics searches to reduce latency and search thread pool pressure.

Synthetics searched the full `synthetics-*` wildcard with no data-tier
filter, so queries fanned out to every backing index across hot/warm/
frozen tiers. On clusters with long frozen retention this drove high
latency (slow screenshots/history) and search thread pool rejections.

`SyntheticsEsClient` now reads the `observability:searchExcludedDataTiers`
advanced setting (already honored by APM and Infrastructure) and injects a
`must_not _tier` filter into every search/msearch/count. The setting
defaults to `[]`, so behavior is unchanged unless an operator opts in.
Alerting rule executors (status, TLS) now pass their `uiSettingsClient`
through so their queries are covered too.

Addresses elastic#273086

Co-authored-by: Cursor <cursoragent@cursor.com>
@shahzad31 shahzad31 added release_note:enhancement Synthetics Team:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. labels Jun 15, 2026
@github-actions github-actions Bot added the author:actionable-obs PRs authored by the actionable obs team label Jun 15, 2026
@shahzad31 shahzad31 marked this pull request as ready for review June 16, 2026 07:27
@shahzad31 shahzad31 requested review from a team as code owners June 16, 2026 07:27
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/actionable-obs-team (Team:actionable-obs)

@mgiota mgiota self-requested a review June 16, 2026 08:19

@mgiota mgiota left a comment

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.

LGTM! Nicely scoped fix — follows the existing APM/Infra pattern for searchExcludedDataTiers, defaults to no behavior change ([]), and centralizing it in SyntheticsEsClient means every UI route and the wired-up rule executors are covered without touching call sites. Tests cover the new search/msearch/count paths plus the helper.

Thanks for tracking the @timestamp lower bounds and the fetchMonitorRecentPings default as follow-ups in #273086.

});
});

describe('excluded data tiers', () => {

@mgiota mgiota Jun 16, 2026

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.

nit: search has both the tiers configured and no tiers excluded cases in the new describe('excluded data tiers') block, but msearch and count only cover the "configured" path.

The pre-existing tests for those methods do exercise the unmodified-request path, but only via the uiSettingsClient short-circuit in getExcludedDataTiers() (no client provided).

What's not covered for msearch/count is the case where the client is provided and returns [] — i.e. the falsy branch of the if (excludedDataTiers.length) guard inside each method. Worth two small symmetric tests for completeness. Pure nit, non-blocking.

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.

it('does not modify msearch requests when no tiers are excluded', async () => {
  esClient.msearch.mockResolvedValueOnce({
    body: { responses: [{}] },
  } as unknown as MsearchResponse);
  const { client, uiSettings } = createClientWithExcludedTiers([]);

  await client.msearch([{ query: matchAll }]);

  expect(uiSettings.get).toHaveBeenCalledWith('observability:searchExcludedDataTiers');
  expect(esClient.msearch).toHaveBeenCalledWith(
    {
      searches: [
        { index: 'synthetics-*', ignore_unavailable: true },
        { query: matchAll },
      ],
    },
    { meta: true }
  );
});

it('does not modify the count query when no tiers are excluded', async () => {
  const { client, uiSettings } = createClientWithExcludedTiers([]);

  await client.count({ query: matchAll });

  expect(uiSettings.get).toHaveBeenCalledWith('observability:searchExcludedDataTiers');
  expect(esClient.count).toHaveBeenCalledWith(
    { index: 'synthetics-*', ignore_unavailable: true, query: matchAll },
    { meta: true, context: { loggingOptions: { loggerName: 'synthetics' } } }
  );
});

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.

Good call — added the two symmetric tests (msearch + count with the client provided but the setting returning [], so the falsy branch of the excludedDataTiers.length guard is covered) in 198f655.

@shahzad31 shahzad31 added the backport:all-open Backport to all branches that could still receive a release label Jun 16, 2026
Cover the falsy branch of the excluded-tiers guard for msearch and count
(client provided, setting returns []), addressing review feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>
shahzad31 and others added 4 commits June 16, 2026 19:51
Client-side queries issued via the data plugin's search service
(useEsSearch / useReduxEsSearch -> /internal/search) bypassed
SyntheticsEsClient and therefore the observability:searchExcludedDataTiers
exclusion added server-side.

Mirror that behavior on the browser: a new applyExcludedDataTiersToParams
helper injects the must_not _tier filter, applied once in the redux
executeEsQueryAPI thunk (covers useReduxEsSearch) and via a new
useSyntheticsEsSearch wrapper (replaces direct useEsSearch usages). The
setting defaults to [], so behavior is unchanged unless an operator opts in.

Co-authored-by: Cursor <cursoragent@cursor.com>
The client bundle cannot import the deep subpath
@kbn/observability-plugin/common/ui_settings_keys. Re-export
searchExcludedDataTiers from @kbn/observability-plugin/common (matching
enableInspectEsQueries) and import the key from the package index in both
the client helper and the server client.

Co-authored-by: Cursor <cursoragent@cursor.com>
These overview CCS index-pattern changes were accidentally swept into the
previous commit via `git add -A` and are unrelated to searchExcludedDataTiers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kibanamachine

Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
synthetics 1352 1355 +3

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
synthetics 1.3MB 1.3MB +487.0B

Page load bundle

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

id before after diff
observability 102.6KB 102.7KB +84.0B

History

@mgiota mgiota merged commit 3ea738e into elastic:main Jun 18, 2026
31 checks passed
@kibanamachine

Copy link
Copy Markdown
Contributor

Starting backport for target branches: 8.19, 9.3, 9.4

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

@kibanamachine

Copy link
Copy Markdown
Contributor

💔 All backports failed

Status Branch Result
8.19 Backport failed because of merge conflicts
9.3 Backport failed because of merge conflicts
9.4 Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 273418

Questions ?

Please refer to the Backport tool documentation

mbondyra added a commit to mbondyra/kibana that referenced this pull request Jun 19, 2026
…g_generation

* commit '408590635258efac66c7e71983ea92560ea41ac9': (199 commits)
  [Cases] Legacy templates migration PR 1/2 - SO changes (elastic#270179)
  [Failed Test Investigator] Skip reference links, exit early on deleted tests (elastic#273970)
  Remove sample data hooks from Scout release tests (elastic#273768)
  [Alerting v2] Remove rule form schema translation layer and delete dead GUI form code (elastic#273991)
  feat(stack-monitoring): replace title props and wrap EuiButtonIcon with EuiToolTip (elastic#271512)
  [Scout][FTR migration] Prefer default Cloud-compatible roles over custom roles (elastic#273744)
  [One Workflow] Unskip flaky jest tests (elastic#271143)
  extend codeql dos exclusions (elastic#274085)
  [Cases] Global fields in field library (elastic#269962)
  [UII] Optimize enrollment key and revision reconciliation during Fleet setup (elastic#272604)
  [Scout] Update test config manifests (elastic#274092)
  [Alerting v2] Create an advanced setting to toggle the alerting v2 feature (elastic#272365)
  Splitting tests on findings onboarding (elastic#270638)
  [Synthetics] [CCS] Add "View on remote cluster" callout to monitor details page (elastic#273629)
  [Synthetics] [CCS] Disable header actions on details page for remote monitors (elastic#273602)
  Update dependency diff to v9 (main) (elastic#265874)
  [Synthetics] Honor searchExcludedDataTiers advanced setting in SyntheticsEsClient (elastic#273418)
  Update docker.elastic.co/wolfi/chainguard-base-fips:latest Docker digest to 278de96 (main) (elastic#274027)
  Fix keyboard access for scrollable command output panel in Response Console (elastic#272707)
  Update docker.elastic.co/wolfi/chainguard-base:latest Docker digest to ce1e3ed (main) (elastic#274028)
  ...
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jun 19, 2026
@kibanamachine

Copy link
Copy Markdown
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add a backport:* label or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 273418 locally
cc: @shahzad31

@kibanamachine

Copy link
Copy Markdown
Contributor

Friendly reminder: Looks like this PR hasn’t been backported yet.
To create automatically backports add a backport:* label or prevent reminders by adding the backport:skip label.
You can also create backports manually by running node scripts/backport --pr 273418 locally
cc: @shahzad31

flash1293 pushed a commit to flash1293/kibana that referenced this pull request Jun 23, 2026
…ticsEsClient (elastic#273418)

## Summary

Addresses elastic#273086 (fix #1 — the single choke point).

Synthetics issued every Elasticsearch query against the broad
`synthetics-*` wildcard with only `ignore_unavailable: true` — no
data-tier filter. As a result, queries fanned out to **all** backing
indices across hot/warm/**frozen** tiers. On clusters with long frozen
retention (e.g. `hot: 3d / warm: 4d / frozen: 365d`) this caused high
latency (slow screenshots and history) and contributed to cluster-wide
**search thread pool rejections**, because frozen searchable-snapshot
shards are slow and deliberately throttled.

This PR makes `SyntheticsEsClient` honor the existing
`observability:searchExcludedDataTiers` advanced setting — the same
mechanism already used by **APM** and **Infrastructure**. When
configured, a `must_not { terms: { _tier: [...] } }` filter is injected
into every `search` / `msearch` / `count`, so excluded tiers (e.g.
`data_frozen`) are skipped.

### What changed

- `SyntheticsEsClient` reads `observability:searchExcludedDataTiers`
(cached per instance) and wraps each query via a new exported
`applyExcludedDataTiersToQuery` helper, reusing the shared
`excludeTiersQuery` util from `@kbn/observability-utils-common`.
- The client now also accepts a plain `IUiSettingsClient`
(`uiSettingsClient` option) in addition to the route-handler
`uiSettings` context, so alerting rule executors can resolve the
setting.
- Wired the **status** and **TLS** rule executors (and the inspect-TLS
route) to pass their `uiSettingsClient`, so alerting queries are covered
too.
- Updated the advanced-setting description to list Synthetics among the
affected apps.

### Behavior / risk

- The setting defaults to `[]`, so **behavior is unchanged unless an
operator opts in** — no functional change for existing deployments.
- All Synthetics UI queries flow through `SyntheticsEsClient` via the
route wrapper (which already passes `uiSettings`), so screenshots,
history, latest-ping, and overview queries are all covered with no
call-site changes.

### Follow-ups (tracked in elastic#273086, not in this PR)

- Add `@timestamp` lower bounds to the time-less queries
(screenshots/steps/network events, latest-ping hooks,
`get_last_successful_check`).
- Drop the residual 30-day default in `fetchMonitorRecentPings`.

## Testing

- `node scripts/jest
x-pack/solutions/observability/plugins/synthetics/server/lib.test.ts` —
added unit tests for `search`/`msearch`/`count` exclusion and the
`applyExcludedDataTiersToQuery` helper.
- Status + TLS rule executor jest suites pass unchanged.
- Manual: set **Stack Management → Advanced Settings → Excluded data
tiers from search** to `data_frozen` and confirm Synthetics search
requests include the `must_not _tier` filter (visible via the inspector
/ `observability:enableInspectEsQueries`).

### Checklist

- [x] Unit tests updated
- [x] Type-check passes for the synthetics project
- [x] ESLint + i18n checks pass

### Release note

Synthetics now respects the `observability:searchExcludedDataTiers`
advanced setting, allowing operators to exclude slow data tiers (such as
`data_frozen`) from Synthetics searches to reduce latency and search
thread pool pressure.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
@shahzad31 shahzad31 deleted the synthetics-search-excluded-data-tiers branch June 23, 2026 21:28
@kibanamachine

Copy link
Copy Markdown
Contributor

Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync.
cc: @shahzad31

1 similar comment
@kibanamachine

Copy link
Copy Markdown
Contributor

Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync.
cc: @shahzad31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author:actionable-obs PRs authored by the actionable obs team backport:all-open Backport to all branches that could still receive a release backport missing Added to PRs automatically when the are determined to be missing a backport. release_note:enhancement Synthetics Team:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

links to styles and js

3 participants