kuiper Docs

Dashboard

Finding things

Jump to any unit, deployment, domain or variable with Ctrl-K, search a project from the CLI, and filter logs with @level:error. The full reference for the search language.

On this page

Everything in a project can be found by typing a few letters. The dashboard has one search for names and one for logs, and the CLI has both. They share a single filter language, described in full at the end of this page.

Find, the palette#

Press Ctrl + K (⌘ + K on a Mac) anywhere in the dashboard. F and / do the same when your cursor is not in a text box, and the Search button in the top bar does too. (Inside a log panel, / goes to that log's filter instead.)

The palette with a few letters typed: units, actions and activity of one project.
Find. Results from the page appear at once, results from the server a moment later.

Type a few letters. Kuiper answers from what the page already knows (projects, the open project's units, pages and actions) and, a moment later, from a search of the project:

GroupWhat matches
UnitsThe unit's name, its address (web-lab.kiprsh.app) or its kind (station).
DeploymentsThe start of its ID (with or without dep_), the start of its commit SHA, its number (#12), its branch, its status, and the commit message and author of pushed commits. Newest first.
DomainsYour custom domains and the host they redirect to.
VariablesVariable names of every unit, and the names of shared values.
SecretsProject secret names.
Databases and BucketsTheir name or engine.
ActivityThe text of recent project events.

Variable and secret values are never searched and never shown, only their names. Matching ignores case, and % and _ mean themselves.

With no project open, the palette searches the whole organisation: projects (by name or slug), units and domains.

KeyWhat it does
↑ ↓Move through the results.
Tab and Shift + TabJump to the next or previous group.
EnterOpen the result, or run the action.
EscClose. Inside a confirmation, go back one step.

Opened results are remembered and listed under Recent the next time you open the palette with nothing typed.

Actions#

Commands appear in the same list. On a unit's page the palette lists that unit's actions first. Anywhere else, type the action: restart web, copy url web, logs web.

ActionWhat it does
Deploy unitBuilds the unit from its linked repository and deploys it.
Redeploy unitDeploys the live image again with the current environment.
Restart unitApplies pending variable changes.
Open logs of unitOpens Logs on that unit.
Open settings of unitOpens the unit's page, with its build and run settings.
Copy URL of unitCopies https:// and the unit's address.
Switch to organisationChanges organisation, for people who belong to more than one.
Toggle themeCycles system, light and dark.
Sign outEnds your session.

Deploy, Redeploy and Restart change something, so they ask first and need the admin or owner role. Press Enter to confirm or Esc to go back.

Search from the CLI#

Terminal
kuiper search web
kuiper search 3f2a1b -p lab
kuiper search "fix timeout"
kuiper search web --org

Without -p and a default project, kuiper search searches the whole organisation. --org does that even when a project is set, and --limit N changes how many results each group shows (up to 50). --json prints the raw answer, which has a dashboard route and an API path for every result.

The same search is an API call: GET /v1/projects/{project}/search?q=…&limit=…, and GET /v1/search?q=… for the organisation.

Filter logs#

Every log panel has a filter box: Logs (any unit), a deployment's Logs tab and its Runtime logs card, and the Build logs of a build. Press / while a log is focused, or on the Logs page, to jump to it.

The Logs page with JSON lines shown as a level, a message and attributes.
Logs. JSON lines become a level, a message and attribute chips.

The filter runs on Kuiper, over the newest 20,000 lines the node kept, not just the lines on screen. It keeps working while the log follows live.

  • JSON lines are shown as the time, a level badge, the message and the rest of the keys as key=value chips. Click a line to see the JSON. Click a chip to add it to the filter, or shift-click to leave lines with it out. Click a level badge to filter by level. Nested keys read as http.status.
  • Plain lines stay as they are, with ANSI colours drawn instead of printed as escape codes.
  • Matches shows only the lines that match. All lines shows every line and marks the matches, so you can read around them. Enter and Shift + Enter (or the arrows) jump to the next and previous match, and the box shows how many there are.
  • Wrap switches between wrapped lines and one line per row. Time hides the timestamps.
  • The download button saves the log as a text file. With a filter on, it saves the lines that match.
Terminal
kuiper logs -u web -q '@level:error'
kuiper logs -u web -q '@level:error,warn -health @user_id:42' --tail 100
kuiper logs -u web -f -q '@rid:r-1003'

kuiper logs -q (or --filter) takes the same filter and prints the last --tail matching lines. With -f it follows. The API is GET /v1/projects/{project}/units/{unit}/logs?q=…, and it answers with how many lines matched and were scanned. GET /v1/builds/{id}/log?q=… does the same for a build, and both have a /download form that returns the whole log as a file.

The filter language#

One small language is used everywhere: the log filter, the -q flag, and (in part) the palette. Terms are separated by spaces, and all of them must hold.

Output
@level:error @user_id:42 timeout -health "connection reset"

Words#

You typeIt matches
timeoutLines that contain timeout, in any case.
"connection reset"Lines that contain that exact phrase.
-healthLines that do not contain health. A leading - negates any term.

A word searches the line without its timestamp and stream. ANSI colour codes are ignored, so ERROR printed in red still matches error.

Fields: @key:value#

@key:value matches one field of a line. Keys ignore case. The value can be:

ValueIt matchesExample
textThat exact text, ignoring case.@level:error
a*A wildcard. * matches anything.@path:/api/*, @msg:*timeout*
>n, >=n, <n, <=nA number compared with the field.@ms:>500
a..bA number from a to b, inclusive.@http.status:400..499
5xxShorthand for 500..599.@http.status:5xx
a,b,cAny of the values.@level:warn,error

A number can end in ms or s (250ms, 1.5s); seconds are turned into milliseconds. A value with spaces goes in quotes: @msg:"two words". -@level:debug leaves debug lines out. A line that has no such field never matches a positive field term and always matches a negated one.

A malformed term (@level with no value, a number where text was expected) is an error shown next to the box, never a silent empty result.

Fields of runtime logs#

FieldAlso writtenWhat it is
@level@lvl, @severitytrace, debug, info, warn, error or fatal. Read from a JSON level (a name, or a pino or bunyan number from 10 to 60), a logfmt level=, or the start of a plain line (ERROR …, [warn] …, Error: …). Names such as warning, err and critical map to these. A lower-case word in the middle of a sentence is not a level.
@stream@fdstdout or stderr.
@deployment@depThe deployment the log belongs to. @deployment:dep_x picks that deployment's log; wildcards and - are checked against the log being read.
@rid@request_id, @req_idA request ID: a JSON rid or request_id key, or rid=… in a logfmt line.
@message@msgA JSON message or msg, or the whole line when it is not JSON.
@any.other.keyAny key of a JSON line, or any key=value pair of a logfmt line. A nested key is written with dots.

A line is JSON when it is an object ({ … }). A line is logfmt when it has key=value pairs (level=info msg="two words" user_id=7).

Fields of build logs#

FieldWhat it is
@levelAs above. error: …, npm ERR! and npm WARN count.
@lineThe line's number in the log. @line:>100 skips the first 100.
@message, @msgThe line.

Build logs have no streams and no JSON attributes, so any other @key is an error.

Examples#

FilterFinds
@level:errorEvery error line.
@level:warn,error -@stream:stdoutWarnings and errors written to stderr.
@http.status:5xx @path:/api/*Server errors under /api, in JSON request logs.
@user_id:42 -@level:debugWhat one user did, without the debug noise.
@rid:r-1003Everything one request logged.
@ms:>1s "payment"Slow lines that mention payment.
-health -pingEverything except health checks.

Limits#

  • A search reads the newest 20,000 lines the node holds. When the log is longer, Kuiper says it searched the newest lines.
  • One answer carries at most 5,000 lines. A download carries the whole retained log (up to 200,000 lines).
  • A node that runs an older kuiperd serves at most 5,000 lines per request, so a search or a download there covers the newest 5,000.
  • Logs are filtered as stored: redaction of secret values is unchanged, and so is the text of every line.