Skip to content

[Alerting v2] Compose Discover: Rule authoring flyout with Discover Sandbox (planning draft)#267982

Draft
jasonrhodes wants to merge 8 commits into
elastic:mainfrom
jasonrhodes:rna/compose-discover-flyout
Draft

[Alerting v2] Compose Discover: Rule authoring flyout with Discover Sandbox (planning draft)#267982
jasonrhodes wants to merge 8 commits into
elastic:mainfrom
jasonrhodes:rna/compose-discover-flyout

Conversation

@jasonrhodes
Copy link
Copy Markdown
Member

@jasonrhodes jasonrhodes commented May 6, 2026

FOR PLANNING ONLY, DO NOT MERGE

This draft PR shows a working prototype of the v2 rule authoring experience. It is intended to drive planning conversations and team review, not for production merge.

What this shows

A two-panel in-context rule authoring experience:

  • Left — Discover Sandbox: Real ES|QL editor (CodeEditor + Lens histogram + EuiDataGrid) rendered as an EUI child flyout (size="fill") alongside the Edit Form.
  • Right — Edit Form: A stepped flyout (session="start") with a custom minimal stepper. Steps: Alert Condition → Details & Artifacts → Notifications (Recovery Condition added in PR E).
  • The prototype also shows the full tracking + split + recovery flow that will ship later.

PR breakdown

PR Scope Status Depends on
#268739 — PR A HorizontalMinimalStepper component + storybook Open (draft)
PR B (#268774) Stepped Edit Form (3 steps), RHF form migration, field groups, API wiring — single editor, no tracking/split In progress PR A
PR C Discover Sandbox redesign — search row, keyboard shortcuts, single editor UX polish Pending PR B
PR D YAML editing mode with round-trip sync Pending PR B
PR E Custom recovery + tracking split — adds Recovery Condition step, tracking toggle, heuristic split, Sandbox tab bar Pending PR C
PR F Split-query ES|QL autocomplete for alert/recovery block editors Pending PR E

PR C and PR D are independent and can be worked in parallel after PR B lands. PR E and PR F are the second wave.

Known gaps (pre-merge requirements across all PRs)

  • RHF migration — form values (PR B)
  • Discover Sandbox redesign — search row, keyboard shortcuts (PR C)
  • YAML round-trip (PR D)
  • Tracking mode + Recovery Condition + Sandbox tab bar (PR E)
  • Split-query autocomplete (PR F)
  • E2E / Scout tests
  • Feature flag gating

How to run this locally

1. Start Elasticsearch

node scripts/es snapshot --license=trial --kibanaUrl http://localhost:5603/ifh

2. Start Kibana (Node 24 required)

export NVM_DIR="$HOME/.nvm" && source "$NVM_DIR/nvm.sh" && nvm use 24
KBN_USE_RSPACK=true yarn start \
  --server.port=5603 \
  --server.basePath=/ifh \
  --server.rewriteBasePath=true

config/kibana.dev.yml must contain:

xpack.alerting_v2.enabled: true
dev.basePathProxyTarget: 5604
mockIdpPlugin.enabled: false

3. Load test data

python3 - <<'EOF'
import json, random, urllib.request
from datetime import datetime, timedelta, timezone
from base64 import b64encode

ES = "http://localhost:9200"
AUTH = b64encode(b"elastic:changeme").decode()
H = {"Content-Type":"application/x-ndjson","Authorization":f"Basic {AUTH}"}
hosts = ["prod-web-01","prod-web-02","prod-app-01","prod-app-02","prod-db-01","prod-db-02","prod-worker-01"]
now = datetime.now(timezone.utc)
lines = []
for i in range(2000):
    ts = now - timedelta(hours=random.uniform(0, 6))
    host = random.choice(hosts)
    base_cpu = 0.85 if host in ("prod-db-01","prod-web-02") else random.uniform(0.3, 0.75)
    doc = {"@timestamp":ts.strftime("%Y-%m-%dT%H:%M:%S.000Z"),"host.name":host,"cpu":round(base_cpu+random.uniform(-0.05,0.1),2),"memory":round(random.uniform(0.4,0.9),2)}
    lines.append(json.dumps({"index":{"_index":"logs-infra-hosts"}}))
    lines.append(json.dumps(doc))
body = ("\n".join(lines)+"\n").encode()
r = urllib.request.Request(f"{ES}/_bulk",data=body,method="POST",headers=H)
with urllib.request.urlopen(r) as resp:
    result = json.loads(resp.read())
print(f"Seeded logs-infra-hosts: errors={result.get('errors')}")
EOF

4. Navigate

http://localhost:5603/ifh/app/management/alertingV2/rules

Click Create rule.

Sample rule

FROM logs-infra-hosts
| STATS avg_cpu = AVG(cpu) BY host.name
| WHERE avg_cpu > 0.8

Related

jasonrhodes and others added 3 commits May 6, 2026 09:56
Types (ComposeDiscoverState, action union, enums), useReducer-based
state management, ES|QL query execution with explicit run + ref-based
params, heuristic pipe-segment query split, and Monaco autocomplete
provider registration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two-layer flyout: compact main form (name, tags, query summaries,
tracking toggle, evaluation fields) and editor child flyout (ES|QL
CodeEditor, Lens histogram, EuiDataGrid with column selection).
Includes Base/Alert/Recovery tab editor for tracking mode with locked
base query + continuation line numbers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lazy-load and export ComposeDiscoverFlyout from the alerting-v2-rule-form
package. Replace the route-based "Create Rule" button with a flyout
trigger on the rules list page, injecting required services (data,
dataViews, lens, http, notifications, application).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@infra-vault-gh-plugin-prod
Copy link
Copy Markdown

🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

@github-actions github-actions Bot added the author:actionable-obs PRs authored by the actionable obs team label May 6, 2026
jasonrhodes and others added 5 commits May 8, 2026 14:52
Adds the data model for the stepped Edit Form:
- `step` (0-based), `option` (opt1/opt2 layout), `recoveryType`, `notificationsEnabled`
- `SandboxTabConfig` union type describing which tabs the Discover Sandbox shows
- Exported `getStepTitles()` and `getSandboxTabConfig()` pure helpers
- New actions: GO_NEXT, GO_BACK, SET_STEP, SET_OPTION, SET_RECOVERY_TYPE,
  SET_NOTIFICATIONS_ENABLED, OPEN_CHILD_FOR_STEP
- Reducer cases: step navigation closes the child; SET_RECOVERY_TYPE auto-runs
  guessRecoveryBlock; SET_YAML_MODE auto-opens child; ENABLE_TRACKING clamps step

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
New self-contained stepper component for compact flyout headers, designed
to match Joana's rule authoring design spec:
- Past steps: small filled blue dot (8px)
- Current step: wider blue pill (24×8px)
- Future steps: small grey dot (8px)
- Bold current step title, muted N/N counter, no click handlers
- CSS-only spring animation (cubic-bezier(0.34, 1.56, 0.64, 1)) on step change
- API mirrors EuiStepsHorizontal subset: steps[]{title, status} + animated prop
- Layout alongside other controls via standard EuiFlexGroup (no rightSlot API)

Candidate for future EUI contribution — see artifacts/HORIZONTAL_MINIMAL_STEPPER_NOTES.md.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Refactors the Edit Form flyout from a flat form to a stepped wizard:

Flyout:
- type="overlay" session="start" — dims background, EUI child-flyout layout
- HorizontalMinimalStepper replaces EuiStepsHorizontal
- Icon-only Form/YAML toggle alongside the stepper row
- Step-based Back/Next footer; YAML mode gets its own Cancel/Save footer
- Next button disabled while Discover Sandbox is open

Form steps (Option 1):
- Alert Condition: query summaries, tracking toggle, time field dropdown
  (populated from useDataFields), group fields — all above the tracking toggle
- Recovery Condition: EuiSuperSelect recovery type (Default/No recovery/Custom),
  read-only recovery block + Edit queries button, recovery delay
- Details & Artifacts: name, description, tags, no-data behavior, runbook, dashboard
- Notifications: lite policy, enable toggle, workflow, throttle, escape-hatch callout

Other changes:
- Time field is a smart EuiSelect (date fields only, defaults to @timestamp)
- Time field disabled while Sandbox is open
- "No query defined yet" empty state text
- Recovery block reverted to read-only QuerySummary + Edit queries button

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Layout and UX improvements to the Discover Sandbox child flyout:

Layout:
- size="fill" child flyout fills space left of Edit Form automatically (EUI session system)
- Tab bar at top of body (above search row), matching Joana's design spec
- Search row: [Search] [EuiSuperDatePicker showUpdateButton=false] [Time field 200px fixed]
- Bordered editor panel directly below search row
- Footer: "N documents queried" after execution

Search / execution:
- "Search" replaces "Run"; no separate Refresh button
- ⌘↵/Ctrl+Enter: capture-phase listener + stopPropagation prevents Monaco newline insertion
- Query does NOT auto-execute on keystroke — only on Search click or ⌘↵
- Lens chart uses lastExecutedQuery snapshot (not live activeQuery) to prevent refresh while typing

Tabs:
- Dynamic tab config (SandboxTabConfig): single / base-alert / base-recovery / all-three
- Recovery step: "Recovery query" tab only (locked base as context, not a separate tab)
- Tab labels: "Base query", "Alert query", "Recovery query", "Query" (single mode)
- hideTabBar prop: renders editor-only when tab bar is in the header instead
- Tab defaults: Alert step → Alert query tab; Recovery step → Recovery query tab

Time field:
- useDataFields guard: only fetches when query has a valid index pattern after FROM
  (prevents wildcard explosion when user is mid-edit)
- Fixed 200px width prevents layout shift when long field names are selected

Apply changes button: always "Apply changes" (was context-dependent Done/Next)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds per-editor Monaco completion providers so the alert block and recovery
block editors have column-aware autocomplete based on the base query output.

Technique (from PR elastic#255876 prior art): at suggestion time, prepend baseQuery
to the editor text to form a complete ES|QL string, adjust cursor offset by
baseQuery.length + 1, then call suggest() from @kbn/esql-language. This makes
columns produced by STATS, EVAL, RENAME, etc. available for autocomplete in the
block editors even though those editors only show the appended fragment.

useSplitQueryCompletion({ baseQuery, search }):
- Registers a per-editor Monaco provider on editorDidMount
- Uses refs for baseQuery/search so the provider always reads current values
  without re-registration on every change
- Cleans up the provider disposable on unmount
- Zero knowledge of the strategy in the caller (ComposeDiscoverTabs)
- Swap strategy: replace only this hook if ES|QL adds a native context API

Wiring: ComposeDiscoverTabs calls the hook twice (alert + recovery) and passes
onEditorMount to TabEditor → CodeEditor editorDidMount.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant