Skip to content

feat: Centralize logging setup with structlog integration#179

Open
khvn26 wants to merge 5 commits intomainfrom
feat/logging-improvements
Open

feat: Centralize logging setup with structlog integration#179
khvn26 wants to merge 5 commits intomainfrom
feat/logging-improvements

Conversation

@khvn26
Copy link
Member

@khvn26 khvn26 commented Mar 13, 2026

Closes #31

Logging setup moves from Django settings into flagsmith-common, running before Django loads. Both stdlib and structlog now route through a single ProcessorFormatter, so all output (app code, structlog, Gunicorn error logs) shares the same format and ISO timestamps.

Key additions

  • setup_logging() in common.core.logging — configures stdlib via dictConfig, then wires structlog through stdlib using LoggerFactory (not PrintLoggerFactory). Accepts application_loggers for per-package level control.
  • build_processor_formatter() — shared formatter builder used by both the root logger and GunicornJsonCapableLogger, ensuring consistent rendering.
  • sentry_processor in common.core.sentry — structlog processor that sets Sentry context from event dicts. Hardwired into the structlog processor chain. Since structlog routes through stdlib, Sentry's LoggingIntegration automatically captures ERROR+ logs.
  • application_loggers allowlist — root logger stays at WARNING to suppress third-party noise; listed app loggers get the requested level. DEBUG overrides everything. Configurable via APPLICATION_LOGGERS env var (comma-separated).
  • Gunicorn error logs now use ProcessorFormatter for both json and generic formats (access logs unchanged — still CLF for generic, GunicornAccessLogJsonFormatter for JSON).
  • sentry-sdk added as an explicit dependency in the common-core group.

What it doesn't change

  • JsonFormatter and JsonRecord stay for Gunicorn access log use.
  • Gunicorn access log format (CLF) is untouched.

Migration guide for flagsmith/flagsmith

1. Replace the LOGGING dict in settings/common.py

# Remove the entire LOGGING = { ... } block (lines ~615-668) and replace with:
LOGGING = {"version": 1, "disable_existing_loggers": False}

Django's dictConfig(LOGGING) call during django.setup() becomes a no-op.

2. Set APPLICATION_LOGGERS env var

APPLICATION_LOGGERS=app,features,integrations,task_processor,app_analytics,webhooks

This ensures app loggers are at the correct level from boot.

3. Delete api/util/logging.py

It duplicates JsonFormatter which now lives in common.core.logging.

@khvn26 khvn26 requested a review from a team as a code owner March 13, 2026 19:28
@khvn26 khvn26 requested review from Zaimwa9 and removed request for a team March 13, 2026 19:28
@codecov-commenter
Copy link

codecov-commenter commented Mar 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.36%. Comparing base (398c83c) to head (ca49486).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #179      +/-   ##
==========================================
+ Coverage   96.12%   96.36%   +0.24%     
==========================================
  Files          92       96       +4     
  Lines        3222     3441     +219     
==========================================
+ Hits         3097     3316     +219     
  Misses        125      125              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logging improvements

2 participants