msgspec.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. """JSON Formatter using [`msgspec`](https://github.com/jcrist/msgspec)"""
  2. ### IMPORTS
  3. ### ============================================================================
  4. ## Future
  5. from __future__ import annotations
  6. ## Standard Library
  7. from typing import Any
  8. from collections.abc import Callable
  9. ## Installed
  10. ## Application
  11. from . import core
  12. from . import defaults as d
  13. from .utils import package_is_available
  14. # We import msgspec after checking it is available
  15. package_is_available("msgspec", throw_error=True)
  16. import msgspec.json # pylint: disable=wrong-import-position,wrong-import-order
  17. ### FUNCTIONS
  18. ### ============================================================================
  19. def msgspec_default(obj: Any) -> Any:
  20. """msgspec default encoder function for non-standard types"""
  21. if d.use_exception_default(obj):
  22. return d.exception_default(obj)
  23. if d.use_traceback_default(obj):
  24. return d.traceback_default(obj)
  25. if d.use_enum_default(obj):
  26. return d.enum_default(obj)
  27. if d.use_type_default(obj):
  28. return d.type_default(obj)
  29. return d.unknown_default(obj)
  30. ### CLASSES
  31. ### ============================================================================
  32. class MsgspecFormatter(core.BaseJsonFormatter):
  33. """JSON formatter using [`msgspec.json.Encoder`](https://jcristharif.com/msgspec/api.html#msgspec.json.Encoder) for encoding."""
  34. def __init__(
  35. self,
  36. *args,
  37. json_default: Callable | None = msgspec_default,
  38. **kwargs,
  39. ) -> None:
  40. """
  41. Args:
  42. args: see [BaseJsonFormatter][pythonjsonlogger.core.BaseJsonFormatter]
  43. json_default: a function for encoding non-standard objects
  44. kwargs: see [BaseJsonFormatter][pythonjsonlogger.core.BaseJsonFormatter]
  45. """
  46. super().__init__(*args, **kwargs)
  47. self.json_default = json_default
  48. self._encoder = msgspec.json.Encoder(enc_hook=self.json_default)
  49. return
  50. def jsonify_log_record(self, log_data: core.LogData) -> str:
  51. """Returns a json string of the log data."""
  52. return self._encoder.encode(log_data).decode("utf8")