mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 14:00:37 +00:00
* ✨ Count the application logs as a metric, by logger and level The error panels had no metric to read: they counted log lines in Loki, because the backend published nothing about the errors of the application (the only thing alive in Prometheus was the http listener error count, which measures another thing). Now there is `penpot_log_events_total{logger, level}`. The counter comes from a new component, `app.loggers.metrics/reporter`, which hooks a watch on the log record like the database and mattermost reporters do, but without a thread or a channel: the increment is in memory, so it runs in the watcher itself. Only `warn`, `error` and `fatal` are counted, and only the records that go through `app.common.logging`: the lines a library writes straight to log4j2 are not counted (one in a thousand today). The body of the watcher is wrapped in a `try/catch` that swallows the error on purpose: the watcher fires from the `swap!` of the log record, inside the logging path, so an exception there would reach whoever was logging and would take the logging executor down with it. A test pins that a failing publication does not propagate. The suite removes the reporter (it would count the logs of the tests and the recording of their `mtx/run!`), so a test of its own pins the wiring. The memories carry the counter, its two limits and why the `try/catch` is not noise; the grafana one also brings the notes of this afternoon about the service account, the dashboard search and Cloudflare, which were waiting for a commit. AI-assisted-by: deepseek-v4.1-flash * 📚 Address the review findings on the log-events metric The review of the counter found that the reason written for the `try/catch` was not the real one, so the memory and the comments say now what happens if it is removed: with `::l/sync?` the exception reaches whoever was logging, and on the async path it dies in the uncaught handler of the logging executor -- outside the application's logging -- where the pool replaces the worker, so logging continues and that line is lost. They also say that a publication failing every time is silent: the counter stays flat and nothing is written about it. The rest are small things the review asked for: the test of the `fatal` level (it was in the counted set and nothing verified it), the HELP of the metric naming the three levels, the require of the test without the unused alias that clj-kondo flagged, and the note that the `level` is lowercase here and uppercase in Loki. The grafana memory loses what was said twice: the two pairs of bullets about reading the API (the service account 403s and the search that lies) are merged, the CLIMIT notes are one bullet instead of two, and the four bullets about editing dashboards are grouped in their own section. Its host name is gone as well, which the first line of that file forbids. AI-assisted-by: deepseek-v4.1-flash