Skip to content

Logging

Logging captures information about what your application is doing. In production, logs help you debug issues, monitor performance, and understand user behavior.

When something breaks in production, you need to know what happened. Logs provide the trail of events leading up to the error.

The simplest logging is console.log. In production, these logs are captured by your hosting platform:

app/api/users/route.ts
export async function GET() {
console.log('[API] Fetching users')
try {
const users = await db.user.findMany()
console.log(`[API] Found ${users.length} users`)
return NextResponse.json({ data: users })
} catch (error) {
console.error('[API] Failed to fetch users:', error)
return NextResponse.json({ error: 'Internal error' }, { status: 500 })
}
}

Structured logs include metadata for better searching:

function log(level: string, message: string, context?: Record<string, unknown>) {
const entry = {
timestamp: new Date().toISOString(),
level,
message,
...context,
}
if (level === 'error') {
console.error(JSON.stringify(entry))
} else {
console.log(JSON.stringify(entry))
}
}
// Usage
log('info', 'User created', { userId: '123', email: 'user@example.com' })
log('error', 'Database connection failed', { error: err.message })
"use server"
export async function createUser(formData: FormData) {
const email = formData.get('email') as string
console.log('[Action] createUser called', { email })
try {
const user = await db.user.create({ data: { email } })
console.log('[Action] User created', { userId: user.id })
return { success: true }
} catch (error) {
console.error('[Action] Failed to create user', { email, error })
return { error: 'Failed to create user' }
}
}
LevelWhen to UseExample
debugDevelopment debugging onlyconsole.debug('Parsed body:', body)
infoNormal operationsconsole.log('User logged in:', userId)
warnUnexpected but handledconsole.warn('Rate limit hit:', ip)
errorFailures that need attentionconsole.error('DB connection failed:', err)
  • Include relevant context (user ID, request ID) in every log entry
  • Use structured logging (JSON) for better searchability
  • Never log sensitive data (passwords, tokens, PII)
  • Use appropriate log levels for different types of events
  • Aggregate logs with a service like Logtail, Datadog, or your platform’s log dashboard
  • Logging sensitive data — Never log passwords, tokens, or personal information
  • Too much logging in hot paths — Logging every request can be expensive and noisy
  • No context in log messages — “Error occurred” is useless without knowing where and why
  • Not logging errors properly — console.log(err) instead of console.error(err.message, err.stack)

Logging is essential for debugging production issues. Use structured logs with context, appropriate log levels, and never log sensitive data. Aggregate logs in a central service for searching and alerting.