Skip to content

Commit af967ed

Browse files
committed
Exclude celery.app.trace from database log storage (v2.6.53)
Per-task INFO rows from celery.app.trace generated heavy WAL volume during maintenance runs, driving PostgreSQL checkpoint IO storms that stalled the producer loops. Added to the default log-exclusion list with an additive startup migration backfilling existing installs.
1 parent 263ff52 commit af967ed

5 files changed

Lines changed: 42 additions & 5 deletions

File tree

CHANGELOG.MD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0).
77

8+
## [2.6.53] - 2026-06-11
9+
10+
### Fixed
11+
12+
- **Maintenance runs no longer trigger 5-minute checkpoint IO storms.** During the verified cleanup run, recurring 2-7 minute slowdowns aligned to the second with PostgreSQL checkpoint write phases. Cause: `celery.app.trace` logs one INFO row per task ("succeeded in Xs" with the full result dict), and the database log handler stored all of them - ~150-190MB of WAL per 5 minutes at ~850 tasks/s, forcing heavy checkpoints that stalled the producer's own DB operations. `celery.app.trace` is now in the default log-exclusion list, and a startup migration appends it to the stored config on existing installs (additive - user customizations survive). Container/Loki logging is unaffected.
13+
814
## [2.6.52] - 2026-06-11
915

1016
### Fixed

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ services:
6363

6464
# PixelProbe application
6565
pixelprobe:
66-
image: ttlequals0/pixelprobe:${PIXELPROBE_VERSION:-2.6.52}
66+
image: ttlequals0/pixelprobe:${PIXELPROBE_VERSION:-2.6.53}
6767
container_name: pixelprobe-app
6868
environment:
6969
# Security
@@ -131,7 +131,7 @@ services:
131131

132132
# P1 Celery Worker for distributed task processing
133133
celery-worker:
134-
image: ttlequals0/pixelprobe:${PIXELPROBE_VERSION:-2.6.52}
134+
image: ttlequals0/pixelprobe:${PIXELPROBE_VERSION:-2.6.53}
135135
container_name: pixelprobe-celery-worker
136136
command: python celery_worker.py
137137
environment:

pixelprobe/constants.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,11 @@
9898
CONFIG_LOG_RETENTION_DAYS = 'log_retention_days'
9999
CONFIG_LOG_EXCLUDE_LOGGERS = 'log_exclude_loggers'
100100

101-
# Default excluded loggers for database log storage
102-
DEFAULT_LOG_EXCLUDE_LOGGERS = 'urllib3,werkzeug,celery.worker.strategy,celery.bootsteps,kombu,amqp'
101+
# Default excluded loggers for database log storage.
102+
# celery.app.trace emits one INFO row per task ("succeeded in Xs" with the
103+
# full result): at ~850 tasks/s during maintenance runs that is ~150MB of WAL
104+
# per 5 minutes, driving checkpoint IO storms that stall the producer loops
105+
DEFAULT_LOG_EXCLUDE_LOGGERS = 'urllib3,werkzeug,celery.worker.strategy,celery.app.trace,celery.bootsteps,kombu,amqp'
103106

104107
# Sentinel value for system (non-scan) logs
105108
SYSTEM_LOG_ID = 'system'

pixelprobe/migrations/startup.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,28 @@ def run_v2_6_49_migrations(db):
317317
logger.error(f"Migration v2.6.49 failed: {e}")
318318

319319

320+
def run_v2_6_53_migrations(db):
321+
"""Append celery.app.trace to the stored log-exclusion list if absent.
322+
323+
The exclude config is seeded once (ON CONFLICT DO NOTHING), so default
324+
changes never reach existing installs. Additive so user customizations
325+
survive. celery.app.trace logs one row per task; at maintenance-run rates
326+
that WAL volume drives 5-minute checkpoint IO storms.
327+
"""
328+
try:
329+
with migration_connection(db) as conn:
330+
conn.execute(text("""
331+
UPDATE app_configs
332+
SET value = value || ',celery.app.trace'
333+
WHERE key = :key
334+
AND ',' || replace(value, ' ', '') || ',' NOT LIKE '%,celery.app.trace,%'
335+
"""), {'key': CONFIG_LOG_EXCLUDE_LOGGERS})
336+
conn.commit()
337+
logger.info("v2.6.53 log-exclusion backfill completed")
338+
except Exception as e:
339+
logger.error(f"Migration v2.6.53 failed: {e}")
340+
341+
320342
def create_performance_indexes(db):
321343
"""Create performance indexes"""
322344
indexes = [
@@ -402,6 +424,12 @@ def _run_all_migrations(db):
402424
except Exception as e:
403425
logger.error(f"v2.6.49 migration failed: {e}")
404426

427+
logger.info("Running v2.6.53 migration (log-exclusion backfill)...")
428+
try:
429+
run_v2_6_53_migrations(db)
430+
except Exception as e:
431+
logger.error(f"v2.6.53 migration failed: {e}")
432+
405433
logger.info("Creating performance indexes...")
406434
try:
407435
create_performance_indexes(db)

pixelprobe/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Default version - this is the single source of truth
55

66

7-
_DEFAULT_VERSION = '2.6.52'
7+
_DEFAULT_VERSION = '2.6.53'
88

99

1010
# Allow override via environment variable for CI/CD, but default to the hardcoded version

0 commit comments

Comments
 (0)