Monitoring & Logs
Track performance and debug issues in production
📊 What is Monitoring?
Monitoring tracks your Next.js app's performance, errors, and user behavior in production. Logging captures detailed information about requests, errors, and system events, helping you debug issues and optimize performance for better user experience.
// Basic logging example
console.log('User logged in:', userId)
console.error('Payment failed:', error)
Monitoring Types
Performance
Track speed and load times
Error Tracking
Catch and log errors
User Analytics
Understand user behavior
Application Logs
Record system events
🔹 Basic Console Logging
Use console methods to log information during development and production. Different log levels help categorize messages by severity. Console logs appear in server logs for server components and browser console for client components.
// app/api/users/route.ts
export async function GET() {
console.log('Fetching users...') // Info
console.warn('Cache is stale') // Warning
console.error('Database connection failed') // Error
try {
const users = await fetchUsers()
console.log('Users fetched:', users.length)
return Response.json(users)
} catch (error) {
console.error('Error fetching users:', error)
return Response.json({ error: 'Failed' }, { status: 500 })
}
}
🔹 Structured Logging
Create structured logs with consistent formatting for easier parsing and analysis. Include timestamps, request IDs, and context information. This makes it easier to search and filter logs in production environments.
// lib/logger.ts
type LogLevel = 'info' | 'warn' | 'error'
export function log(level: LogLevel, message: string, meta?: any) {
const logEntry = {
timestamp: new Date().toISOString(),
level,
message,
...meta,
}
console.log(JSON.stringify(logEntry))
}
// Usage in your app
import { log } from '@/lib/logger'
log('info', 'User logged in', { userId: '123', email: '[email protected]' })
log('error', 'Payment failed', { orderId: '456', error: 'Card declined' })
🔹 Error Tracking with Sentry
Sentry automatically captures errors, provides stack traces, and tracks error frequency. It helps you identify and fix issues quickly by showing exactly where errors occur and how often they happen in production.
# Install Sentry
npm install @sentry/nextjs
// sentry.client.config.js
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
})
// sentry.server.config.js
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
})
// app/api/checkout/route.ts
import * as Sentry from '@sentry/nextjs'
export async function POST(request: Request) {
try {
const result = await processPayment()
return Response.json(result)
} catch (error) {
// Automatically sent to Sentry
Sentry.captureException(error)
return Response.json({ error: 'Payment failed' }, { status: 500 })
}
}
🔹 Performance Monitoring
Track Core Web Vitals and custom performance metrics. Next.js provides built-in performance monitoring through the Web Vitals API. Monitor page load times, API response times, and user interactions to optimize performance.
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'
import { SpeedInsights } from '@vercel/speed-insights/next'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
)
}
// app/components/web-vitals.tsx
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
console.log(metric)
// Send to analytics service
if (metric.label === 'web-vital') {
// Track: LCP, FID, CLS, FCP, TTFB
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify(metric),
})
}
})
return null
}
🔹 Custom Event Tracking
Track user interactions and business events. Monitor button clicks, form submissions, purchases, and other important actions. This data helps you understand user behavior and improve your application.
// lib/analytics.ts
export function trackEvent(eventName: string, properties?: any) {
// Send to your analytics service
console.log('Event:', eventName, properties)
// Example: Send to Google Analytics
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', eventName, properties)
}
}
// Usage in components
'use client'
import { trackEvent } from '@/lib/analytics'
export default function CheckoutButton() {
const handleClick = () => {
trackEvent('checkout_started', {
value: 99.99,
currency: 'USD',
items: ['product-1', 'product-2'],
})
}
return <button onClick={handleClick}>Checkout</button>
}
🔹 Request Logging Middleware
Log all incoming requests with details like method, URL, response time, and status code. Middleware runs on every request, making it perfect for centralized logging and monitoring of your API routes.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const start = Date.now()
// Log request
console.log({
method: request.method,
url: request.url,
timestamp: new Date().toISOString(),
})
const response = NextResponse.next()
// Log response time
const duration = Date.now() - start
console.log({
url: request.url,
duration: `${duration}ms`,
status: response.status,
})
return response
}
export const config = {
matcher: '/api/:path*',
}
🔹 Monitoring Best Practices
Follow these guidelines for effective monitoring and logging:
Key Practices:
- Log levels: Use appropriate levels (info, warn, error)
- Structured logs: Use JSON format for easy parsing
- Context: Include user ID, request ID, timestamps
- Sensitive data: Never log passwords or tokens
- Performance: Monitor Core Web Vitals regularly
- Alerts: Set up notifications for critical errors
- Retention: Define log retention policies