Skip to content

chore: improve exception logging across the SDK#7358

Open
kausmeows wants to merge 8 commits intomainfrom
fix/full-traceback-opt-in
Open

chore: improve exception logging across the SDK#7358
kausmeows wants to merge 8 commits intomainfrom
fix/full-traceback-opt-in

Conversation

@kausmeows
Copy link
Copy Markdown
Contributor

Summary

  • Replace log_error(f"...{str(e)}") with log_exception("...") in except blocks across the SDK — uses the idiomatic Python pattern for logging errors with tracebacks.
  • Replace log_warning(f"...{str(e)}") with log_warning("...", exc_info=True) in except blocks — stops swallowing exception context.
  • Add AGNO_VERBOSE_EXCEPTIONS env var (opt-in) to control traceback visibility — off by default (clean logs), full tracebacks when set to true.
  • Add set_verbose_exceptions() and configure_agno_logging(enable_verbose_exceptions=...) for programmatic control.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Improvement
  • Model update
  • Other:

Checklist

  • Code complies with style guidelines
  • Ran format/validation scripts (./scripts/format.sh and ./scripts/validate.sh)
  • Self-review completed
  • Documentation updated (comments, docstrings)
  • Examples and guides: Relevant cookbook examples have been included or updated (if applicable)
  • Tested in clean environment
  • Tests added/updated (if applicable)

Duplicate and AI-Generated PR Check

  • I have searched existing open pull requests and confirmed that no other PR already addresses this issue
  • If a similar PR exists, I have explained below why this PR is a better approach
  • Check if this PR was entirely AI-generated (by Copilot, Claude Code, Cursor, etc.)

Additional Notes

Add any important context (deployment instructions, screenshots, security considerations, etc.)

@@ -112,6 +119,10 @@ def build_logger(logger_name: str, source_type: Optional[str] = None) -> Any:
debug_on: bool = False
debug_level: Literal[1, 2] = 1

# Controls whether exc_info tracebacks are rendered in log output.
# Opt-in only: set AGNO_VERBOSE_EXCEPTIONS=true or call set_verbose_exceptions(True).
verbose_exceptions: bool = getenv("AGNO_VERBOSE_EXCEPTIONS", "false").lower() in ("true", "1", "yes")
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.

AGNO_VERBOSE_EXCEPTIONS seems a bit ambiguous since it looks as if its scoped to exceptions only but we cater other logging outputs as well. Wdyt?

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.

yeah that's why this on slack thread to get more opinions on DX-

  • added exc_info=True in log_warning but its gated with a new env variable AGNO_VERBOSE_EXCEPTIONS which is by default False so it strips the exc_info from those logs, if turned itrue it keep it and prints the full traceback.
  • are we happy with this env variable approach or do we rather add some debug_level=3 for this? or some entirely new flag on agent/team/workflow (which does not sound elegant)

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.

We can also rename this to be more self explanatory something like AGNO_LOG_TRACEBACKS

def set_verbose_exceptions(enabled: bool = True) -> None:
"""Enable or disable full tracebacks in log output.

When enabled, ``log_exception`` and ``log_warning`` calls with
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.

Shouldn't the log_exception's exc_info be ideally be True always?

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.

yes, updated so that it is not stripped in case of log_exception

Copy link
Copy Markdown
Contributor

@sannya-singal sannya-singal left a comment

Choose a reason for hiding this comment

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

Thanks for following up on this, nice work! I just have few comments.

)
except Exception as e:
log_warning(f"Knowledge search failed: {e}")
log_warning("Knowledge search failed", exc_info=True)
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.

Settings exc_info=True here is a bit misleading since it depends on the env var

run_context=run_context,
)
except Exception as e:
log_warning(f"Knowledge search failed: {e}")
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.

Now for a simple log warning, user would get less information since we are removing {e}. Instead, we should keep the error statements as before with the option of expanding traceback if necessary

@@ -32,6 +32,18 @@ def __init__(self, *args, source_type: Optional[str] = None, **kwargs):
super().__init__(*args, **kwargs)
self.source_type = source_type

def emit(self, record: logging.LogRecord) -> None:
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.

The emit() override is fine for gating tracebacks behind the env var, but we should keep {e} in the warning messages. Right now the default mode gives users less info than before — e.g. "Knowledge search failed" vs "Knowledge search failed: ConnectionRefused(...)".

Can we do both?

log_warning(f"Knowledge search failed: {e}", exc_info=True)

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