# Log levels are used appropriately

- **Pattern:** `ab-002312` (`saas-logging.app-logging.log-levels-appropriate`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002312
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002312)

## Why it matters

CWE-779 (Logging of Excessive Data) and CWE-778 (Insufficient Logging) sit at opposite ends of the same failure: logging everything at one level either floods your log store with noise or misses the signal entirely. OWASP A09 and NIST AU-2 both require that logged events carry enough severity context to support triage. When `error` level is used for informational messages or `info` is used for caught exceptions, alerting rules misfires — high-severity issues never trigger a page, and on-call engineers chase false alarms. The business impact is delayed incident response: teams lose the ability to distinguish a 500-rate spike from routine debug output.

## Severity rationale

Medium because miscategorized log levels degrade alert fidelity without directly exposing data, but they predictably delay incident detection and response.

## Remediation

Audit your catch blocks and log call sites and apply consistent level semantics: `error` for failures that require attention, `warn` for recoverable anomalies, `info` for significant business events, `debug` for diagnostic detail.

```ts
try {
  await processPayment(userId)
  logger.info({ userId, event: 'payment.success' }, 'Payment processed')
} catch (err) {
  logger.error({ err, userId }, 'Payment processing failed') // error — not info
}
```

Search for `logger.info` inside `catch` blocks across `app/api/` and `lib/` — those are the most common miscategorizations. Set up a Sentry alert rule on `error`-level log volume so you notice when the rate changes.

## Detection

- **ID:** `log-levels-appropriate`
- **Severity:** `medium`
- **What to look for:** Enumerate all relevant files and Examine server-side code for log level usage. Check whether `error` level is used for actual errors (caught exceptions, failed operations), `warn` for recoverable problems and unexpected states, `info` for notable business events (user signed up, subscription created), and `debug` for detailed diagnostic data. Look for misuse: using `error` for informational messages, using `info` for everything, or using a single level throughout. Quote the exact code pattern or configuration value found.
- **Pass criteria:** At least 1 implementation must be present. At least two distinct log levels are in use in server-side code, used in semantically appropriate contexts. Errors and exceptions are logged at `error` level. Routine operational messages use `info` or lower. Debug-level logging exists and is separate from error-level.
- **Fail criteria:** Only one log level is used throughout (usually `console.log` or `logger.info` for everything), OR errors and normal messages are logged at the same level, OR the logging library is present but level differentiation is absent. A partial or incomplete implementation does not count as pass.
- **Skip (N/A) when:** No server-side logging of any kind is present (see `structured-logging` — if that check is skipped, this one is too).
- **Cross-reference:** For performance impact of logging on application throughput, the Performance & Load audit covers I/O bottlenecks and async patterns.
- **Detail on fail:** Describe the issue specifically. Example: `"All logging uses logger.info including exception catch blocks; error-level logging not used anywhere in server code"` or `"console.log used for everything — no level differentiation"`
- **Remediation:** Log levels let you filter noise in production and alert on real problems. The convention is: `error` for things that need immediate attention, `warn` for things that are wrong but recoverable, `info` for significant business events, `debug` for diagnostic detail you only need when investigating.

  Update your error handlers to use the right level:
  ```ts
  try {
    await processPayment(userId)
    logger.info({ userId, event: 'payment.success' }, 'Payment processed')
  } catch (err) {
    logger.error({ userId, err }, 'Payment processing failed') // error level for failures
  }
  ```

## External references

- cwe CWE-779
- cwe CWE-778
- owasp A09
- nist AU-2

Taxons: observability

HTML version: https://auditbuffet.com/patterns/ab-002312
