Structured Logging Best Practices for 2026
Published 2026-01-28 · Updated 2026-03-01
>_ what is structured logging and why should you care?
>_ json logs vs. text logs: a practical comparison
// Unstructured text log — hard to parse programmaticallyconsole.log('User 12345 failed login attempt 3 from IP 192.168.1.1');// Structured JSON log — easy to search, filter, and aggregateconsole.log(JSON.stringify({ event: 'login_failed', userId: '12345', attemptCount: 3, ipAddress: '192.168.1.1', timestamp: new Date().toISOString(),}));>_ best practice 1: use consistent field names
- $Pick one naming convention: camelCase or snake_case
- $Standardize common fields: timestamp, level, message, requestId, userId
- $Create a shared logging utility that enforces conventions
- $Document your logging schema for the team
>_ best practice 2: add context, not just messages
// Bad: No contextconsole.error('Payment failed');// Good: Rich context for debuggingconsole.error(JSON.stringify({ event: 'payment_failed', userId: user.id, orderId: order.id, amount: order.total, currency: order.currency, paymentMethod: payment.method, errorCode: error.code, errorMessage: error.message, retryCount: attempt, duration_ms: Date.now() - startTime,}));>_ best practice 3: use log levels correctly
- $DEBUG: Detailed diagnostic information for development
- $INFO: Significant events in normal application flow
- $WARN: Unexpected situations that are handled gracefully
- $ERROR: Failures that need investigation or affect users
- $FATAL: Application is about to crash or has become unusable
>_ best practice 4: include request and correlation ids
import { v4 as uuidv4 } from 'uuid';// Express middleware to add request IDapp.use((req, res, next) => { req.requestId = req.headers['x-request-id'] || uuidv4(); res.setHeader('x-request-id', req.requestId); next();});// Include requestId in every logfunction log(level, message, data = {}) { console.log(JSON.stringify({ timestamp: new Date().toISOString(), level, message, requestId: getCurrentRequestId(), ...data, }));}// Usagelog('info', 'Processing order', { orderId: 'order_789', userId: 'user_123', items: 3,});>_ best practice 5: do not log sensitive data
- $Never log: passwords, tokens, API keys, credit card numbers, SSNs
- $Mask partially: email addresses, phone numbers, IP addresses
- $Use allowlists rather than blocklists for sensitive field detection
- $Implement automated scanning for sensitive data in logs
- $Review logging statements in code review with security in mind
>_ putting it all together
>_ frequently asked questions
Use structured logging in your code, but configure your logger to output human-readable text in development and JSON in production. Most logging libraries support different formatters per environment, so you get readability during development and parseability in production.
JSON logs are typically 20-50% larger than equivalent text logs due to field names and JSON syntax. However, the increased searchability and queryability more than compensates for the additional storage cost. Most log management tools compress JSON efficiently.
For JavaScript/Node.js: Pino or Winston. For Python: structlog. For Go: zerolog or zap. For Java: Logback with Logstash encoder. All of these support structured JSON output and are well-maintained.