NIST AU-3 requires that audit records be formatted consistently so they can be reliably parsed and analyzed. Inconsistent logging — some files using userId, others user_id, some emitting JSON, others emitting plain strings — defeats the purpose of structured logging. A query for userId = 'abc' in your log platform returns no results for log entries that used user_id instead. Inconsistent format also means your log platform's parser may fail to extract structured fields from some entries, causing them to appear as unindexed raw strings. The cost of inconsistency compounds over time: every developer who adds a new log entry makes a slightly different field naming decision, and the drift accelerates.
Low because log format inconsistency degrades query reliability and incident response efficiency, but does not directly expose vulnerabilities or data.
Enforce a single import path for the logger and define standard field names so every log entry in the codebase is consistent.
// Always import from the central module
import logger from '@/lib/logger'
// Standard fields: userId (not user_id), requestId (not req_id), operationId
logger.info({ userId, requestId, operationId: 'checkout.init' }, 'Checkout started')
Do a codebase-wide search for direct console.log and console.error in server-side directories (app/api/, lib/, actions/) and replace with the shared logger:
grep -r 'console\.log\|console\.error' app/api/ lib/
Document your standard field names in lib/logger.ts JSDoc or docs/logging-standards.md so new contributors know the convention. Consider adding an ESLint rule (no-console) for server-side files to prevent regressions.
ID: saas-logging.observability.log-format-consistent
Severity: low
What to look for: Enumerate all relevant files and Check whether the same logger and log format is used across different parts of the application — API routes, background jobs, webhooks, middleware, server actions, and utility functions. Look for: multiple different loggers in use (some files import from lib/logger, others use raw console.log, some use Winston while others use Pino), inconsistent field naming (some log entries use userId, others user_id, others uid), or log entries in different formats (some JSON, some plain text, some using structured fields and others using template strings).
Pass criteria: A single logger module is imported and used consistently throughout the server-side codebase. Field names are consistent across log entries. The log format (JSON vs. text) is consistent.
Fail criteria: Multiple logging approaches in use — some files use the shared logger, others use raw console.log or a different library. Inconsistent field naming or format across modules.
Skip (N/A) when: No server-side logging of any kind.
Detail on fail: "Inconsistent logging: src/lib/ uses pino logger but app/api/webhooks/* uses console.log directly; field naming inconsistent (userId vs user_id across files)"
Remediation: Inconsistent logging defeats the purpose of structured logging — you can't reliably query for userId if half your logs use user_id. It also makes logs harder to read during incidents.
The fix is simple: ensure every server-side file imports from your central logger module:
// Always import from the central logger
import logger from '@/lib/logger'
// Never use raw console in server code
// console.log(...) // remove these
Do a codebase-wide search for console.log and console.error in server-side code (not in client components) and replace with the appropriate logger calls. Define and document your standard field names (e.g., always userId not user_id) in your logger module's JSDoc or a docs/logging-standards.md file.