structlog-config 0.6.0__py3-none-any.whl → 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,9 +11,10 @@ from structlog.typing import FilteringBoundLogger
11
11
 
12
12
  from structlog_config.formatters import (
13
13
  PathPrettifier,
14
+ WheneverFormatter,
14
15
  add_fastapi_context,
16
+ beautiful_traceback_exception_formatter,
15
17
  logger_name,
16
- pretty_traceback_exception_formatter,
17
18
  simplify_activemodel_objects,
18
19
  )
19
20
 
@@ -61,12 +62,16 @@ def log_processors_for_mode(json_logger: bool) -> list[structlog.types.Processor
61
62
  structlog.processors.JSONRenderer(serializer=orjson_dumps_sorted),
62
63
  ]
63
64
 
65
+ # Passing None skips the ConsoleRenderer default, so use the explicit dev default.
66
+ exception_formatter = structlog.dev.default_exception_formatter
67
+
68
+ if packages.beautiful_traceback:
69
+ exception_formatter = beautiful_traceback_exception_formatter
70
+
64
71
  return [
65
72
  structlog.dev.ConsoleRenderer(
66
73
  colors=not NO_COLOR,
67
- exception_formatter=pretty_traceback_exception_formatter
68
- if packages.pretty_traceback
69
- else structlog.dev.default_exception_formatter,
74
+ exception_formatter=exception_formatter,
70
75
  )
71
76
  ]
72
77
 
@@ -85,6 +90,7 @@ def get_default_processors(json_logger) -> list[structlog.types.Processor]:
85
90
  if packages.activemodel and packages.typeid
86
91
  else None,
87
92
  PathPrettifier(),
93
+ WheneverFormatter() if packages.whenever else None,
88
94
  structlog.processors.TimeStamper(fmt="iso", utc=True),
89
95
  # add `stack_info=True` to a log and get a `stack` attached to the log
90
96
  structlog.processors.StackInfoRenderer(),
@@ -64,19 +64,20 @@ def logger_name(logger: Any, method_name: Any, event_dict: EventDict) -> EventDi
64
64
  return event_dict
65
65
 
66
66
 
67
- def pretty_traceback_exception_formatter(sio: TextIO, exc_info: ExcInfo) -> None:
67
+ def beautiful_traceback_exception_formatter(sio: TextIO, exc_info: ExcInfo) -> None:
68
68
  """
69
69
  By default, rich and then better-exceptions is used to render exceptions when a ConsoleRenderer is used.
70
70
 
71
- I prefer pretty-traceback, so I've added a custom processor to use it.
71
+ I prefer beautiful-traceback, so I've added a custom processor to use it.
72
72
 
73
73
  https://github.com/hynek/structlog/blob/66e22d261bf493ad2084009ec97c51832fdbb0b9/src/structlog/dev.py#L412
74
74
  """
75
75
 
76
76
  # only available in dev
77
- from pretty_traceback.formatting import exc_to_traceback_str
77
+ from beautiful_traceback.formatting import exc_to_traceback_str
78
78
 
79
79
  _, exc_value, traceback = exc_info
80
+ assert traceback is not None
80
81
  # TODO support local_stack_only env var support
81
82
  formatted_exception = exc_to_traceback_str(exc_value, traceback, color=not NO_COLOR)
82
83
  sio.write("\n" + formatted_exception)
@@ -150,6 +151,26 @@ class RenameField:
150
151
  return event_dict
151
152
 
152
153
 
154
+ class WheneverFormatter:
155
+ """A processor for formatting whenever datetime objects.
156
+
157
+ Changes all whenever datetime objects (ZonedDateTime, Instant, PlainDateTime, etc.)
158
+ from their repr() format (e.g., ZonedDateTime("2025-11-02 00:00:00+00:00[UTC]"))
159
+ to their string format (e.g., 2025-11-02 00:00:00+00:00[UTC]).
160
+
161
+ This provides cleaner log output without the class wrapper.
162
+ """
163
+
164
+ def __call__(self, _, __, event_dict):
165
+ for key, value in event_dict.items():
166
+ # Check if the value has the _pywhenever module attribute
167
+ # This is a reliable way to detect whenever types without importing them
168
+ if hasattr(value, "__module__") and value.__module__.startswith("whenever"):
169
+ event_dict[key] = str(value)
170
+
171
+ return event_dict
172
+
173
+
153
174
  def add_fastapi_context(
154
175
  logger: logging.Logger,
155
176
  method_name: str,
@@ -23,11 +23,16 @@ except ImportError:
23
23
  typeid = None
24
24
 
25
25
  try:
26
- import pretty_traceback
26
+ import beautiful_traceback
27
27
  except ImportError:
28
- pretty_traceback = None
28
+ beautiful_traceback = None
29
29
 
30
30
  try:
31
31
  import starlette_context
32
32
  except ImportError:
33
33
  starlette_context = None
34
+
35
+ try:
36
+ import whenever
37
+ except ImportError:
38
+ whenever = None
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: structlog-config
3
- Version: 0.6.0
3
+ Version: 0.8.0
4
4
  Summary: A comprehensive structlog configuration with sensible defaults for development and production environments, featuring context management, exception formatting, and path prettification.
5
5
  Keywords: logging,structlog,json-logging,structured-logging
6
6
  Author: Michael Bianco
7
7
  Author-email: Michael Bianco <mike@mikebian.co>
8
8
  Requires-Dist: orjson>=3.10.15
9
9
  Requires-Dist: python-decouple-typed>=3.11.0
10
- Requires-Dist: python-ipware>=3.0.0
10
+ Requires-Dist: fastapi-ipware>=0.1.1
11
11
  Requires-Dist: structlog>=25.2.0
12
12
  Requires-Dist: fastapi-ipware>=0.1.0 ; extra == 'fastapi'
13
13
  Requires-Python: >=3.11
@@ -120,6 +120,64 @@ For example, if you wanted to [mimic `OPENAI_LOG` functionality](https://github.
120
120
  * `LOG_LEVEL_HTTPX=DEBUG`
121
121
  * `LOG_PATH_HTTPX=tmp/openai.log`
122
122
 
123
+ ## Custom Formatters
124
+
125
+ This package includes several custom formatters that automatically clean up log output:
126
+
127
+ ### Path Prettifier
128
+
129
+ Automatically formats `pathlib.Path` and `PosixPath` objects to show relative paths when possible, removing the wrapper class names:
130
+
131
+ ```python
132
+ from pathlib import Path
133
+ log.info("Processing file", file_path=Path.cwd() / "data" / "users.csv")
134
+ # Output: file_path=data/users.csv (instead of PosixPath('/home/user/data/users.csv'))
135
+ ```
136
+
137
+ ### Whenever Datetime Formatter
138
+
139
+ **Note:** Requires `pip install whenever` to be installed.
140
+
141
+ Formats [whenever](https://github.com/ariebovenberg/whenever) datetime objects without their class wrappers for cleaner output:
142
+
143
+ ```python
144
+ from whenever import ZonedDateTime
145
+
146
+ log.info("Event scheduled", event_time=ZonedDateTime(2025, 11, 2, 0, 0, 0, tz="UTC"))
147
+ # Output: event_time=2025-11-02T00:00:00+00:00[UTC]
148
+ # Instead of: event_time=ZonedDateTime("2025-11-02T00:00:00+00:00[UTC]")
149
+ ```
150
+
151
+ Supports all whenever datetime types: `ZonedDateTime`, `Instant`, `LocalDateTime`, `PlainDateTime`, etc.
152
+
153
+ ### ActiveModel Object Formatter
154
+
155
+ **Note:** Requires `pip install activemodel` and `pip install typeid-python` to be installed.
156
+
157
+ Automatically converts [ActiveModel](https://github.com/iloveitaly/activemodel) BaseModel instances to their ID representation and TypeID objects to strings:
158
+
159
+ ```python
160
+ from activemodel import BaseModel
161
+
162
+ user = User(id="user_123", name="Alice")
163
+ log.info("User action", user=user)
164
+ # Output: user_id=user_123 (instead of full object representation)
165
+ ```
166
+
167
+ ### FastAPI Context
168
+
169
+ **Note:** Requires `pip install starlette-context` to be installed.
170
+
171
+ Automatically includes all context data from [starlette-context](https://github.com/tomwojcik/starlette-context) in your logs, useful for request tracing:
172
+
173
+ ```python
174
+ # Context data (request_id, correlation_id, etc.) automatically included in all logs
175
+ log.info("Processing request")
176
+ # Output includes: request_id=abc-123 correlation_id=xyz-789 ...
177
+ ```
178
+
179
+ All formatters are optional and automatically enabled when their respective dependencies are installed. They work seamlessly in both development (console) and production (JSON) logging modes.
180
+
123
181
  ## FastAPI Access Logger
124
182
 
125
183
  **Note:** Requires `pip install structlog-config[fastapi]` for FastAPI dependencies.
@@ -193,6 +251,16 @@ FAILED tests/test_user.py::test_user_login
193
251
 
194
252
  For passing tests, no log output is shown, keeping your test output clean and focused.
195
253
 
254
+ ## Beautiful Traceback Support
255
+
256
+ Optional support for [beautiful-traceback](https://github.com/iloveitaly/beautiful-traceback) provides enhanced exception formatting with improved readability, smart coloring, path aliasing (e.g., `<pwd>`, `<site>`), and better alignment. Automatically activates when installed:
257
+
258
+ ```bash
259
+ uv add beautiful-traceback --group dev
260
+ ```
261
+
262
+ No configuration needed - just install and `configure_logger()` will use it automatically.
263
+
196
264
  ## iPython
197
265
 
198
266
  Often it's helpful to update logging level within an iPython session. You can do this and make sure all loggers pick up on it.
@@ -1,15 +1,15 @@
1
- structlog_config/__init__.py,sha256=b0I_Jir4s2H2iVv9OB38MfHaCRGiq50G6gQMaX_RK80,6706
1
+ structlog_config/__init__.py,sha256=jTw47yiht0XmINIDUMicHZQYF_757ALXopxgOkAEhaQ,6939
2
2
  structlog_config/constants.py,sha256=O1nPnB29yZdqqaI7aeTUrimA3LOtA5WpP6BGPLWJvj8,510
3
3
  structlog_config/env_config.py,sha256=_EJO0rgAKndRPSh4wuBaH3bui9F3nIpn8FaEkjAjZso,1737
4
4
  structlog_config/environments.py,sha256=JpZYVVDGxEf1EaKdPdn6Jo-4wJK6SqF0ueFl7e2TBvI,612
5
5
  structlog_config/fastapi_access_logger.py,sha256=CYZsww0AIcdfrU5Wgr6POwdJxJ5vMB96ttsYqoE30BU,4363
6
- structlog_config/formatters.py,sha256=ll0Y0QeRs1DMmD-ft1n1zA4Vn2STRSK-mOrczYB2OjE,5898
6
+ structlog_config/formatters.py,sha256=4B485qMTn9y5LqV7uWPJbgJrdIW5IiyRS3A0PEjcrS4,6748
7
7
  structlog_config/levels.py,sha256=LqXG4l01mIpxS2qI7PF_Vp9K7IrO0D5qU_x-Uo3LNuM,2372
8
- structlog_config/packages.py,sha256=asxrzLR-iRYAbkoSYutyTdIRcruTjHgkzfe2pjm2VFM,519
8
+ structlog_config/packages.py,sha256=xO4wHPIhAwGG6jv0kHdCr9NHpoIFx4VUeRzmztXp2is,591
9
9
  structlog_config/pytest_plugin.py,sha256=XBtef1KpuGV_RmXoWf13b0EUy69iAKMAk4-e5ZZnAuM,6819
10
10
  structlog_config/stdlib_logging.py,sha256=iHApYdsAs_ZC7Y8NpbKs23AHAJB1qLUCZPvFd-Nf_4I,7381
11
11
  structlog_config/trace.py,sha256=esSzTulaVr63H3iOYpHlU-NXPSwpEGS7GEYbv6Iq-3A,2118
12
12
  structlog_config/warnings.py,sha256=gKEcuHWqH0BaKitJtQkv-uJ0Z3uCH5nn6k8qpqjR-RM,998
13
- structlog_config-0.6.0.dist-info/WHEEL,sha256=4n27za1eEkOnA7dNjN6C5-O2rUiw6iapszm14Uj-Qmk,79
14
- structlog_config-0.6.0.dist-info/METADATA,sha256=Fs9cC8t70oUVMVUBUTTFGEvlNZZcQRtoibBX_OYidtk,8366
15
- structlog_config-0.6.0.dist-info/RECORD,,
13
+ structlog_config-0.8.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
14
+ structlog_config-0.8.0.dist-info/METADATA,sha256=SmpaIUr3-ELE2u_dOAvrVBJkj6IX33rVe-lZgz9PiCU,10995
15
+ structlog_config-0.8.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: uv 0.8.13
2
+ Generator: uv 0.8.24
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any