Skip to content

[Streams] Match grok pattern color with preview highlighting#269680

Open
mohamedhamed-ahmed wants to merge 11 commits into
elastic:mainfrom
mohamedhamed-ahmed:grok-pattern-color-match-preview
Open

[Streams] Match grok pattern color with preview highlighting#269680
mohamedhamed-ahmed wants to merge 11 commits into
elastic:mainfrom
mohamedhamed-ahmed:grok-pattern-color-match-preview

Conversation

@mohamedhamed-ahmed
Copy link
Copy Markdown
Contributor

@mohamedhamed-ahmed mohamedhamed-ahmed commented May 18, 2026

closes https://github.com/elastic/streams-program/issues/1197

Summary

This PR adds similar color matching for the grok pattern and the preview highlighting

Screenshot 2026-05-18 at 15 45 06

@mohamedhamed-ahmed mohamedhamed-ahmed added the Team:obs-onboarding Observability Onboarding Team label May 18, 2026
@mohamedhamed-ahmed mohamedhamed-ahmed requested a review from a team as a code owner May 18, 2026 11:56
@mohamedhamed-ahmed mohamedhamed-ahmed added the Feature:Streams This is the label for the Streams Project label May 18, 2026
@infra-vault-gh-plugin-prod
Copy link
Copy Markdown

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

@mohamedhamed-ahmed mohamedhamed-ahmed added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting labels May 18, 2026
Copy link
Copy Markdown
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

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

This works well, one thing I'm not sure about is that we don't reuse color codes, which causes this (color cycles each key press):

Image

Besides the slightly weird visual, the effect of that is that the color assignments won't end up evenly distributed in the end, at least it's not guaranteed:

Image

Should we make it slightly smarter and kick out and reuse colors for group names that disappear? I think it would be cool to make the first group color x, the second group color y and so on in a consistent manner, if that makes sense

@@ -184,6 +195,7 @@ export class GrokCollection {

public resetColourIndex = () => {
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 seems like we don't need resetColourIndex anymore?

@flash1293
Copy link
Copy Markdown
Contributor

@mohamedhamed-ahmed I'm not sure how much time we should spend on it, it's really a balancing act - if we use the index of the named group for the color assignment, then they can change quite a bit if you add something in between, which is also not great. If @3kt is happy I'm happy too.

@3kt
Copy link
Copy Markdown

3kt commented May 19, 2026

The goal is to get beyond "just feature parity" for such a widely used processor: I want users to get a compelling reason to use Streams UI rather than anything else (plus it demos quite well). Ideally let's solve the color cycling then we're good to go.

@mohamedhamed-ahmed
Copy link
Copy Markdown
Contributor Author

Ideally let's solve the color cycling then we're good to go.

@3kt you mean the typing issue color cycles each key press that Joe mentioned in his comment?

@3kt
Copy link
Copy Markdown

3kt commented May 19, 2026

@mohamedhamed-ahmed yes - IIRC my attempt suffered from the same issue.

@mohamedhamed-ahmed
Copy link
Copy Markdown
Contributor Author

@mohamedhamed-ahmed yes - IIRC my attempt suffered from the same issue.

Yes tested it there as well, I already have a fix will test it now and push the changes

@mohamedhamed-ahmed
Copy link
Copy Markdown
Contributor Author

@flash1293 this is how the behavior is now.

Screen.Recording.2026-05-21.at.13.18.21.mov

@elastic elastic deleted a comment from kibanamachine May 21, 2026
@mohamedhamed-ahmed mohamedhamed-ahmed enabled auto-merge (squash) May 21, 2026 14:05
@3kt
Copy link
Copy Markdown

3kt commented May 21, 2026

Darn this looks great @mohamedhamed-ahmed <3

@flash1293
Copy link
Copy Markdown
Contributor

Colors are still behaving a bit weirdly:

Kapture 2026-05-26 at 16 09 44

But not a blocker I'd say. In general it feels like the UI is a bit laggy when using grok highlighting in general, @Kerry350 do you have any thoughts about this? Is this something that has room for optimization? Maybe more aggressive debounce? I don't mind if it takes a second to propagate a new pattern, but it's really annoying when typing and the characters don't appear. Also an issue on main though

@Kerry350
Copy link
Copy Markdown
Contributor

do you have any thoughts about this? Is this something that has room for optimization? Maybe more aggressive debounce? I don't mind if it takes a second to propagate a new pattern, but it's really annoying when typing and the characters don't appear. Also an issue on main though

Off the top of my head there's probably room to debounce better when doing the actual parsing, application of highlights in Monaco etc. We can probably separate that process from the process of "just" updating the actual input value. It might be harder than it sounds as it will cause character drift on the highlights already applied (if that makes sense), unless we're okay with something like clearing the highlights until the user is done typing. When I did the refactor to providers for easier consumer use the performance was okay, so maybe something changed along the way. Worth an issue to investigate at least.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements stable field-name-based color assignment for grok pattern editing. GrokCollection now tracks field-usage sources and allocates colors per field name instead of rotating through a palette. DraftGrokExpression implements the GrokFieldUsageSource contract, registering itself with the parent collection and reconciling field usage during edits. The Expression editor component uses internal editorValue state to decouple from external pattern updates, scans editor text for field tokens, and applies Monaco inline decorations mapped to assigned colors. Integration wires patternSlotId through context and UI components, and test coverage validates color stability, sharing, reuse, and lifecycle behavior.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • 🛠️ Update Documentation

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/platform/packages/shared/kbn-grok-ui/components/expression.tsx`:
- Around line 45-48: The DraftGrokExpression instance created in the useMemo
(draftGrokExpression) subscribes to customPatternsChanged$ and registers itself
as a field-usage source but is never destroyed, causing
subscription/registration leaks; update the component to ensure destroy() is
called when the component unmounts or when dependencies change (e.g., by
creating the DraftGrokExpression in the current hook and adding a useEffect that
returns a cleanup which calls draftGrokExpression.destroy()), referencing
DraftGrokExpression, draftGrokExpression, customPatternsChanged$, and destroy()
so the instance is properly unsubscribed and deregistered on teardown.

In
`@x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/grok/grok_patterns_editor.tsx`:
- Around line 195-212: The file uses the EuiToolTip component but it isn't
imported, causing a runtime error; update the import statement that destructures
components from '`@elastic/eui`' to include EuiToolTip (alongside existing imports
like EuiButtonIcon) in grok_patterns_editor.tsx so the EuiToolTip symbol is
available where the tooltip wrapping the remove button (onRemove handler /
EuiButtonIcon) is rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: 5ba4b7dd-ac53-417b-ab44-106525d09ba2

📥 Commits

Reviewing files that changed from the base of the PR and between 8952121 and 6721a5d.

📒 Files selected for processing (6)
  • src/platform/packages/shared/kbn-grok-ui/components/expression.tsx
  • src/platform/packages/shared/kbn-grok-ui/contexts/grok_expressions_context.tsx
  • src/platform/packages/shared/kbn-grok-ui/models/draft_grok_expression.ts
  • src/platform/packages/shared/kbn-grok-ui/models/grok_collection_and_pattern.ts
  • src/platform/packages/shared/kbn-grok-ui/models/grok_models.test.ts
  • x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/grok/grok_patterns_editor.tsx

Comment on lines 45 to +48
const draftGrokExpression = useMemo(() => {
return new DraftGrokExpression(grokCollection, pattern);
return new DraftGrokExpression(grokCollection, pattern, { patternSlotId });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [grokCollection]);
}, [grokCollection, patternSlotId]);
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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing cleanup for draftGrokExpression – subscription and registration leak.

DraftGrokExpression subscribes to customPatternsChanged$ and registers itself as a field-usage source. Without calling destroy() on unmount or when deps change, these persist indefinitely.

Proposed fix
  const draftGrokExpression = useMemo(() => {
    return new DraftGrokExpression(grokCollection, pattern, { patternSlotId });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [grokCollection, patternSlotId]);

+ useEffect(() => {
+   return () => {
+     draftGrokExpression.destroy();
+   };
+ }, [draftGrokExpression]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const draftGrokExpression = useMemo(() => {
return new DraftGrokExpression(grokCollection, pattern);
return new DraftGrokExpression(grokCollection, pattern, { patternSlotId });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [grokCollection]);
}, [grokCollection, patternSlotId]);
const draftGrokExpression = useMemo(() => {
return new DraftGrokExpression(grokCollection, pattern, { patternSlotId });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [grokCollection, patternSlotId]);
useEffect(() => {
return () => {
draftGrokExpression.destroy();
};
}, [draftGrokExpression]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/platform/packages/shared/kbn-grok-ui/components/expression.tsx` around
lines 45 - 48, The DraftGrokExpression instance created in the useMemo
(draftGrokExpression) subscribes to customPatternsChanged$ and registers itself
as a field-usage source but is never destroyed, causing
subscription/registration leaks; update the component to ensure destroy() is
called when the component unmounts or when dependencies change (e.g., by
creating the DraftGrokExpression in the current hook and adding a useEffect that
returns a cleanup which calls draftGrokExpression.destroy()), referencing
DraftGrokExpression, draftGrokExpression, customPatternsChanged$, and destroy()
so the instance is properly unsubscribed and deregistered on teardown.

Comment on lines +195 to +212
<EuiToolTip
content={i18n.translate(
'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.removePattern',
{ defaultMessage: 'Remove grok pattern' }
)}
/>
disableScreenReaderOutput
>
<EuiButtonIcon
data-test-subj="streamsAppDraggablePatternInputButton"
iconType="minusCircle"
color="danger"
onClick={onRemove}
aria-label={i18n.translate(
'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.removePattern',
{ defaultMessage: 'Remove grok pattern' }
)}
/>
</EuiToolTip>
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.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

EuiToolTip is used but not imported – runtime error.

Add EuiToolTip to the destructured imports from @elastic/eui on line 11.

Proposed fix
 import {
   EuiFormRow,
   EuiPanel,
   EuiButtonEmpty,
   EuiDraggable,
   EuiFlexGroup,
   EuiIcon,
   EuiButtonIcon,
   EuiFlexItem,
   useEuiTheme,
+  EuiToolTip,
 } from '`@elastic/eui`';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<EuiToolTip
content={i18n.translate(
'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.removePattern',
{ defaultMessage: 'Remove grok pattern' }
)}
/>
disableScreenReaderOutput
>
<EuiButtonIcon
data-test-subj="streamsAppDraggablePatternInputButton"
iconType="minusCircle"
color="danger"
onClick={onRemove}
aria-label={i18n.translate(
'xpack.streams.streamDetailView.managementTab.enrichment.processor.grokEditor.removePattern',
{ defaultMessage: 'Remove grok pattern' }
)}
/>
</EuiToolTip>
import {
EuiFormRow,
EuiPanel,
EuiButtonEmpty,
EuiDraggable,
EuiFlexGroup,
EuiIcon,
EuiButtonIcon,
EuiFlexItem,
useEuiTheme,
EuiToolTip,
} from '`@elastic/eui`';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@x-pack/platform/plugins/shared/streams_app/public/components/stream_management/data_management/stream_detail_enrichment/steps/blocks/action/grok/grok_patterns_editor.tsx`
around lines 195 - 212, The file uses the EuiToolTip component but it isn't
imported, causing a runtime error; update the import statement that destructures
components from '`@elastic/eui`' to include EuiToolTip (alongside existing imports
like EuiButtonIcon) in grok_patterns_editor.tsx so the EuiToolTip symbol is
available where the tooltip wrapping the remove button (onRemove handler /
EuiButtonIcon) is rendered.

@mohamedhamed-ahmed
Copy link
Copy Markdown
Contributor Author

@flash1293 @Kerry350 Do you think we can merge it with the current behavior and open a separats ticket for the debounce enhancement?

@kibanamachine
Copy link
Copy Markdown
Contributor

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] Scout Lane #6 - stateful-classic / default / local-stateful-classic - Entity analytics management page - Privileges - should show privileges callout and disable switch for user without risk engine privileges
  • [job] [logs] Scout Lane #6 - stateful-classic / default / local-stateful-classic - Entity analytics management page - Risk Score tab - should discard changes when clicking discard button
  • [job] [logs] Scout Lane #6 - stateful-classic / default / local-stateful-classic - Entity analytics management page - Risk Score tab - should show save bar when toggling closed alerts switch
  • [job] [logs] Scout Lane #6 - stateful-classic / default / local-stateful-classic - Entity analytics management page - Risk Score tab - should show save bar when toggling retain checkbox

Metrics [docs]

Async chunks

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

id before after diff
streamsApp 2.1MB 2.1MB +3.4KB

History

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

Labels

backport:skip This PR does not require backporting Feature:Streams This is the label for the Streams Project release_note:skip Skip the PR/issue when compiling release notes Team:obs-onboarding Observability Onboarding Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants