Skip to content

fix: log traceback in logger.exception() of Haystack loggers - #13189

Open
hardness1020 wants to merge 2 commits into
deepset-ai:mainfrom
hardness1020:fix/logger-exception-traceback
Open

hardness1020 wants to merge 2 commits into
deepset-ai:mainfrom
hardness1020:fix/logger-exception-traceback

Conversation

@hardness1020

@hardness1020 hardness1020 commented Oct 8, 2026 •

Copy link
Copy Markdown

Related Issues

Proposed Changes:

getLogger wrapped logger.exception with patch_log_method_to_kwargs_only, which always forwards exc_info=None. The stdlib default exc_info=True never applied, so logger.exception(...) logged no traceback in JSON or console output.

  • patch_log_method_to_kwargs_only takes a keyword-only default_exc_info (default None), and exception is wrapped with default_exc_info=True. Explicit exc_info still works, and positional-arg errors still name Logger.exception().
  • PatchedLogger.exception now declares exc_info: Any = True.

How did you test it?

  • New tests in test/test_logging.py: exception() attaches exc_info, and exc_info=False is respected. The traceback test fails without the fix.
  • test_haystack_logger_with_positional_args now checks that the TypeError names the called method.
  • test/test_logging.py passes on Python 3.14 and 3.10. Tests for the 8 modules that call logger.exception pass, except 2 test_type_serialization failures that also fail on main under 3.14 (Union repr).
  • Ran the repro from the issue: JSON has the exception entry, and the console output renders the traceback.
  • hatch run fmt and hatch run test:types pass.

Notes for the reviewer

  • On Python 3.10 the caller line of exception() records stays wrong for plain logging.Logger instances (two wrapper frames), as on main. It goes away once 3.10 is dropped (Drop Python 3.10 support and add Python 3.15 #13065). See the review thread for a single-wrapper variant that fixes it now.
  • Side effects of tracebacks appearing: JSON exc_value is not truncated (same as for stdlib loggers today), and console mode with rich shows locals in tracebacks.

Checklist

  • I have read the contributors guidelines and the code of conduct.
  • I have updated the related issue with new insights and changes.
  • I have added unit tests and updated the docstrings.
  • I've used one of the conventional commit types for my PR title: fix:, feat:, build:, chore:, ci:, docs:, style:, refactor:, perf:, test: and added ! in case the PR includes breaking changes.
  • I have documented my code.
  • I have added a release note file, following the contributors guidelines.
  • I have run pre-commit hooks and fixed any issue.

🤖 Generated with Claude Code

Stop wrapping `exception` in `getLogger`: the wrapper forwarded `exc_info=None`,
so records had no traceback. Stdlib `Logger.exception` already calls the patched
`error` with `exc_info=True`, which also fixes the caller line on Python 3.10.

Fixes deepset-ai#13188

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hardness1020
hardness1020 requested a review from a team as a code owner October 8, 2026 22:26
@hardness1020
hardness1020 requested review from sjrl and removed request for a team October 8, 2026 22:26
@vercel

vercel Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

@hardness1020 is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant

CLAassistant commented Oct 8, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Comment thread haystack/logging.py Outdated
Comment on lines +276 to +277
# `exception` stays unpatched: the stdlib version calls the patched `error` with `exc_info=True`. Wrapping it would
# pass `exc_info=None` and drop the traceback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we keep the wrapper here instead of relying on stdlib Logger.exception delegating to self.error? Without it a positional call raises Logger.error() takes 1 positional argument ..., which is confusing from exception(). Lets give patch_log_method_to_kwargs_only an exc_info default instead:

Suggested change
# `exception` stays unpatched: the stdlib version calls the patched `error` with `exc_info=True`. Wrapping it would
# pass `exc_info=None` and drop the traceback.
logger.exception = patch_log_method_to_kwargs_only(logger.exception, default_exc_info=True) # type: ignore

with exc_info: Any = default_exc_info in the inner wrapper's signature. WDYT?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, done in 40dc64d: patch_log_method_to_kwargs_only takes a keyword-only default_exc_info, and exception passes True. I also pinned the Logger.<method>() name in test_haystack_logger_with_positional_args.

One trade-off: with two wrappers, the caller line is still wrong on Python 3.10 (it points into haystack/logging.py), as on main. #13065 makes that moot. If you want it fixed now, exception can wrap the unpatched error instead, which keeps the exception() name and passes on 3.10:

logger.exception = functools.wraps(logger.exception)(
    patch_log_method_to_kwargs_only(unpatched_error, default_exc_info=True)
)

Happy to switch.

@github-actions github-actions Bot added the type:documentation Improvements on the docs label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack
  logging.py
  haystack/hooks/compaction
  __init__.py
  tool_result_pruning.py
  utils.py
  haystack/hooks/tool_result_offloading
  hooks.py
Project Total  

This report was generated by python-coverage-comment-action

Restore the wrapper so positional-arg errors name `Logger.exception()`, and
give `patch_log_method_to_kwargs_only` a keyword-only `default_exc_info`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

logger.exception() from haystack.logging.getLogger does not log the traceback

3 participants