Skip to content

fix(logs): trim log writer redis streams on the target's db_shard - #3953

Open
ryanmelt wants to merge 1 commit into
mainfrom
fix/log-writer-trim-shard
Open

ryanmelt wants to merge 1 commit into
mainfrom
fix/log-writer-trim-shard

Conversation

@ryanmelt

Copy link
Copy Markdown
Member

What

  • Ruby LogWriter: the shard lookup used /__\{?([^}_]+)\}?__/, which on SCOPE__TELEMETRY__{TARGET}__PACKET matches TELEMETRY, not the target. It also always looked up the DEFAULT scope. Added LogWriter.db_shard_for_topic, which reads the {TARGET} hashtag and the scope prefix.
  • Python LogWriter, same fix plus two latent bugs in the same code:
    • it trimmed shard 0 unconditionally
    • cleanup_offsets / last_offsets dicts were iterated without .items(), so any queued cleanup would raise
    • hourly/daily cycling compared utc_now.min (the datetime.min class constant) instead of utc_now.minute, so it could never trigger
  • Moved the Python trim loop into trim_due_cleanups() so it can be tested.

Why

On deployments with more than one Redis db_shard, TELEMETRY__ streams for targets on non-zero shards were never trimmed by the log writer and grew without bound. XTRIM against the wrong shard is a silent no-op. Single-shard deployments are unaffected. The Python LogWriter is currently only used by interface stream logs, which don't record Redis offsets, so the Python dict-iteration bug hasn't been hit in practice.

Testing

  • New openc3/spec/logs/log_writer_spec.rb; bundle exec rspec spec/logs: 60 examples, 0 failures
  • New openc3/python/test/logs/test_log_writer.py (shard lookup, plus close → trim on the correct shard); uv run pytest test/logs: 56 passed; ruff clean

🤖 Generated with Claude Code

The shard lookup regex matched the stream type (TELEMETRY) instead of the
{TARGET} hashtag and ignored scope, so on multi-shard deployments target
streams outside shard 0 were never trimmed by the log writer. Python also
iterated offset dicts without .items() and used datetime.min for minutes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ryanmelt
ryanmelt force-pushed the fix/log-writer-trim-shard branch from 6453ef4 to f44bd4d Compare September 28, 2026 00:42
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.14%. Comparing base (688f928) to head (f44bd4d).

Files with missing lines Patch % Lines
openc3/lib/openc3/logs/log_writer.rb 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3953      +/-   ##
==========================================
+ Coverage   80.08%   80.14%   +0.06%     
==========================================
  Files         901      901              
  Lines       68356    68368      +12     
  Branches     2645     2645              
==========================================
+ Hits        54743    54796      +53     
+ Misses      12946    12910      -36     
+ Partials      667      662       -5     
Flag Coverage Δ
frontend 67.00% <ø> (+0.04%) ⬆️
python 80.19% <ø> (+0.06%) ⬆️
ruby-api 82.41% <ø> (+0.40%) ⬆️
ruby-backend 85.66% <80.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

# Returns the Redis db_shard holding a target stream such as
# SCOPE__TELEMETRY__{TARGET}__PACKET, or 0 if no target can be determined
def self.db_shard_for_topic(redis_topic)
target_match = redis_topic.match(/\{([^}]+)\}/)

This branch has not been deployed

No deployments
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.

2 participants