Wide events logging pattern and conventions for this project. Use when writing logging code, adding observability, or implementing request tracing.
This project follows the Wide Events pattern. Logs are optimized for querying, not writing.
Emit one comprehensive event per request per service containing all contextual information. Do not scatter log statements throughout your code.
Wrong mental model: Log what your code is doing Correct mental model: Log what happened to this request
Each event should include:
{
// Request metadata
requestId: string,
traceId: string,
timestamp: Date,
service: string,
// HTTP details
method: string,
path: string,
statusCode: number,
durationMs: number,
// User context
userId?: string,
subscriptionTier?: string,
// Business context
pollId?: string,
spaceId?: string,
featureFlags: Record<string, boolean>,
// Error details (when applicable)
errorType?: string,
errorCode?: string,
errorMessage?: string,
isRetriable?: boolean,
// Performance metrics
dbQueryCount?: number,
dbQueryDurationMs?: number
}
Use middleware to build the event throughout the request lifecycle:
Never do these:
console.log statements throughout codeExample of what NOT to do:
// BAD - scattered, low-context logs
console.log("Starting request");
console.log("User authenticated");
console.log("Fetching poll");
console.log("Request complete");
Example of correct approach:
// GOOD - single wide event with full context
logger.info({
requestId: ctx.requestId,
userId: ctx.user?.id,
pollId: params.pollId,
method: "GET",
path: "/api/polls/:id",
statusCode: 200,
durationMs: 45,
dbQueryCount: 2,
dbQueryDurationMs: 12
});
When implementing log sampling, make decisions after request completion:
Always capture 100%:
Sample remaining traffic: 1-5% of successful, fast requests
Include high-cardinality fields (userId, pollId, requestId). Modern observability tools handle this efficiently. Aim for 50+ fields per event. Include: