Skip to content

fix: telemetry recording on corrupt entries and exception log level - #28

Open
emiliano-go wants to merge 5 commits into
redis:mainfrom
emiliano-go:fix/telemetry-data-integrity
Open

emiliano-go wants to merge 5 commits into
redis:mainfrom
emiliano-go:fix/telemetry-data-integrity

Conversation

@emiliano-go

Copy link
Copy Markdown
Contributor

Changes

Bug: Corrupt cache entry records double telemetry (hit + miss)

record_cache_request(result="hit") and the span cache.hit attribute were
emitted before deserializing the cached response. When the entry had
corrupt JSON, the exception was caught, execution fell through to the MISS
path, and a second metric was recorded.

Fix: Deserialize first, then emit telemetry only on success. If
deserialization fails only a single "miss" metric is recorded.

Bug: Swallowed telemetry exceptions logged at DEBUG level

OpenTelemetry metric helpers (record_cache_request, record_cache_eviction,
record_cache_write, record_cache_latency) swallowed all exceptions at
logger.debug(...), making OTel errors invisible in production without
debug logging enabled.

Fix: Changed all four handlers to logger.warning(...).

@tishun tishun added needs-triage The team needs to go through the provided information and analyse it and removed needs-triage The team needs to go through the provided information and analyse it labels Aug 19, 2026

@tishun tishun left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thanks for the contribution!

Can you also make sure you run uv run nox to make sure lint/format/mypy cleaned up

Comment thread src/redis_fastapi/telemetry.py Outdated
Comment thread tests/unit/test_edge_cases.py Outdated
@emiliano-go

Copy link
Copy Markdown
Contributor Author

Willco!

Address tishun's review on PR redis#28:
- Route all telemetry metric failures through a log-once pattern:
  the first failure is surfaced as a WARNING, repeats fall back to
  DEBUG to avoid log spam.
- Apply the same handling to rate-limit telemetry.
- Replace weak tests with real regression tests: corrupt entry records
  exactly one miss (never hit) and the cache.get span never sets
  cache.hit True; metric failures log one WARNING then DEBUG.
@emiliano-go
emiliano-go force-pushed the fix/telemetry-data-integrity branch from 382135e to 9ea0e8d Compare August 20, 2026 19:18
@emiliano-go

Copy link
Copy Markdown
Contributor Author

Log-once pattern: all telemetry recording failures are now routed through a single mechanism (_warn_once), the first failure surfaces as a WARNING, and repeats fall back to DEBUG so operators notice the problem without log spam. This applies to the cache metrics and the rate-limit metrics (record_rate_limit_request/record_rate_limit_latency), which previously only logged at DEBUG.

Tests rewritten as real regression tests: instead of tests that passed without the fix, the suite now has genuine regression coverage:

  • corrupt entry records exactly one metric (a miss, never a hit) via a spy on record_cache_request;
  • a recording-span stand-in asserts the cache.get span's cache.hit attribute is only ever set to False (never True → False) on a corrupt entry;
  • forced metric-instrument failures assert exactly one WARNING followed by DEBUG on repeat failures, for both cache and rate-limit paths.

Also fixed the pre-existing lint failures (unused/unsorted imports) and the Python 3.10 module-shadowing issue in the tests by patching via importlib.

@emiliano-go
emiliano-go requested a review from tishun August 20, 2026 19:22
@codecov-commenter

codecov-commenter commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.16%. Comparing base (2fa5d16) to head (b9a56c9).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #28      +/-   ##
==========================================
+ Coverage   96.78%   97.16%   +0.38%     
==========================================
  Files          12       12              
  Lines        1214     1271      +57     
==========================================
+ Hits         1175     1235      +60     
+ Misses         39       36       -3     
Flag Coverage Δ
integration 77.41% <30.00%> (-0.59%) ⬇️
unit 94.02% <100.00%> (+0.69%) ⬆️

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.

Parametrize the telemetry log-once regression test across all six
metric helpers (cache request/eviction/write/latency and rate-limit
request/latency), asserting exactly one WARNING on the first failure
and DEBUG on repeats. This also covers record_rate_limit_latency,
which Codecov flagged as the single uncovered line in telemetry.py.
- Change except clause from (json.JSONDecodeError, KeyError) to Exception
  in cache-hit path so TypeError, AttributeError, and other exceptions
  from corrupt entries are caught gracefully
- Prevents 500 errors when binary garbage or partial JSON is stored in Redis
- Add tests for corrupt entry recovery with binary data and non-JSON strings
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.

3 participants