You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/cookbook.md
+77-1Lines changed: 77 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,11 @@ Recipies for common tasks.
4
4
5
5
## Include all fields
6
6
7
-
This can be achieved by setting `reserved_attrs=[]` when creating the formatter.
7
+
By default Python JSON Logger will not include fields [defined in the standard library](https://docs.python.org/3/library/logging.html#logrecord-attributes) unless they are included in the format. Manually including all these fields is tedious and Python version specific. Instead of adding them as explicit fields, we can add them implicitly be ensuring they are not in the `reserver_attrs` argument of the formatter.
By the nature of Python's logging library, the JSON formatters will only ever run in handlers which are enabled for the given log level. This saves the performance hit of constructing JSON that is never used - but what about the data we pass into the logger? There are two options available to us: using if statements to avoid the call altogether, or using lazy string evaluation libraries.
176
+
177
+
!!! note
178
+
The below strategies will work for data passed in the `msg` and `extra` arguments.
179
+
180
+
To avoid the logging calls we use `logger.isEnabledFor` to ensure that we only start constructing our log messages if the logger is enabled:
181
+
182
+
```python
183
+
import logging
184
+
import time
185
+
186
+
from pythonjsonlogger.json import JsonFormatter
187
+
188
+
defexpensive_to_compute():
189
+
time.sleep(5)
190
+
return"world"
191
+
192
+
## Setup
193
+
## -------------------------------------
194
+
logger = logging.getLogger()
195
+
handler = logging.StreamHandler()
196
+
formatter = JsonFormatter()
197
+
handler.setFormatter(formatter)
198
+
logger.addHandler(handler)
199
+
logger.setLevel(logging.INFO)
200
+
201
+
## Log Using isEnabledFor
202
+
## -------------------------------------
203
+
start = time.time()
204
+
if logger.isEnabledFor(logging.INFO):
205
+
logger.info(
206
+
{
207
+
"data": "hello {}".format(expensive_to_compute())
208
+
}
209
+
)
210
+
print(f"Logging INFO using isEnabledFor took: {int(time.time() - start)}s")
211
+
212
+
start = time.time()
213
+
if logger.isEnabledFor(logging.DEBUG):
214
+
logger.debug(
215
+
{
216
+
"data": "hello {}".format(expensive_to_compute())
217
+
}
218
+
)
219
+
print(f"Logging DEBUG using isEnabledFor took: {int(time.time() - start)}s")
220
+
```
221
+
222
+
For lazy string evaluation we can take advantage of the fact that the default JSON encoders included in this package will call `str` on unkown objects. We can use this to build our own lazy string evaluators, or we can use an existing external package. Pre-existing solutions include: [`lazy-string`](https://pypi.org/project/lazy-string/)'s `LazyString` or [`stringlike`](https://pypi.org/project/stringlike/)'s `CachedLazyString`.
0 commit comments