Skip to content

fix: avoid fabricated correlation IDs outside active HTTP request contexts #125

Closed

Description

@suppagoddo

Summary

When the library is initialized for Flask (and potentially Quart or Connexion), application logs emitted outside an active HTTP request context can contain a freshly generated, apparently valid correlation_id instead of the expected empty value ("-"). Subsequent log records can receive different fabricated IDs, making unrelated startup, shutdown, and Gunicorn access logs appear associated with real requests.

This behavior was identified during a cross-framework maintenance audit. It needs a regression test on current master before implementation.

Related history

Suspected cause

  • FlaskRequestInfoExtractor.get_current_request() and analogous framework extractors return a framework request proxy even when it is unbound.
  • RequestUtil.get_correlation_id() in json_logging/util.py currently distinguishes only request is None from an active request.
  • With a proxy but no request context, the code can generate a UUID. The framework-specific set_correlation_id() catches the failure to store it, leaving a new UUID to be generated for the next log.

Relevant paths: json_logging/util.py, json_logging/framework/flask/__init__.py, json_logging/framework/quart/__init__.py, and json_logging/framework/connexion/__init__.py.

Expected behavior

  • An application log emitted without an active HTTP request must report correlation_id: "-" (or preserve an explicitly supplied per-log correlation value), not generate and discard a random ID.
  • Application logs inside a request must continue to share the supplied correlation header or one stable generated value.
  • No changes to the default JSON schema, unrelated frameworks, or global logger behavior.

Reproduction and tests requested

  1. Enable JSON logging for Flask, configure a capture handler, and log twice before entering an HTTP request context and/or after the request completes.
  2. Check whether both records contain non-empty, unrelated generated IDs rather than "-".
  3. Repeat for Quart and Connexion where supported and include a Gunicorn worker example where practical.
  4. Confirm the regression test fails on unmodified master and passes with the fix.
  5. Confirm normal request logging, supplied-header IDs, generated IDs, and sequential/concurrent request isolation still work.

Proposed minimal fix

Use framework-native active-request-context detection to return None when there is no real request; keep RequestUtil's existing no-request EMPTY_VALUE behavior. Avoid global mutable context and broad refactors.

Acceptance criteria

  • Deterministic regression covering the original failure
  • No random correlation ID outside active HTTP requests
  • Stable, correct correlation IDs inside requests
  • Backward-compatible log fields and values inside requests
  • Relevant unit tests, smoke tests, and blocking lint checks pass
  • Changelog entry if behavior is modified

Release candidate: 1.6.0 if independently reviewed, tested, and ready by the release freeze; otherwise follow-up patch release.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions