Skip to content

Releases: hynek/structlog

25.4.0

02 Jun 08:20
25.4.0
d38385c
Compare
Choose a tag to compare

Highlights

The main feature is support for exception groups we stole adapted from Rich, however the main reason for this release at this point in time are backwards-incompatible changes in the upcoming Python 3.13.4. Update structlog before updating Python, if you use structlog.stdlib.filter_by_level().

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), Klaviyo (@klaviyo), Privacy Solutions GmbH (@privacy-solutions), FilePreviews (@filepreviews), Doist (@Doist), nate nowack (@zzstoatzz), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Buttondown (@buttondown), Christopher Dignam (@chdsbd), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Polar (@polarsource), Mike Fiedler (@miketheman), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), Pieter Swinkels (@swinkels), Nick Libertini (@libertininick), Brian M. Dennis (@crossjam), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), The Westervelt Company (@westerveltco), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Thomas Klinger (@thmsklngr), Andreas Poehlmann (@ap--), August Trapper Bigelow (@atbigelow), Carlton Gibson (@carltongibson), and Roboflow (@roboflow).

Not to forget 14 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • Support for Python 3.14 and Python 3.13.4.

    Python 3.14 has an backwards-incompatible change to logging.Logger.isEnabledFor() (it now always returns False if a log entry is in flight) that has been backported to 3.13.4 (expected on 2025-06-03). It mainly affects structlog.stdlib.filter_by_level(). #723

  • structlog.tracebacks now handles exception groups. structlog.tracebacks.Stack has two new fields, is_group: bool and exceptions: list[Trace]. This works similarly to what Rich v14.0.0 does. #720

Fixed

  • structlog.processors.ExceptionPrettyPrinter now respects the exception_formatter arguments instead of always using the default formatter. #724

This release contains contributions from @anujdas, @hynek, and @sscherfke.

Artifact Attestations

You can verify this release's artifact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:

$ gh attestation verify --owner hynek structlog-25.4.0.tar.gz

and

$ gh attestation verify --owner hynek structlog-25.4.0-py3-none-any.whl

25.3.0

25 Apr 15:59
25.3.0
edfa953
Compare
Choose a tag to compare

Highlights

This fixes a rather ugly bug where seemingly UTC timestamps in TimeStamper had the timestamp from the local timezone when passing utc=True.

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), Klaviyo (@klaviyo), Privacy Solutions GmbH (@privacy-solutions), Andreas Jung (@zopyx), Ecosystems (@ecosyste-ms), FilePreviews (@filepreviews), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Buttondown (@buttondown), Christopher Dignam (@chdsbd), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Polar (@polarsource), Mike Fiedler (@miketheman), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), Pieter Swinkels (@swinkels), Nick Libertini (@libertininick), Brian M. Dennis (@crossjam), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), The Westervelt Company (@westerveltco), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Thomas Klinger (@thmsklngr), Andreas Poehlmann (@ap--), August Trapper Bigelow (@atbigelow), Carlton Gibson (@carltongibson), and Roboflow (@roboflow).

Not to forget 15 more amazing humans who chose to be generous but anonymous!

Full Changelog

Fixed

  • structlog.processors.TimeStamper now again uses timestamps using UTC for custom format strings when utc=True. #713

This release contains contributions from @hynek, and @m-endra.

Artifact Attestations

You can verify this release's artifact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:

$ gh attestation verify --owner hynek structlog-25.3.0.tar.gz

and

$ gh attestation verify --owner hynek structlog-25.3.0-py3-none-any.whl

25.2.0

11 Mar 17:40
25.2.0
e948850
Compare
Choose a tag to compare

Highlights

Quick release before my travel frenzy! It seems like the boring fix to type hints of bind() et al is a fan favorite, though.

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), Ecosystems (@ecosyste-ms), Klaviyo (@klaviyo), Privacy Solutions GmbH (@privacy-solutions), FilePreviews (@filepreviews), nate nowack (@zzstoatzz), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Buttondown (@buttondown), Christopher Dignam (@chdsbd), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Polar (@polarsource), Mike Fiedler (@miketheman), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), Pieter Swinkels (@swinkels), Nick Libertini (@libertininick), Brian M. Dennis (@crossjam), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), The Westervelt Company (@westerveltco), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Thomas Klinger (@thmsklngr), Andreas Poehlmann (@ap--), August Trapper Bigelow (@atbigelow), Carlton Gibson (@carltongibson), and Roboflow (@roboflow).

Not to forget 14 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • structlog.tracebacks.Stack now includes an exc_notes field reflecting the notes attached to the exception. #684

Changed

  • structlog.stdlib.BoundLogger's binding-related methods now also return Self. #694

  • structlog.processors.TimeStamper now produces internally timezone-aware datetime objects. Default output hasn't changed, but you can now use %z in your fmt string. #709

Fixed

  • Expose structlog.dev.RichTracebackFormatter for imports. #699
  • Expose structlog.processors.LogfmtRenderer for imports. #701

This release contains contributions from @camillol, @hynek, @k4nar, @keongalvin, and @ttrei.

Artifact Attestations

You can verify this release's artifact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:

$ gh attestation verify --owner hynek structlog-25.2.0.tar.gz

and

$ gh attestation verify --owner hynek structlog-25.2.0-py3-none-any.whl

25.1.0

16 Jan 13:03
25.1.0
a38a5ac
Compare
Choose a tag to compare

Highlights

Lots of updates to exception handling that I hope will stabilize a bit now.

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), Klaviyo (@klaviyo), FilePreviews (@filepreviews), Privacy Solutions GmbH (@privacy-solutions), Gedankenspieler (@Gedankenspieler), Daniel Fortunov (@asqui), Kevin P. Fleming (@kpfleming), and Polar (@polarsource).

Maintenance Sustainers

Buttondown (@buttondown), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Chris Withers (@cjw296), Mike Fiedler (@miketheman), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), Pieter Swinkels (@swinkels), Nick Libertini (@libertininick), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), The Westervelt Company (@westerveltco), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Thomas Klinger (@thmsklngr), Andreas Poehlmann (@ap--), August Bigelow (@atbigelow), Carlton Gibson (@carltongibson), and Roboflow (@roboflow).

Not to forget 11 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • Add structlog.stdlib.render_to_log_args_and_kwargs processor. Same as structlog.stdlib.render_to_log_kwargs, but also allows to pass positional arguments to logging. With it, you do not need to add structlog.stdlib.PositionalArgumentsFormatter processor to format positional arguments from structlog loggers. #668

  • Native loggers now have is_enabled_for() and get_effective_level() methods that mirror the behavior of the standard library's logging.Logger.isEnabledFor() and logging.Logger.getEffectiveLevel(). #689

Changed

  • structlog.typing.BindableLogger protocol now returns Self instead of BindableLogger. This adds a dependency on typing-extensions for Pythons older than 3.11. #642 #659

  • structlog.dev.ConsoleRenderer will quote string value with special characters. #647

  • structlog.stdlib.recreate_defaults() now also adds structlog.stdlib.PositionalArgumentsFormatter. In default native mode, this is done by the loggers at the edge.

  • structlog.make_filtering_bound_logger() now also accepts a string for min_level.

Fixed

  • Fix handling calls to {logger}.exception() outside of exception blocks. Depending on the structlog configuration, this either resulted in an event dict key exception: "MISSING" or lead to an error. Now, an invalid or missing exc_info will just be ignored. This means, that calling {logger}.exception() outside of an exception block is basically the same as calling {logger}.error(). #634 #680

  • Instantiating structlog.dev.ConsoleRenderer does not mutate the passed styles dict anymore. #669

  • The native FilteringBoundLogger.fatal() method now maps to the critical level, as it does in the standard library. Note that the level is discouraged to use there, so we recommend to stick to error() or critical(). #677

  • structlog.tracebacks.ExceptionDictTransformer now actually accepts None for locals_max_length and locals_max_string. #675


This release contains contributions from @aThorp96, @brcsw, @denis-savran, @emmanuel-ferdman, @hynek, @kain88-de, @Sh4pe, @sscherfke, @Tinche, @trim21, and @yaelmi3.

Artifact Attestations

You can verify this release's artifact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:

$ gh attestation verify --owner hynek structlog-25.1.0.tar.gz

and

$ gh attestation verify --owner hynek structlog-25.1.0-py3-none-any.whl

24.4.0

17 Jul 12:37
24.4.0
42fca8c
Compare
Choose a tag to compare

Highlights

This is just a docs / PyPI README update. No code changes whatsoever.

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Klaviyo (@klaviyo), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Adam Hill (@adamghill), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Mike Fiedler (@miketheman), Thomas Klinger (@thmsklngr), Duncan Hill (@cricalix), and Colin Marquardt (@cmarqu).

Not to forget 7 more amazing humans who chose to be generous but anonymous!

Full Changelog

Changed

No code changes since 24.3.0

Artifact Attestations

You can verify this release's artififact attestions using GitHub's CLI tool by downloading the sdist and wheel from PyPI and running:

$ gh attestation verify --owner hynek structlog-24.4.0.tar.gz

and

$ gh attestation verify --owner hynek structlog-24.4.0-py3-none-any.whl

24.3.0

17 Jul 11:18
24.3.0
320e61a
Compare
Choose a tag to compare

Highlights

This is just a quick release so I can focus on my other projects. But do enjoy the improved traceback dict rendering and log level handling in testing!

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Klaviyo (@klaviyo), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Adam Hill (@adamghill), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Mike Fiedler (@miketheman), Thomas Klinger (@thmsklngr), Duncan Hill (@cricalix), and Colin Marquardt (@cmarqu).

Not to forget 7 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • Restore feature parity between structlog.traceback.ExceptionDictTransformer and Rich's traceback extractor:

    • When displaying locals, use Rich for formatting if it is available.
    • When displaying locals, call repr() on strings, too (improves handling of SecretStr implementations).
    • Add locals_max_length config option
    • Add locals_hide_sunder config option
    • Add locals_hide_dunder config option
    • Add suppress config option

    #627

Changed

  • structlog.testing.capture_logs() now maps the exception log level to error (as it's elsewhere). #628

24.2.0

27 May 21:42
24.2.0
78729a8
Compare
Choose a tag to compare

Highlights

Overdue, and mostly bug fixes & optimizations! See y'all after my vacation. 🌴

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Klaviyo (@klaviyo), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Mike Fiedler (@miketheman), Thomas Klinger (@thmsklngr), Duncan Hill (@cricalix), and Colin Marquardt (@cmarqu).

Not to forget 7 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • It is now possible to disable log level-padding in structlog.dev.LogLevelColumnFormatter and structlog.dev.ConsoleRenderer. #599

  • The structlog.processors.CallsiteParameterAdder can now be pickled. #603

  • structlog.processors.CallsiteParameterAdder now also works with structlog.stdlib.BoundLogger's non-standard async methods (ainfo(), and so forth) #618

Changed

  • structlog.processors.LogfmtRenderer now escapes newlines. #592

  • structlog.processors.LogfmtRenderer now escapes backslashes and double quotes. #594

  • structlog.processors.CallsiteParameterAdder has been optimized to be about 2x faster. #606

Fixed

  • structlog.stdlib.render_to_log_kwargs now correctly passes stacklevel as a kwarg to stdlib logging. #619

24.1.0

08 Jan 09:51
24.1.0
6f3fc33
Compare
Choose a tag to compare

Highlights

This quick bugfix release fixes two regressions and the fact that RichTracebackFormatter has been ignoring its width argument the whole time.

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Daniel Fortunov (@asqui), Kevin P. Fleming (@kpfleming), and Sören Weber (@SoerenWeber).

Maintenance Sustainers

Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), and Mike Fiedler (@miketheman).

Not to forget 6 more amazing humans who chose to be generous but anonymous!

Full Changelog

Fixed

  • The lazy logger proxy returned by structlog.get_logger() now returns its initial values when asked for context. When asked for context before binding for the first time, it returned an empty dictionary in 23.3.0.

  • The displayed level name when using structlog.stdlib.BoundLogger.exception() is "error" instead of "exception". Fixes regression in 23.3.0. #584

  • Don't ignore the width argument of RichTracebackFormatter. #587

23.3.0

29 Dec 14:01
23.3.0
45ba191
Compare
Choose a tag to compare

Highlights

The highlight is the configurability of structlog.dev.ConsoleRenderer's output (check out https://www.structlog.org/en/stable/console-output.html#console-output-configuration!) and structlog.processors.CallsiteParameterAdder getting asyncio support.

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), FilePreviews (@filepreviews), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), and Mike Fiedler (@miketheman).

Not to forget 6 more amazing humans who chose to be generous but anonymous!

Full Changelog

Added

  • The colorful development logger is now even more configurable! Choose freely your colors and the order of the key-value pairs! Implement your own formatters for certain keys!

    Implementing the output on top of the new columns API has changed the default very slightly, but shouldn't be noticeable. #577

  • Async log methods (those starting with an a) now also support the collection of callsite information using structlog.processors.CallsiteParameterAdder. #565

Changed

  • structlog.stdlib.recreate_defaults() now also adds structlog.stdlib.add_logger_name to the processors. Check out the updated screenshot!

Fixed

  • The return value from get_logger() (a BoundLoggerLazyProxy) now passes isinstance-checks against structlog.typing.BindableLogger on Python 3.12. #561

  • structlog.threadlocal.tmp_bind() now also works with BoundLoggerLazyProxy (in other words: before anything is bound to a bound logger).

  • stdlib: ProcessorFormatter can now be told to not render the log record message using getMessage and just str(record.msg) instead. #550

  • stdlib: structlog.stdlib.BoundLogger.exception()'s handling ofLogRecord.exc_info is now set consistent with logging. #571 #572

23.2.0

09 Oct 14:53
23.2.0
f5cbae4
Compare
Choose a tag to compare

Highlights

Not a super exciting release, but it was time to deliver some fixes and quality-of-life features to the people!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), HiredScore (@HiredScore), FilePreviews (@filepreviews), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Adam Hill (@adamghill), Dan Groshev (@si14), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Moving Content AG (@moving-content), ProteinQure (@ProteinQure), Jesse Snyder (@jessesnyder), Rivo Laks (@rivol), Tom Ballinger (@thomasballinger), Ionel Cristian Mărieș (@ionelmc), The Westervelt Company (@westerveltco), Philippe Galvan (@PhilippeGalvan), Birk Jernström (@birkjernstrom), Tim Schilling (@tim-schilling), Chris Withers (@cjw296), Christopher Dignam (@chdsbd), Stefan Hagen (@sthagen), and Sławomir Ehlert (@slafs).

Not to forget 4 more amazing humans who chose to be generous but anonymous!

Full Changelog

Removed

  • Support for Python 3.7.

Added

  • Official support for Python 3.12. #515

  • structlog.processors.MaybeTimeStamper that only adds a timestamp if there isn't one already. #81

  • structlog.dev.ConsoleRenderer now supports renamed timestamp keys using the timestamp_key parameter. #541

  • structlog.dev.RichTracebackFormatter that allows to configure the traceback formatting. #542

Fixed

  • FilteringBoundLogger.exception() and FilteringBoundLogger.aexception() now support positional argument formatting like the rest of the methods. #531
  • structlog.processors.format_exc_info() and structlog.dev.ConsoleRenderer do not crash anymore when told to format a non-existent exception. #533