Skip to content

feat: Monaco editor with LQL support for search field#3239

Open
msmithstubbs wants to merge 22 commits intoLogflare:mainfrom
msmithstubbs:feat/o11y-1309
Open

feat: Monaco editor with LQL support for search field#3239
msmithstubbs wants to merge 22 commits intoLogflare:mainfrom
msmithstubbs:feat/o11y-1309

Conversation

@msmithstubbs
Copy link
Contributor

@msmithstubbs msmithstubbs commented Mar 5, 2026

Use the Monaco editor component for the search field

  • Replaces the search field with a LiveMonacoEditor/1 component
  • Syntax highlight for LQL
  • Autocomplete for LQL operators, aggregates, source fields, and saved searches
  • Add vitest for JS testing framework (currently just covers lql_language.js)

I chose to replace the search <form> element and have the monaco editor instance communicate using liveview hooks and events. This simplified keeping the editor in sync with a hidden text input.

Fixes O11Y-1309

LQL syntax highlighting

CleanShot 2026-03-05 at 15 54 54@2x

Supports aggregate completions

CleanShot 2026-03-10 at 11 49 12@2x

Saved searches are included in autocomplete

CleanShot 2026-03-10 at 11 47 36@2x

Source query and recommended fields adopt similar styling

Same background and text colours, but not Monaco editor.

CleanShot 2026-03-12 at 14 15 03@2x CleanShot 2026-03-12 at 14 15 30@2x
CleanShot.2026-03-10.at.13.08.47.mp4

@Ziinc
Copy link
Contributor

Ziinc commented Mar 5, 2026

we can style the new suggested field inputs to look like the monaco inputs but doesn't need to be a monaco editor.
looks great!
can you add in suggestions for opertaors and for supported aggregations as well?

@msmithstubbs
Copy link
Contributor Author

msmithstubbs commented Mar 5, 2026

we can style the new suggested field inputs to look like the monaco inputs but doesn't need to be a monaco editor.
Sure, makes sense.

looks great! can you add in suggestions for opertaors and for supported aggregations as well?

Yes, can do.

What about suggested searches? We use have a <datalist> for those currently, but they could be pulled into monaco editor's autocomplete, too?

@msmithstubbs msmithstubbs force-pushed the feat/o11y-1309 branch 8 times, most recently from e2018ce to 6451e20 Compare March 11, 2026 06:25
@msmithstubbs msmithstubbs changed the title wip: Monaco editor with LQL support for search field feat: Monaco editor with LQL support for search field Mar 11, 2026
@msmithstubbs msmithstubbs marked this pull request as ready for review March 12, 2026 01:25
@msmithstubbs msmithstubbs marked this pull request as draft March 12, 2026 03:56
@msmithstubbs msmithstubbs marked this pull request as ready for review March 12, 2026 04:18
@Ziinc
Copy link
Contributor

Ziinc commented Mar 12, 2026

What about suggested searches? We use have a for those currently, but they could be pulled into monaco editor's autocomplete, too?

Yes the demo looks great, perhaps for the first character, we can limit it to saved searches only

CleanShot 2026-03-12 at 13 15 54@2x

i think we can consolidate metadata: into m: and maybe add a helper description so something like m: (alias metadata:) and for timestamp: into t: too, since shorthand is more commonly used.

Probably can also consolidate the c:group_by together as well.

should be s: instead of s:*, don't want to encourage users to select the world, would be too many fields and bad for ux.

Copy link
Contributor

@Ziinc Ziinc left a comment

Choose a reason for hiding this comment

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

considering this is a very important flow, lets add an integration test using PhoenixTest that executes a search using this.

would likely need to add postgres lql support for it to run on CI. can be separate PR with this stacked.

{ label: "m.", detail: "metadata field", insertText: "m." },
{ label: "metadata.", detail: "metadata field", insertText: "metadata." },
{ label: "s:*", detail: "select all fields", insertText: "s:*" },
{ label: "c:count(*)", detail: "chart count", insertText: "c:count(*)" },
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{ label: "c:count(*)", detail: "chart count", insertText: "c:count(*)" },
{ label: "c:count()", detail: "chart count", insertText: "c:count($0)" },

Copy link
Contributor

Choose a reason for hiding this comment

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

can we get this file's logic covered with tests? using vitest would be great, but whatever works.

Copy link
Contributor

Choose a reason for hiding this comment

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

too much chance for breakage for such an important component.


const monaco = window.monaco;

registerLqlLanguage(monaco);
Copy link
Contributor

Choose a reason for hiding this comment

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

should wrap this in a try/do to prevent mount failure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wrapped registerLqlLanguage to catch failure. Was that where you think we'd get an exception? Or are you concerned monaco might not be loaded at all?

hook.pushEvent("soft_pause", {})
})
},
pushChartControlsUpdate() {
Copy link
Contributor

Choose a reason for hiding this comment

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

should cover this hook with an integration test as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will include in the follow up integration test PR.

That should be an integration test with Playwright in test/e2e/features/ ?

Comment on lines +1187 to +1199
defp schema_fields_json(source), do: source |> lql_schema_fields() |> Jason.encode!()

defp lql_schema_fields(source) do
case SourceSchemas.Cache.get_source_schema_by(source_id: source.id) do
%{schema_flat_map: flat_map} when is_map(flat_map) ->
Enum.map(flat_map, fn {name, type} ->
%{name: name, type: format_schema_type(type)}
end)

_ ->
[]
end
end
Copy link
Contributor

Choose a reason for hiding this comment

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

can't we pass the flatmap directly? or this needs to be done elixir side?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can pass the flatmap as is if we only want the field names. If we'd like the field types, too, we need to encode any tuples (such as {:list, :string}) because they can't currently be JSON encoded.

I've simplified the schema fields helper, and moved it to FormComponents which is a little bit simpler because it reduces passing another assign and attribute. I don't love that a helper in FormComponents is fetching a record which might hit the db, but it's cached so shouldn't be a problem in practice.

Copy link
Contributor

Choose a reason for hiding this comment

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

i think would be better to move the fetch out of the template and into the liveview. feels like a code smell, plus we can consolidate the calls (liveview also stores source schema in state)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree with that. I couldn't see anywhere SearchLV stores source schema currently but there would be some refactoring if we stack this on top of #3120

@msmithstubbs msmithstubbs force-pushed the feat/o11y-1309 branch 7 times, most recently from 59ffada to 23a9f06 Compare March 16, 2026 22:33
@msmithstubbs msmithstubbs force-pushed the feat/o11y-1309 branch 3 times, most recently from 6c08e9a to f97ad82 Compare March 19, 2026 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants