Best Practices for Structured Logging
Learn how to structure your logs for maximum searchability and debugging value.
Use Metadata, Not String Interpolation
Embedding data in log messages makes them impossible to search reliably.
JavaScript
// Bad — hard to search, hard to aggregate
Lognitor.info(`User ${userId} purchased ${item} for $${amount}`);
// Good — searchable, filterable, structured
Lognitor.info('Purchase completed', {
metadata: { userId, item, amount },
tags: ['purchase', 'revenue'],
});Consistent Field Names
Use the same metadata field names across all services. Create a team convention:
| Field | Convention | Example |
|---|---|---|
| User ID | userId | user_123 |
| Order ID | orderId | ord_456 |
| Duration | durationMs | 245 |
| Amount | amount | 99.99 |
Use Actions for Event Types
The action field creates a searchable event taxonomy:
JavaScript
Lognitor.info('User signed up', { action: 'user.signup' });
Lognitor.info('Order created', { action: 'order.create' });
Lognitor.info('Payment processed', { action: 'payment.process' });Log at the Right Level
Don't log everything as info. Use levels meaningfully — debug for verbose internals, warn for concerning-but-functional states, error only when something actually failed.
Include Request Context
For HTTP services, always include request data:
JavaScript
Lognitor.info('Request completed', {
request: {
method: 'POST',
url: '/api/orders',
status_code: 201,
duration_ms: 45,
},
});Framework middleware handles this
If you use Express, Fastify, Django, or Laravel middleware, request context is captured automatically. You don't need to add it manually.