Skip to content

[Nightshift] Shared investigation detail flyout - #289402

Merged
mykolaharmash merged 5 commits into
mainfrom
nightshift/homepage-2-shared-flyout
Sep 11, 2026
Merged

[Nightshift] Shared investigation detail flyout#289402
mykolaharmash merged 5 commits into
mainfrom
nightshift/homepage-2-shared-flyout

Conversation

@jasonrhodes

@jasonrhodes jasonrhodes commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

Adds InvestigationDetailFlyout and InvestigationRunStatusBadge to the nightshift_investigations plugin, exported from public/components/.

Important

It's probably not possible to see this code in this review, it's been left as a separated PR to isolate the changes for code review instead. Screenshots are included below, or you can run these commits alongside the next PR in this stack to see it all in action.

PR
1 list API
2 shared flyout ← you are here
3 app, list and row
4 list features

Both components are stateless — no internal data fetching — so any consumer (Nightshift, observability alerts, etc.) owns the query and passes data as props.

Screenshot 2026-09-04 at 6 43 15 PM Screenshot 2026-09-04 at 6 43 37 PM Screenshot 2026-09-04 at 6 43 47 PM

Hypotheses, recommendations and blind spots render as real content via HypothesisRow and FinalResults from @kbn/investigation-output, which are newly exported from that package (purely additive — it previously exported only InvestigationOutput, useInvestigationState, EvidenceList and the evidence-link helpers).

Escape hatches

Two optional props, matching the existing flyoutMenuProps / onClickCapture pattern, so a consumer can supply app-specific behaviour without this plugin depending on any app:

  • getQueryHref — builds Discover hrefs for evidence links inside hypotheses. HypothesisRow already types this optional, so degrading to non-linked evidence when absent is free.
  • flyoutMenuProps — pass-through to EuiFlyout for share URLs, EBT tracking, etc.

The type bridge

toInvestigationState bridges GetInvestigationResponse (where summary and hypotheses are optional, since they may not exist mid-run) to InvestigationState (which requires both). Defaults are safe: an empty summary renders nothing, empty hypotheses render nothing.

Note

@mykolaharmash raised a good question about this on the previous revision of this PR — whether the transformation belongs at fetch time instead, so the rest of the code doesn't need to think about it. Carried forward here and still open. One consideration: the flyout reads nine fields off GetInvestigationResponse (status, subject, executed_by, created_at, started_at, completed_at, error, investigation_id, summary) and only five feed InvestigationState, so the component needs the full response for its header regardless — moving the transform would make it an additional derived value rather than a replacement, unless the hook returns both.

Icon dependency

NightshiftMarkIcon is a local copy (public/components/nightshift_mark_icon.tsx) rather than an import from @kbn/observability-shared-plugin.

This plugin is "group": "platform" and observability_shared is observability/private, so importing it trips @kbn/imports/no_group_crossing_*. The mark is a static SVG with no logic, so duplicating ~45 lines was the cheapest fix. The file carries a comment saying to delete it and go back to the shared import once this plugin moves under x-pack/solutions/observability.

Worth noting for whenever that move happens: it can't happen in isolation. significant_events is also "group": "platform" and lists nightshiftInvestigations in optionalPlugins, and the manifest rule counts optional dependencies (no_group_crossing_manifests.ts:67) — so moving this plugin alone would just invert the same violation. Both need to move together.

Testing

The consumer arrives in PR 3 of the stack. To see it rendered, check out nightshift/homepage-3-app-and-list.

@@ -0,0 +1,58 @@
/*

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.

Can we put it inside a SVG file and use EUI's <Icon> component?

* they may not yet exist mid-run) to `InvestigationState` (which requires both).
* Defaults are safe: an empty summary shows nothing; empty hypotheses render nothing.
*/
function toInvestigationState(inv: GetInvestigationResponse): InvestigationState {

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.

Continuing on this type conversion.

I think ultimately we need to have a single complete type that represents investigation on the client. Having nearly identical GetInvestigationResponse and InvestigationState seems redundant. WDYT?

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.

Let's leave it as a follow up. There is now a bit of mess in terms of type ownership:

  • GetInvestigationResponse is in nightshift_investigations
  • InvestigationState is in @kbn/significant-events-schema
  • <FinalResults> that depends on InvestigationState is in @kbn/investigation-output

Any type unification would require some awkward boundary crossing. I'd first move everything into nightshift_investigations, then type unification would be more straightforward.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah this makes sense, a small follow up to just re-organize types would be great, and easy to review.

@jasonrhodes
jasonrhodes force-pushed the nightshift/homepage-2-shared-flyout branch from 1b6b98e to 0948be0 Compare September 9, 2026 02:05

@github-actions github-actions Bot 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.

One non-blocking note on missing unit coverage for the new components' formatting/bridging helpers. Implementation itself looks correct — status mapping is exhaustive, the newly-exported HypothesisRow/FinalResults prop shapes match, and the subject fallback chain is runtime-safe.

Generated by Claude Reviewer for #289402 · claude · opus · 183.7 AIC · ⌖ 22.7 AIC · ⊞ 5.5K

</EuiTitle>
);
}

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.

These new components ship with non-trivial pure logic but no unit tests, while the sibling @kbn/investigation-output package establishes a .test.tsx convention (hypothesis_row, evidence_list, etc.). A few behaviors here can regress silently and are cheap to pin down:

  • formatDuration boundary handling: sub-minute runs collapse to 0 min, the 60-minute rollover to 1h, and the {hrs}h {rem}m vs {hrs}h branch.
  • formatDate fallback to the Unknown time string on an unparseable ISO value.
  • toInvestigationState defaulting summary/hypotheses when absent mid-run, and InvestigationRunStatusBadge mapping each InvestigationStatus.

Worth a small unit test around the formatting/bridging helpers so future edits (or a new status value) fail loudly rather than rendering a wrong string.

@jasonrhodes
jasonrhodes force-pushed the nightshift/homepage-2-shared-flyout branch from 0948be0 to ac56eaf Compare September 9, 2026 02:23
Base automatically changed from nightshift/homepage-1-list-api to main September 10, 2026 13:18
jasonrhodes and others added 2 commits September 10, 2026 15:18
Adds `InvestigationDetailFlyout` and `InvestigationRunStatusBadge` to the
`nightshift_investigations` plugin, exported from `public/components/`.

Both are stateless — no internal data fetching — so any consumer
(Nightshift, observability alerts, etc.) owns the query and passes data
as props. Hypotheses, recommendations and blind spots render as real
content via `HypothesisRow` and `FinalResults` from
`@kbn/investigation-output`, which are newly exported from that package
(purely additive).

Two escape hatches, matching the existing `flyoutMenuProps` /
`onClickCapture` pattern, so a consumer can supply app-specific
behaviour without this plugin depending on any app: `getQueryHref` for
Discover links on evidence, and the pass-through flyout menu props.

`toInvestigationState` bridges `GetInvestigationResponse` (where
`summary` and `hypotheses` are optional, since they may not exist
mid-run) to `InvestigationState` (which requires both). Defaults are
safe: an empty summary renders nothing, empty hypotheses render nothing.

Adds `observabilityShared` as a required plugin dep for
`NightshiftMarkIcon`.

The consumer arrives in the next PR in the stack.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UZHFaTqNZLj89CHFr9YQwc
@mykolaharmash
mykolaharmash force-pushed the nightshift/homepage-2-shared-flyout branch from ac56eaf to e1e1292 Compare September 10, 2026 13:18
@github-actions

Copy link
Copy Markdown
Contributor

@jasonrhodes, this PR increases one or more page-load bundle sizes by 15% or more:

Limits file Plugin Before (bytes) After (bytes) Change
packages/kbn-rspack-optimizer/limits.yml nightshiftInvestigations 1,221 9,405 +670.3%

Large bundle size increases can affect page load performance. Consider whether dependencies can be lazy-loaded or code split to reduce the bundle.

See the bundle optimization guide for tips.

@mykolaharmash

mykolaharmash commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Pushed a few changes:

  • Lazy-load wrapper for the flyout component
  • Deleted the icon as the latest prototype doesn't have it (if we need it later, I'll ping EUI team to include it)
  • Addressed CI failures
  • Moved formatting helpers into a utils.ts

@github-actions github-actions Bot 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.

Reviewed the shared flyout components. Types, the GetInvestigationResponseInvestigationState bridge, and the FinalResults/HypothesisRow prop usage all check out. One non-blocking note left inline about missing unit coverage for the new pure date/duration utils.

Generated by Claude Reviewer for #289402 · claude · opus · 202.7 AIC · ⌖ 25.8 AIC · ⊞ 5.5K

Covers the branches flagged in review: formatDate invalid-input fallback,
formatDuration sub-minute clamp, 59-min boundary, whole-hour branch, and
hours+minutes branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@jasonrhodes jasonrhodes left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added some unit tests for utils functions, all the rest LGTM

@kibanamachine

kibanamachine commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
nightshiftInvestigations 1 4 +3
shared-packages 1271 1272 +1
total +4

Async chunks

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

id before after diff
nightshift 110.5KB 107.9KB -2.5KB
nightshiftInvestigations 4.0KB 8.9KB +4.9KB
securitySolution 1010.2KB 1010.2KB -4.0B
significantEventsApp 326.2KB 323.9KB -2.3KB
total +88.0B

Page load bundle

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

id before after diff
nightshiftInvestigations 1.1KB 8.3KB +7.3KB
shared-packages 4.6MB 4.6MB +2.5KB
significantEventsApp 4.4KB 4.4KB +1.0B
total +9.8KB
Unknown metric groups

shared chunks total size

id before after diff
all 7.0MB 7.0MB +158.0B

total optimizer output size

id before after diff
all 63.8MB 63.8MB +10.1KB

Test Failures

  • [job] [logs] FTR Configs #54 / Discover alerting Search source Alert should check that there are no errors detected after an alert is created
  • [job] [logs] FTR Configs #135 / lens app - group 8 lens logsdb smoke testing functions support Scenarios with changing stream type Data-stream upgraded to LogsDB scenarios LogsDB stream with an additional TSDB stream should visualize an annotation layer from a logsDB stream using another time field
  • [job] [logs] Scout Lane #9 - stateful-classic / default / local-stateful-classic - pingList query - returns a list of pings for the date range and given size

History

@mykolaharmash
mykolaharmash self-requested a review September 11, 2026 09:02
@mykolaharmash
mykolaharmash merged commit c0034f7 into main Sep 11, 2026
44 checks passed
@mykolaharmash
mykolaharmash deleted the nightshift/homepage-2-shared-flyout branch September 11, 2026 09:13
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:skip This PR does not require backporting release_note:skip Skip the PR/issue when compiling release notes v9.6.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants