text: from collections.abc import Mapping
  from logging import Formatter, LogRecord
  import json
  
  
  #: Attributes of a LogRecord.
  # See <the docs `https://docs.python.org/3/library/logging.html#logrecord-attributes`>_.
  RECORD_ATTRIBUTES = (
      "args",
      "asctime",
      "created",
      "exc_info",
      "exc_text",
      "filename",
      "funcName",
      "levelname",
      "levelno",
      "lineno",
      "message",
      "module",
      "msecs",
      "msg",
      "name",
      "pathname",
      "process",
      "processName",
      "relativeCreated",
      "stack_info",
      "thread",
      "threadName",
  )
  
  
  class JsonFormatter(Formatter):
      """
      Formatter that emits data as JSON
  
      :param fmt: default data for all records
      :param datefmt: format for timestamps
  
      The ``datefmt`` parameter has almost the same meaning as
     :py:class:`~.Formatter`.
      Setting it to ``None`` uses the default time format.
      However, setting it to any other value that is boolean
      false excludes the timestamp from reports.
      """
  
      def __init__(self, fmt: dict = None, datefmt: str = None):
          super().__init__(fmt=None, datefmt=datefmt, style="%")
          self._defaults = fmt or {}
          if not isinstance(self._defaults, Mapping):
              raise TypeError("`fmt` must be a Mapping or None")
          self._add_time = self.datefmt or self.datefmt is None
  
      def format(self, record: LogRecord):
          args = record.args
          if args == ({},):  # logger.info('message', {}) -> record.args == ({},)
              args = {}
          assert isinstance(
              args, Mapping
          ), "monitor record argument must be a mapping, not %r" % type(args)
          data = self._defaults.copy()
          if self._add_time:
              data["time"] = self.formatTime(record, self.datefmt)
          data["message"] = record.getMessage() if args else record.msg
          data.update(args)
          return json.dumps(data)
  
  
  if __name__ == "__main__":
      import logging
  
      logger = logging.getLogger()
      logger.handlers = [logging.StreamHandler()]
      logger.handlers[0].formatter = JsonFormatter({"latitude": 49, "longitude": 8})
      logger.warning("forecast", {"temperature": 298, "humidity": 0.45})
  