Prometheus Tab-completion For Everybody
on Nov 22, 2017
I still remember my first steps with PromQL. Even after I learned more about the available functions and the Prometheus data model, the queries just would not flow as quickly as I liked. At Kausal, we believe making the writing of those queries easier will benefit the general adoption of Prometheus. That is why we decided to make our PromQL query editor open source.
The editor comes with tab-completion for metric names, label keys, label values, ranges, etc.
It is now available as prom-editor
at our public mono-repo: https://github.com/kausalco/public, wrapped inside an example React application.
We previously wrote about Slate and Prism, the underlying editor libraries.
This blog post will dive a little deeper into the mechanics of the editor and its integration into an application.
Editor Mechanics
The query field component wraps a Slate.js editor. That editor handles all the browser events that occur while typing and keeps a state object of the editor content. What should happen on typing input is determined by implementing API handlers or plugins. Currently, the query field uses both, eventually I would like it to be entirely plugin-based.
For event handling via plugins, consider the Runner plugin.
Its sole purpose is to handle Return key presses.
Based on which meta keys were pressed at the same time, it will enter a soft newline, or call the onPressEnter
handler that was provided to the editor component itself.
Plugins are evaluated in order: The first one to return
a new state will stop the chain evaluation and cause the editor to apply the returned state.
The query field also implements handlers directly, via props to the editor component.
An example is the onKeyDown
handler, which is in charge of controlling the interaction with the tab-completion, e.g., arrow up and tab, as well as some helpers that automatically close parenthesis.
Typeahead Suggestions
How do we know what to suggest?
We need a mechanism that tells us which part of a query we are currently typing, e.g., a function name, a metric name, a label value, etc.
What comes in handy here is the Prism.js plugin, which does the syntax highlighting.
We have structured the syntax rules not only to mark the tokens of a query, but also added some context markers.
Consider this query, just after the =
has been typed:
http_request_duration_microseconds{handler=|}
The Prism pattern 'context-labels': /\{[^}]*(?=})/
establishes that we are typing labels.
After we hit =
, the typeahead handler knows that a label value must follow.
The handler now looks left for the label key based on the 'label-key'
class that has been applied by Prism to the label key.
It does the same for the first metric name it sees to its left.
The metric name plus label key can now be used to look up the label values that the label key supports.
Those values will then be listed in as suggestions in the typeahead overlay.
The lookup of the label keys and values happens dynamically, as soon as the editor sees a {}
it starts querying for the available labels.
Naturally, there will be a slight delay in showing the suggestions based on how fast the Prometheus server responds.
Try It Yourself
We made the PromQL editor open source.
Here is the link to our public repository for our Open Source projects.
In that repo, the query field is in the prom-editor
project.
This project comes with an example React application that integrates the query field, shows the JSON results of a query, and prints a couple of query evaluation stats that have recently been added to the Prometheus API.
By default, the example application points to your local Prometheus installation (running on http://localhost:9090/).
If you need a different URL, just patch the api
proxy in package.json
.
To try it out, clone the repo, install its dependencies, and start it.
See the README for more details.
Upcoming Improvements
We are continuously improving the query editor. Here is a non-comprehensive list of things that still need work:
- Add support from Prometheus function name completion with docs snippet.
- The query analysis in not done with a proper lexer, so does not support all conceivable PromQL queries.
- A new slate.js version is available, consider upgrading.
- Wrapping issues with long queries.
- It’s too easy to end up with doubly-quoted label values.
Give it a try, and contributions are welcome!