Skip to content

gh-132502: Prototyping adding timestamps to tracebacks. #129337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 60 commits into
base: main
Choose a base branch
from

Conversation

gpshead
Copy link
Member

@gpshead gpshead commented Jan 27, 2025

The idea for this came up at work with @njsmith tossing the idea out as "dumb" yet still maybe useful... Why? to make debugging what happened in async servers with lots of exception groups and exceptions easier. Event timestamps reported on everything when emitting exception groups containing tracebacks often with their own nested causes would allow some semblance of order to be more readily understood and correlated with other parts of the distributed system.

This draft PR is a demo. If we want such a feature, we should settle on semantics in a Discuss thread and if necessary, write it up as a PEP. This should be simpler than exception notes (PEP-678) was. One thought was just to store the timestamp as a note; but that'd involve string and list creation on every exception - slow.

Demo

± PYTHON_TRACEBACK_TIMESTAMPS=iso ../b/python
Python 3.14.0a4+ (heads/traceback-timestamps-dirty:b06539429ef, Feb  1 2025, 17:54:53) [Clang 18.1.3 (1ubuntu1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def california_raisin():
...     try:
...         raise RuntimeError("not enough sunshine")
...     except Exception:
...         raise OSError(2, "on a cloudy day")
...
>>> california_raisin()
Traceback (most recent call last):
  File "<python-input-0>", line 3, in california_raisin
    raise RuntimeError("not enough sunshine")
RuntimeError: not enough sunshine <@2025-02-01T20:43:01.026169>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    california_raisin()
    ~~~~~~~~~~~~~~~~~^^
  File "<python-input-0>", line 5, in california_raisin
    raise OSError(2, "on a cloudy day")
FileNotFoundError: [Errno 2] on a cloudy day <@2025-02-01T20:43:01.026176Z>
>>>

A real world demo involving exception groups in an async application would be more interesting but isn't something I can just tap out in a repl...

Updates: [edits]

I've done performance testing. It now appears to be a no-op (no meaningful regression) as desired performance wise on Linux. For that to be true, I had to add the one special case I suspected might matter: Don't collect the timestamp on StopIteration and AsyncStopIteration as those are not infrequent error exceptions, but a normal part of application control flow. Without that, one of the async pyperformance benchmarks showed a significant performance hit of over 10%.

I've changed it to not emit the timestamps by default. If you set the PYTHON_TRACEBACK_TIMESTAMPS= environment variable to one of either us or 1, ns, or iso, timestamps will be enabled in traceback module display output. See the documentation in the PR.

TODO

  • Fix the reference leak crash in iso mode. Or decide iso is too complicated and simplify by ripping it out?
  • macOS performance regression testing.
  • Windows performance regression testing.
  • Fix the 32-bit build test_sys exception struct size failures.
  • Tests needed:
    • I doubt the existing test suite passes if that environment variable is set?
    • Specifically test pickle and unpickle of all existing exception types in our heirarchy.
    • Test user derived class exception types from each of BaseException, Exception, OSError, ImportError, AttributeError to have the expected attributes and to survive pickle dump and load with the timestamp intact.
    • Test that the timestamp shows up when enabled on everything but StopIteration and AsyncStopIteration.
  • Can I have a PONY?

This came up at work as a suggestion to make debugging what happened in
big async servers with lots of exception groups and exceptions easier.
Timestamps when emitting exception groups containing tracebacks often
with their own nested causes would allow some semblance of order to be
understood.

This is a demo.  If we want such a feature, we should settle on
semantics in a Discuss thread and write it up as a PEP.  This should be
simpler than exception notes (PEP-678) was.  One thought was just to
store the timestamp as a note; but that'd involve string and list
creation on every exception.

Performance testing needs to be done. This is the kind of thing that is
visually distracting, so not all applications want to _see_ the
timestamps.  A knob to turn that on for those who do seems more useful
rather than making that the default.  But the performance impact of
merely collecting the timestamps is worth knowing.
Avoids a 15% regression in the pyperformance async_generators suite.
Tested with `PYTHON_TRACEBACK_TIMESTAMPS=ns` set.

First pass.  Further review could rework some of these changes.

Explicit tests for the new feature have yet to be added.
@gpshead gpshead force-pushed the traceback-timestamps branch from 6c85054 to 53b5500 Compare February 10, 2025 08:04
Better docs, improved tests.

Claude Code using Sonnet 3.7 helped with this, but that was a bit of a battle
as our CPython code context size for this type of change is huge.
TODO: performance testing - this increases the conditional load on every
BaseException instantiation with that interp->config.field && field[0] check.

If needed, we could cache the "collect or not" bool in a static global as it is
fair to say this is a process wide setting rather than per interpreter, but ugh.
gpshead and others added 3 commits April 13, 2025 22:32
Use regex assertions with multi-line mode to match end of lines instead of
literal newline characters. This allows the tests to pass on Windows which
uses \r\n line endings instead of Unix \n line endings.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gpshead gpshead added the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Apr 14, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @gpshead for commit b268c82 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F129337%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Apr 14, 2025
@gpshead gpshead changed the title Proof of concept: Add timestamps to tracebacks. gh-132502: Prototyping adding timestamps to tracebacks. Apr 14, 2025
gpshead and others added 5 commits May 24, 2025 05:08
Resolves conflicts by integrating traceback timestamp functionality with
the new colorization system and maintaining timestamp regex patterns in tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Update test_wsgiref, test_pdb, and test_remote_pdb to handle timestamp
suffixes in exception messages when PYTHON_TRACEBACK_TIMESTAMPS is set.

- test_wsgiref: Use traceback.strip_exc_timestamps() before comparing
  error messages in validation tests
- test_pdb: Update doctest expected output to use ellipsis for timestamp
  matching in await support test
- test_remote_pdb: Strip timestamps from stdout before comparison in
  do_test method

All tests now pass both with and without timestamp functionality enabled.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implements the missing tests identified in PR python#129337 TODO section:
- Test pickle/unpickle of all built-in exception types in hierarchy
- Test user-derived exception classes from BaseException, Exception, OSError, ImportError, AttributeError
- Test timestamp presence on all exception types except StopIteration and StopAsyncIteration

Reorganizes tests into a proper package structure with specialized test modules:
- test_basic.py: Original basic functionality tests
- test_pickle.py: Exception pickle/unpickle preservation tests
- test_user_exceptions.py: Custom exception class tests with inheritance validation
- test_timestamp_presence.py: Timestamp behavior verification across all exception types

All tests validate behavior both with and without timestamp feature enabled,
ensuring proper functionality and performance optimizations for StopIteration/StopAsyncIteration.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Create shared_utils.py with common exception creation logic
- Consolidate duplicate code across test_pickle.py, test_timestamp_presence.py, and test_user_exceptions.py
- Embed shared functions directly in subprocess test scripts to avoid import issues
- Reduce overall test code by ~400 lines while preserving functionality
- All 25 tests pass both with and without timestamps enabled

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gpshead gpshead added the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label May 24, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @gpshead for commit 4aaa4dc 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F129337%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label May 24, 2025
gpshead and others added 4 commits May 24, 2025 23:41
When traceback timestamps are disabled, exception pickles no longer
include an empty state dictionary, reducing pickle size to match
Python 3.13 baseline. When timestamps are enabled, the state dict
is included with timestamp data.

- BaseException: Only include dict when timestamp > 0 or custom attributes exist
- OSError: Apply same optimization while preserving filename attributes
- ImportError: Conditionally include state based on meaningful attributes
- AttributeError: Always include state dict for Python 3.13 compatibility

Results:
- ValueError/RuntimeError: 53 bytes (disabled) -> 103 bytes (enabled)
- OSError: 56 bytes (disabled) -> 106 bytes (enabled)
- AttributeError: 76 bytes (disabled) -> 120 bytes (enabled)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gpshead gpshead self-assigned this Jun 8, 2025
gpshead and others added 2 commits June 8, 2025 11:36
- Include BaseException and Exception in pickle tests by removing unnecessary filtering
- Add user-derived exception classes for ImportError and AttributeError
- Tests now fully cover all built-in exception types and required user-derived classes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gpshead gpshead force-pushed the traceback-timestamps branch from 52554ea to 77ffb5a Compare June 8, 2025 18:37
@gpshead gpshead added the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Jun 8, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @gpshead for commit 77ffb5a 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F129337%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Jun 8, 2025
gpshead and others added 2 commits June 8, 2025 12:30
- Add cross-references between command line flags and environment variables
- Clarify default behavior when PYTHON_TRACEBACK_TIMESTAMPS is unset
- Simplify traceback.rst wording to use "canonical output"
- Fix alphabetical ordering in test_config.py
- Improve comment formatting in test_sys.py for better readability

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
The functionality is already provided by force_color(False) and
force_not_colorized() which were added since this branch started.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
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
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy