Skip to content

fix(logging): log warnings without a traceback - #201

Merged
dimoschi merged 4 commits into
mainfrom
fix/member-not-found-log-noise
Oct 6, 2026
Merged

dimoschi merged 4 commits into
mainfrom
fix/member-not-found-log-noise

Conversation

@dimoschi

@dimoschi dimoschi commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Types of changes

  • Bugfix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality not to work as expected).
  • Documentation Update (if none of the other choices applies).

Proposed changes

Warnings no longer log a traceback. A warning is a handled condition, so a traceback only buries real errors. Errors keep their traceback, because it makes issues easier to resolve.

This started from the bot's startup log. On every start, the scheduled tasks re-schedule unbans and unmutes for users who left the guild. Each one logged Could not find guild member at WARNING with a full NotFound 10007 Unknown Member traceback, roughly 80 per start.

  • Every logger.warning call in src/ that passed exc_info drops it: 7 in src/bot.py, 6 in src/helpers/ban.py, 1 in src/services/role_manager.py. Levels and messages are unchanged. except ... as exc bindings that are now unused are removed.
  • The dynamic role reload warning in role_manager.py had only the traceback to say what failed, so its message now ends with the exception text.
  • tests/src/test_logging_rules.py parses src/ and fails if any logger.warning call passes exc_info or stack_info, so the rule holds for new code.
  • Small fixes pre-commit flagged in the touched files: two f-strings without placeholders, and import order.

Checklist

  • I have read and followed the CONTRIBUTING.md
    doc.
  • Lint and unit tests pass locally with my changes.
  • I have added the necessary documentation (if appropriate).

Additional context

New tests:

  • tests/src/test_bot.py: get_member_or_user, each branch's return value, level, message, and whether a traceback is attached (WARNING never, ERROR always).
  • tests/src/services/test_role_manager.py: a failed reload keeps the cache and logs the cause without a traceback.
  • tests/src/test_logging_rules.py: the rule above. It failed with 14 call sites before the change.

Full suite: 328 passed.

A member who left the guild is an expected case in get_member_or_user, and the code falls back to the user lookup. It logged a full traceback at WARNING, which produced dozens of tracebacks on every start when scheduled unbans and unmutes were re-created. It now logs one DEBUG line with the id. Forbidden, HTTP errors and a missing user still log with the traceback. The user lookup messages now say user instead of guild member.
@dimoschi
dimoschi requested a review from makelarisjr as a code owner October 5, 2026 14:43
@codecov

codecov Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.65517% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.64%. Comparing base (99fe0e8) to head (7e72604).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/bot.py 81.25% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #201      +/-   ##
==========================================
- Coverage   67.20%   66.64%   -0.56%     
==========================================
  Files          74       76       +2     
  Lines        3436     3586     +150     
==========================================
+ Hits         2309     2390      +81     
- Misses       1127     1196      +69     

☔ 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.

The level stays as it was. Only the traceback goes.
A warning is a handled condition, so a traceback only buries real errors. No logger.warning call in src/ passes exc_info any more, and a test fails if one does. Errors keep their traceback.

The dynamic role reload warning had only the traceback to explain what failed, so its message now includes the exception text.
@dimoschi dimoschi changed the title fix(bot): log a missing guild member without a traceback fix(logging): log warnings without a traceback Oct 5, 2026

@ToxicBiohazard ToxicBiohazard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this. The ~80 NotFound tracebacks on every startup are real noise, and "no traceback for warnings, keep it for errors" makes sense to me. The AST test is a nice way to keep it that way, and good catch on the alembic fileConfig disabling the loggers.

Two things I'd like changed before merging:

  1. The HTTPException warnings in ban.py now don't tell us what actually went wrong. Those aren't routine like a member leaving, so we still need the cause in the log.
  2. The message renames in get_member_or_user were only done in one of the two fallback branches.

The rest are small nits.

Comment thread src/helpers/ban.py Outdated
Comment thread src/helpers/ban.py Outdated
f"them..."
)
except HTTPException:
logger.warning(f"HTTPException when trying to unban user with ID {member.id}")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same problem as the ban HTTPException at line 361. If the DM fails, we don't know which Discord error it was. Can we add : {exc} here too (with except HTTPException as exc:)?

Also this says "unban" but it's the DM sent before a ban. Not from this PR, but could you fix it while you're on this line?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 7e72604. Added the cause and fixed the wording: HTTPException when trying to DM user with ID {id} about their ban: {exc}.

Comment thread src/helpers/ban.py Outdated
Comment thread src/bot.py Outdated
Comment thread tests/src/test_logging_rules.py
…okup wording

The ban, ban DM and infraction DM warnings now end with the Discord error (status, reason and error code), so the cause is logged without a traceback. The ban DM warning also said unban; it now says what failed.

The user fallback after an HTTPException on the member lookup now uses the same messages as the fallback after NotFound.

@ToxicBiohazard ToxicBiohazard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, thanks!

@dimoschi
dimoschi merged commit 5e9a1c3 into main Oct 6, 2026
4 checks passed
@dimoschi
dimoschi deleted the fix/member-not-found-log-noise branch October 6, 2026 09:31
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