Logging
The module ships two logging mechanisms: a structured HTTP request logger, and a pino logger instance used by all internal operations. Both are available for use in your own handlers.
HTTP logger
httpLogger() is an H3 plugin that attaches structured request and response logging to your app. It hooks into onRequest, onResponse, and onError to capture the full lifecycle of every request.
Register it during startup. When using the Nuxt module, registration happens automatically.
import { createApp } from 'h3'
import { httpLogger } from 'auth-h3client/v1'
const app = createApp()
httpLogger()(app)
import { H3 } from 'h3'
import { httpLogger } from 'auth-h3client/v2'
const app = new H3()
app.register(httpLogger())
Logs output
On each request, the logger records:
- Request ID (
x-request-id): read from the incoming header if present, otherwise a random UUID. Set on the response and stored onevent.context.ridfor use by other middleware and handlers. - Method, URL path, query string, and full host URL
- Client IP address and User-Agent
- Request fingerprint via
getRequestFingerprint - All request headers and cookies (both redacted to
[SECRET]in the log output) - Referrer
On each response, it records the status code, response headers, content type, content length, and latency in milliseconds.
On errors, it records the status, error name, message, stack trace, and error body.
Log level selection
The HTTP logger selects the level for each response automatically:
| Status range | Level |
|---|---|
| 5xx or error context | error |
| 4xx | warn |
| 2xx / 3xx | info |
Output destination
Log output is written to logs/http.log as newline-delimited JSON using a pino file transport. The logs/ directory is created automatically at the nearest package.json root relative to the process working directory. Set the CLIENT_LOG_DIR environment variable to write logs to a different path. This logger is separate from the general getLogger() instance, but its minimum level is controlled by the same logLevel configuration field.
Log entry shape
Each request produces an entry at onRequest and a second entry at onResponse. The structure looks like:
{
"level": 30,
"time": "2026-04-12T10:00:00.000Z",
"uptime": 120.5,
"requestId": "a1b2c3d4-...",
"ip": "1.2.3.4",
"userAgent": "Mozilla/5.0 ...",
"FullUrl": "app.example.com/api/profile",
"fingerPrints": "...",
"referrer": "https://app.example.com/",
"httpRequest": {
"method": "POST",
"url": "/api/profile",
"headers": "[SECRET]",
"remoteAddress": "1.2.3.4"
},
"msg": "request start"
}
The response entry adds latencyMS and an httpResponse block with statusCode, statusText, resHeaders, contentType, contentLength, and type. Error entries use an httpError block with status, statusText, body, data, name, message, and stack.
The authorization header and all cookies are redacted to [SECRET] before the entry is written.
Skipped paths
The logger skips static asset paths (.css, .js, .png, .jpg, .svg, .ico, .woff, .ttf, .webp, .json, .map) and /.well-known/ paths to avoid noise in the log output.
getLogger
getLogger() returns the pino logger instance used internally by the module. Use it in custom handlers to write structured log entries in the same format as module logs.
export default defineAuthenticatedEventHandler(async (event) => {
const log = getLogger().child({ service: 'profile', route: '/api/profile' })
const { userId } = event.context.authorizedData
log.info({ userId }, 'Fetching profile')
return await getProfile(userId)
})
Child loggers inherit the parent log level and transport, and add the fields from the child bindings to every entry they produce.
Output is written to three files under the logs/ directory at the nearest package.json root relative to the process working directory: info.log (info and above), warn.log (warn and above), and errors.log (error and above). Set CLIENT_LOG_DIR to write to a different path.
Log levels
The logLevel field in the configuration controls the minimum severity level emitted by getLogger(). Available levels:
| Level | When to use |
|---|---|
debug | Development. Logs every internal step including token checks and cache hits |
info | Default. Logs route executions, token rotations, and key authentication events |
warn | Logs only potential issues such as rate limits, MFA challenges, and bot flags |
error | Logs errors only |
fatal | Logs only unrecoverable failures |
Set logLevel: 'debug' during development to see the full authentication flow. Use info or warn in production.