All posts

chmonitor v0.3.9 — Know who runs what

Every dashboard query now says who ran it and from where, a new Dashboard Usage page reads that back, the users page shows activity and last login, and alerts thread on Matrix and Telegram.

October 24, 2026

chmonitor v0.3.9 ships 9 new features and 10 fixes since v0.3.8. Every query the dashboard sends now carries who ran it and from which page, a new Dashboard Usage page reads that back, the users page shows who is active, and repeat alerts thread under the first message.

What’s new in v0.3.9

Query attributionEach dashboard query carries the user, source, host and version.
Dashboard UsageWho uses the dashboard, which pages, and what it costs, global and per user.
Users pageStatus, queries, errors, last query, last login, and a detail row per user.
Alert threadsRepeats, escalations and recovery reply under the first alert on Matrix and Telegram.
Webhook alert blockOpt-in structured alert data and top contributors for agents.
Optimization planAdvisor findings ranked into one plan. It recommends, it never applies.
Replica driftAn opt-in toggle in the access matrix compares grants across replicas.

Every query says who sent it

Before this release, a dashboard query in system.query_log looked like any other query from the same ClickHouse user. Now each one carries an attribution record in two places. The SQL starts with one JSON comment:

/* {"client":"clickhouse-monitoring","app":"chmonitor","v":1,"version":"0.3.9","user":"jane","source":"chart:query-count","host":"ch-0"} */
SELECT ...

The same JSON goes into the log_comment setting, so you can read it back with JSONExtractString(log_comment, 'user'). Pages, charts, the SQL console, agent tools, cron jobs and per-user connections all send it.

A few rules keep it safe:

Turn it off with CHM_QUERY_ATTRIBUTION=false. CHM_QUERY_ATTRIBUTION_LABEL adds your own label, CHM_QUERY_ATTRIBUTION_SQL_COMMENT controls the comment, and CHM_QUERY_ATTRIBUTION_INCLUDE_EMAIL adds the email to log_comment.

Interactive: each card is one dashboard query. The press stamps the attribution comment on it, the card files into query_log, and the column of the user who ran it grows by one. Hover a column, or use the arrow keys, to read one user's count. The names and counts are illustrative.
Eight queries from three users go through the press and into the log, and each user's column grows as they file.

Dashboard Usage

The new Dashboard Usage page reads the attribution record back from the query log. The global view has KPI tiles for queries, users, error rate, p95 duration and bytes read, charts for queries, errors and p95 over time, and top 10 lists for users, sources, pages, versions and labels.

Click a user for the per-user view: the same KPIs and charts for that one person, their top sources and pages, recent queries as normalized shapes, errors by message, and the most expensive queries. One selector sets the window to 1, 7 or 30 days. Scans are capped at 30 days, and the page does not poll. It needs the operations permission, and a user’s view never shows other users.

Users page

The users page now answers who is active and what they run. Each row shows a status (active, idle or inactive over this replica’s 7-day query log), queries in the last 24 hours and 7 days, errors, the last query, the last login from session_log, and whether the account expires.

Open a row to see that user’s queries per hour, query kinds, last five query shapes, last login address and interface, roles and profiles, and links to their usage, history, failed and running queries. When query_log or session_log is missing, the page hides those columns instead of failing.

Alerts

Repeat alerts now thread. On Matrix and Telegram, reminders, escalations and the recovery reply under the first message of the alert, so one problem stays in one thread. A thread is one host, rule and destination, from first alert to recovery. Without a metadata database, alerts are sent as top-level messages as before. Slack keeps the compact repeat line, because incoming webhooks return no message id to reply to.

Webhooks can carry a structured alert block. Targets and subscriptions with details turned on get one alert object: rule, metric, threshold, value, previous value, trend, first seen, and repeat count. Cluster text sits under an untrusted key, with secrets redacted and each string capped at 200 characters. It is built for agents that read alerts.

Firing alerts on those targets also list the top contributors: the top five tables by disk or by active parts, or the top five running queries by memory or by elapsed time, depending on the rule. Queries appear as normalized shapes with no raw literals. If the read fails, the field is left out and the alert still goes out.

This changes the raw webhook body: the key details is now alert, and details.firstFiredAt is gone.

Also in this release

Upgrading

Pull the new image or redeploy. Query attribution is on by default. If you parse the raw webhook body, read alert instead of details.

docker pull ghcr.io/chmonitor/chmonitor:0.3.9

On Kubernetes, Helm chart 0.2.19 ships with this release. It adds a queryAttribution: block to values.yaml that sets the attribution env vars.

helm repo update
helm upgrade my-chm chmonitor/chmonitor --version 0.2.19

The chm CLI v0.1.5 sends its usage telemetry to the shared telemetry service. Every opt-out still works, including DO_NOT_TRACK and CHM_TELEMETRY=off.

Read more