Logs
This page helps you collect Goiabada’s logs and find what you need in them.
The metrics count; the logs say which request and why. Both servers write one record per line to standard error.
Collect the logs
Section titled “Collect the logs”-
Capture standard error. Every record goes there, request records included. If your setup captures only standard output, you’ll see nothing, and silence looks like no traffic rather than a stream nobody reads.
-
Write JSON, which most log pipelines parse without a pattern: set
GOIABADA_AUTHSERVER_LOG_FORMAT=jsonandGOIABADA_ADMINCONSOLE_LOG_FORMAT=json. The default,text, writes onekey=valueline per record. -
Log each request, with
GOIABADA_AUTHSERVER_LOG_HTTP_REQUESTS=trueandGOIABADA_ADMINCONSOLE_LOG_HTTP_REQUESTS=true. Every deployment the setup wizard generates already sets both. -
Count the
ERRORrecords. Each one is something that went wrong on Goiabada’s side, so put their rate on the same dashboard as the 5xx rate. -
Send the audit log to your pipeline if you alert on security events, as the audit log below describes.
Every record written while serving a request carries its request_id, so you can gather the records of one request. It’s the X-Request-Id your client or proxy sent, or one Goiabada made up.
Records worth knowing
Section titled “Records worth knowing”The level says who should look: ERROR means someone must act, WARN a request that was refused or handled, INFO startup, shutdown and the records below, and DEBUG diagnostic detail.
Record (msg) |
Level | What it says |
|---|---|---|
http request |
INFO |
One per request, with its method, target, ip, status, bytes and duration. Written only with request logging on |
audit event |
INFO |
One audit event, with its event name and details, written when the audit log’s console target is on |
worker task completed |
INFO |
A cleanup run that reached every step, with its duration. A failed step writes an ERROR record first |
a job to run after its response was dropped, too many in flight |
WARN |
A forgot-password, registration or email-change mail that wasn’t sent |
cross-origin request refused |
WARN |
A state-changing request the CSRF check refused as cross-origin, with its explanation and remedy. A run of them after a change of hostname or proxy is a misconfiguration rather than an attack |
client authentication refused at the token endpoint |
WARN |
A token request answered invalid_client, with the reason the client was given, the client_identifier as sent and the client_auth_method it used. A run of them from one client is usually a wrong or rotated secret |
client registration refused |
WARN |
A dynamic client registration refused with 400 or 403, with the error_code and the reason the registrant was given, such as a redirect URI it may not use. Written for the 403 of a server taking no registrations too |
database migrated |
INFO |
How many migrations a starting auth server applied, and their duration |
The audit log
Section titled “The audit log”The security events are in the audit log, not the metrics: every sign-in, failed password, token issued, rate-limit refusal and administrative change, each with who did it. It goes to standard error as the audit event records above, to the database, where the admin console browses it, or to both, as the Audit log settings page in the admin console says. New installations start with both.
Watch for a run of auth_failed_pwd or ropc_auth_failed events against one account, and for rate_limit_exceeded, which each pod writes at most once per key and window, so it shows which accounts and addresses the rate limiter’s refusals were about.
Levels
Section titled “Levels”Each server writes records at its level and above: GOIABADA_AUTHSERVER_LOG_LEVEL and GOIABADA_ADMINCONSOLE_LOG_LEVEL, info by default, or debug, warn or error. A level or format spelled any other way, uppercase included, stops the server at start. The environment variables list every logging setting.
Request records
Section titled “Request records”With request logging on, every request gets a record but three kinds, which are never logged: health checks (/health), static files (/static/) and /favicon.ico. A record’s request_id, method and ip are each clipped at 128 bytes, with the true length in a marker, so a very long request id sent by a proxy shows up shortened rather than missing.
What a request record leaves out
Section titled “What a request record leaves out”A request record names every query parameter that arrived, but not every value. Every query value is replaced by [redacted], apart from those of these names, whose value is kept: client_id, response_type, response_mode, scope, prompt, max_age, acr_values, code_challenge_method, ui_locales, error, page and size.
That keeps an id_token_hint, an activation code and a password reset code out of the log, along with anything a client puts in a parameter nobody has assessed. Names are matched exactly, so Client_ID is redacted like any other unknown name. Activation and password reset links reach the log once each: following one checks the code and redirects to the same page with no query string, so the code never reaches the address bar, the browser’s history or the Referer of anything the page loads.
The recorded target is an inventory, not a copy:
- It’s re-encoded. The query is parsed and written back, so parameters appear in alphabetical order and escaping is canonical:
scope=openid%20profileis recorded asscope=openid+profile. - It’s bounded. Each parameter name and each kept value is clipped at 512 bytes, and the whole target at 4096, each with a marker giving the true length. A target past 4096 bytes loses its later parameters.
- A query that can’t be parsed isn’t guessed at. It’s recorded as
?[unparsable query, N bytes], with no names at all.
Verbose API logging
Section titled “Verbose API logging”GOIABADA_AUTHSERVER_DEBUG_API_REQUESTS=true writes the request and response bodies of every /api/v1/admin and /api/v1/account call to the auth server’s log. It’s off by default and meant for development.
Credential values are replaced by [redacted] before anything is written: passwords, OTP codes and secrets, the authenticator enrollment image, client secrets, the SMTP password, email verification codes, the logout URL carrying a signed id_token_hint, and any field whose name contains password, secret, otp or token. Field names are kept, so the body’s shape is still readable. The Authorization header is written as Bearer [redacted], and the URL’s query is redacted as in a request record.
A body that isn’t valid JSON, is larger than 256 KB, or nests more than 32 levels deep is replaced by a one-line note giving its size and why it wasn’t logged.