Skip to content
Documentation: Logs

Logs

What the server writes, as JSON, and where to read it.

Describes Ronne AI Marketplace 0.4.0.

Logs

Ronne writes one line per event to its standard output, as JSON: when it happened, how serious, what happened, and the request it belongs to. Where that output goes depends on how Ronne runs:

Ronne runs asIts logs
Dockerdocker compose logs web (Docker's logging driver)
A Linux servicesudo rmk-server service logs, or journalctl -u rmk-server
A macOS servicesudo rmk-server service logs, or /Library/Logs/rmk-server/server.log
npm or a package with Node.js inside, no servicethe terminal running rmk-server start
A clonethe terminal running pnpm start, or pnpm dev (as text)

A line looks like this:

{"time":"2026-10-14T14:03:22.417Z","level":"info","msg":"Released","domain":"submissions","event":"version.released","requestId":"01K7…","userId":"01J9…","count":3}
  • Always: time (UTC), level and msg, a short sentence that never changes.
  • When they apply: event, a stable name to search and alert on; domain, the part of Ronne that wrote it; requestId, the request it belongs to; userId, who made it (an id, never an email or a name); err, an error's name, message and code, with its stack at error; with tracing on, traceId and spanId, the span it was written in (Monitoring).
  • The event's own fields: numbers, counts and short reasons, such as status or count.
  • Better Auth's own lines (sign-in's library): msg is Better Auth, with source and its text in detail.

LOG_LEVEL (debug, info, warn or error; info by default) sets the least serious lines written: warn is what someone should look at, error a failure, and debug adds detail nobody needs day to day. An unknown value writes one warning and uses info. LOG_FORMAT is json, or text for a person reading a terminal (the default with pnpm dev). Set either in the settings file or the environment (with Docker, in the .env file next to compose.yaml, then docker compose up -d), and restart Ronne.

The events:

EventLevelWhenFields
server.startedinfoThe server started (before setup, setup: required in place of dialect)version, dialect, setup, runtime, port
server.migrations_appliedinfoDatabase changes were applied at startcount, latest
http.requestinfo (warn for 429, error for 5xx)An API request was answeredmethod, route, status, ms, userId
http.errorerrorAn unexpected errorerr, route
auth.signed_ininfoSomeone signed inuserId
auth.sign_in_failedwarnA sign-in failed (via is cli for rmk login; reason is two_factor_required when rmk login sent the right password of an account with two-factor)reason, via
auth.rate_limitedwarnToo many sign-ins or token requestslimit
auth.two_factor_startedinfoSomeone started setting up two-factor sign-inuserId
auth.two_factor_enabledinfoTwo-factor sign-in was turned onuserId
auth.two_factor_disabledinfoTwo-factor sign-in was turned offuserId
auth.two_factor_failedwarnA two-factor code was refused at sign-inreason (wrong_code, used, expired, too_many, locked, refused, unreadable)
token.exchangedinformk login, or a browser approval, got an access tokenuserId
token.rejectedwarnAn access token was refusedreason (unknown, revoked, expired, disabled)
version.releasedinfoVersions were released (one line when releasing many at once)count, userId
version.yankedinfoA version was yankeduserId
draft.uploadedinfoA draft was uploadedfiles, bytes
draft.upload_refusedwarnA draft upload was refusedreason
upload.rate_limitedwarnToo many uploads or submitslimit
usage.rate_limitedwarnToo many usage reportslimit
submission.checks_failedwarnSubmit's checks couldn't runerr
feed.builtinfo (debug from the cache)A plugin feed was built, or served from the cache (cached, without plugins or ms)tool, plugins, ms, bytes, cached
feed.size_warningwarnA feed is near its size limittool, percent
feed.plugin_skippedwarnA plugin was left out of a feedtool, reason
db.unavailableerrorThe health check couldn't reach the databaseerr
storage.unavailableerrorThe health check found storage not writableerr
telemetry.startedinfoOpenTelemetry started (Monitoring)traces, metrics
telemetry.endpoint_invalidwarnThe OTLP endpoint isn't an http(s) URL; telemetry is off
telemetry.failederrorOpenTelemetry couldn't start; the server starts without iterr
telemetry.verbose_offwarnNEXT_OTEL_VERBOSE is turned off: verbose spans would carry private names
telemetry.export_failedwarnThe collector couldn't be reached (at most once a minute)signal
job.startedinfoA scheduled job started (Privacy: the retention purge)job
job.finishedinfoA scheduled job finished, with what it didjob, ms, ipsCleared, emailsCleared, sessionsDeleted, grantsDeleted
job.skippeddebugAnother run holds the job's lockjob, reason
job.failederrorA scheduled job failed; the next runs on schedulejob, ms, err
log.level_invalidwarnLOG_LEVEL isn't a level; info is used

Never in a line: passwords, access tokens, cookies, AUTH_SECRET, a database's password, emails, people's IP addresses, or the names of items, scopes and workspaces (a private workspace's names stay private). Ronne doesn't write them, and the logger also takes out what could slip in, error messages included: fields named like a secret, access tokens, passwords in addresses, emails, the paths of stored files, and the value a database quotes in a duplicate-key error. Next.js also prints an unexpected error itself, as plain text next to Ronne's line: that text is Next.js's own, outside Ronne's logger. So is the error Better Auth (sign-in's library) prints when the database itself fails mid-request.

Reporting a problem: every page and API response carries an X-Request-Id header, and the API's message for an unexpected error names it. Quote it, and whoever runs the instance finds that request's lines by their requestId. Behind a proxy that sets its own X-Request-Id, Ronne keeps it when TRUST_PROXY=true, so one ID follows the request through.