Logs
O2ID captures structured log entries — leveled (debug/info/warn/error)
and tagged with the resource(s) each entry is about (user, application,
role, ...) — that you can query and tail.
Reading logs requires a role with the logs:read scope — see Managing Roles for how to create and assign roles.
What gets captured
- Auth-flow events (login attempts, token issuance, consent decisions).
- One entry per mutating management API request (
POST/PATCH/PUT/DELETE), tagged with the resource type and ID from the request path.
Enabling and disabling levels
Which levels are captured is an explicit list rather than a min-level
threshold — so you can enable non-contiguous combinations (e.g. debug and
error without info/warn) if that's what you want, not just "this
level and everything above it". A level left off the list is entirely off:
no entries at that level are recorded, streamed, or shipped to remote
sinks.
Levels are per-tenant, the same way remote log publishing already is —
useful if one tenant wants debug-level detail flowing to their own
log-webhook destination while others don't. Set them with:
o2idctl tenant-settings update --log-level info --log-level warn --log-level error
Repeat --log-level to enable more than one. This takes effect immediately
— no restart required.
o2idctl tenant-settings update --clear-log-levels
Falls this tenant back to the platform's own default level set, configured
platform-wide in o2id.toml:
[logging]
levels = ["info", "warn", "error"] # default for tenants with no override
retention = "168h" # how long entries are kept (7 days)
stdout = true # also print every entry to stdout
retention and stdout apply to every tenant sharing the process and
require restarting o2id serve to change — there's no live config reload
for those. levels in o2id.toml only matters as the fallback for a
tenant that hasn't set its own override.
debug entries include request-flow detail (usernames, request internals)
you generally don't want captured by default — enable it only while
diagnosing an issue, and disable it again afterward.
Listing entries
o2idctl logs list
o2idctl logs list --level info --level error --component users
o2idctl logs list --user <user-id>
o2idctl logs list --since 2026-01-01T00:00:00Z --limit 50
Results are newest first. Resource flags: --user, --application,
--role, --agent, --resource-server, --connection, --authenticator,
--flow, --organization.
Tailing entries live
o2idctl logs tail
o2idctl logs tail --component oauth2 --application <application-id>
Streams newly captured entries matching the given filters until you stop it with Ctrl-C.
Shipping logs to a remote destination
Configure a log-webhook connection to deliver every captured entry to an
HTTPS endpoint of your choice, HMAC-signed so the receiver can verify it
came from your tenant:
o2idctl connections add --type log-webhook --name "SIEM Export" \
--field url=https://siem.example.com/ingest
See Managing Connections for how connections work generally.