Enable logging in your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['better-convex-nuxt'],
convex: {
url: process.env.CONVEX_URL,
logging: {
enabled: true, // Enable logging
},
},
})
| Option | Type | Default | Description |
|---|---|---|---|
logging.enabled | boolean | 'debug' | false | Enable logging (true = info, 'debug' = verbose) |
logging.format | 'pretty' | 'json' | 'pretty' | Output format |
convex: {
logging: {
// false - No logs (production default)
// true - Info-level canonical events
// 'debug' - Include debug-level details
enabled: process.env.NODE_ENV === 'development' ? 'debug' : false,
},
}
Pretty format (default) - Human-readable, ideal for development:
[better-convex-nuxt] > plugin:init [ok] client 47ms | url: happy-dog-123.convex.cloud, auth: enabled
[better-convex-nuxt] * auth:change loading -> authenticated | trigger: ssr-hydration, user: abc12345
[better-convex-nuxt] > query [ok] api.users.get 23ms (cached)
[better-convex-nuxt] > mutation [err] api.posts.create 156ms | error: ConvexError "Unauthorized", retriable
JSON format - Structured output for log aggregation systems:
convex: {
logging: {
enabled: true,
format: 'json',
},
}
{"timestamp":"2025-01-09T12:00:00.000Z","event":"plugin:init","env":"client","duration_ms":47,"outcome":"success","config":{"url":"happy-dog-123.convex.cloud","auth":true}}
{"timestamp":"2025-01-09T12:00:00.050Z","event":"auth:change","env":"client","from":"loading","to":"authenticated","trigger":"ssr-hydration","user_id":"abc12345"}
{"timestamp":"2025-01-09T12:00:00.073Z","event":"operation:complete","env":"client","type":"query","name":"api.users.get","duration_ms":23,"outcome":"success","cached":true}
The module emits canonical log events - one rich event per significant operation containing all context needed to debug issues.
Emitted when the Convex plugin initializes on client or server:
{
"event": "plugin:init",
"env": "client",
"config": { "url": "...", "siteUrl": "...", "authEnabled": true },
"duration_ms": 47,
"outcome": "success"
}
Emitted when authentication state changes:
{
"event": "auth:change",
"env": "client",
"from": "loading",
"to": "authenticated",
"user_id": "abc12345",
"trigger": "ssr-hydration"
}
Triggers: init, login, logout, token-refresh, ssr-hydration
Emitted when a query, mutation, or action completes:
{
"event": "operation:complete",
"env": "client",
"type": "mutation",
"name": "api.posts.create",
"duration_ms": 156,
"outcome": "success",
"optimistic": true,
"args_preview": "{\"title\":\"Hello...\"}"
}
On error:
{
"event": "operation:complete",
"env": "server",
"type": "query",
"name": "api.users.get",
"duration_ms": 45,
"outcome": "error",
"error": {
"type": "ConvexError",
"message": "Unauthorized",
"retriable": false
}
}
Emitted when a real-time subscription changes state:
{
"event": "subscription:change",
"env": "client",
"name": "api.posts.list",
"state": "subscribed",
"cache_hit": false
}
On unsubscribe:
{
"event": "subscription:change",
"env": "client",
"name": "api.posts.list",
"state": "unsubscribed",
"updates_received": 42
}
States: subscribed, unsubscribed, error, reconnecting
Emitted when WebSocket connection state changes:
{
"event": "connection:change",
"from": "Disconnected",
"to": "Connected"
}
On reconnection:
{
"event": "connection:change",
"from": "Disconnected",
"to": "Connected",
"retry_count": 3,
"offline_duration_ms": 5000
}
Emitted on the client when SSR state is hydrated:
{
"event": "ssr:hydration",
"outcome": "match",
"queries_hydrated": 0,
"auth_state_match": true,
"duration_ms": 2
}
On mismatch (e.g., auth token present but user data missing):
{
"event": "ssr:hydration",
"outcome": "mismatch",
"queries_hydrated": 0,
"auth_state_match": false,
"mismatch_details": ["token present but user missing"],
"duration_ms": 1
}
Enable logging and look for plugin:init events on both server and client:
[better-convex-nuxt] > plugin:init [ok] server 120ms | url: happy-dog-123.convex.cloud, auth: enabled
[better-convex-nuxt] > plugin:init [ok] client 47ms | url: happy-dog-123.convex.cloud, auth: enabled
If the server init fails, check your CONVEX_URL environment variable.
Track auth state transitions:
[better-convex-nuxt] * auth:change loading -> unauthenticated | trigger: init
[better-convex-nuxt] * auth:change unauthenticated -> authenticated | trigger: login, user: abc12345
Monitor operation timing:
[better-convex-nuxt] > query [ok] api.posts.list 230ms
[better-convex-nuxt] > query [ok] api.posts.list 12ms (cached)
The (cached) indicator shows when data comes from an existing subscription.
Track real-time subscription health:
[better-convex-nuxt] ~ subscription api.posts.list subscribed
[better-convex-nuxt] ~ subscription api.posts.list unsubscribed, updates: 15
Monitor WebSocket connectivity:
[better-convex-nuxt] || connection Connected -> Disconnected
[better-convex-nuxt] || connection Disconnected -> Connected, retry: 2, offline: 3500ms
For production, use JSON format and send logs to your aggregation system:
export default defineNuxtConfig({
convex: {
logging: {
// Enable in production only if needed for debugging
enabled: process.env.CONVEX_LOGGING === 'true',
format: 'json',
},
},
})
The structured JSON output integrates with tools like:
enabled: 'debug' with format: 'pretty' for maximum visibilityenabled: false by default, enable via environment variable when debuggingformat: 'json' for structured logging systems