class naz.log.SimpleLogger(logger_name, level=20, log_metadata=None, handler=None, render_as_json=True)[source]

Bases: logging.Logger

It implements a structured logger that renders logs as either json(default) or python dictionary.

example usage:

logger = SimpleLogger("myLogger")
           {"event": "web_request", "url": "https://www.google.com/"})
__init__(logger_name, level=20, log_metadata=None, handler=None, render_as_json=True)[source]
  • logger_name (str) – name of the logger. it should be unique per logger.

  • level (Union[str, int]) – the level at which to log

  • log_metadata (Union[None, dict]) – metadata that will be included in all log statements

  • handler (Union[None, Handler]) – python logging handler to be attached to this logger. By default, logging.StreamHandler is used.

  • render_as_json – whether to render logs as json or dictionary. By default it renders as json.

Return type


log(level, msg, *args, **kwargs)[source]

Log ‘msg % args’ with the integer severity ‘level’.

To pass exception information, use the keyword argument exc_info with a true value, e.g.

logger.log(level, “We have a %s”, “mysterious problem”, exc_info=1)

class naz.log.BreachHandler(flushLevel=30, capacity=1000, target=None, flushOnClose=False, heartbeatInterval=None, targetLevel='DEBUG')[source]

Bases: logging.handlers.MemoryHandler

This is an implementation of logging.Handler that puts logs in an in-memory ring buffer. When a trigger condition(eg a certain log level) is met; then all the logs in the buffer are flushed into a given stream(file, stdout etc)

It is a bit like logging.handlers.MemoryHandler except that it does not flush when the ring-buffer capacity is met but only when/if the trigger is met.

It is inspired by the article Triggering Diagnostic Logging on Exception

example usage:

import naz, logging

_handler = naz.log.BreachHandler()
logger = naz.log.SimpleLogger("aha", handler=_handler, log_metadata={"id": "123"})

logger.log(logging.INFO, {"name": "Jayz"})
logger.log(logging.ERROR, {"msg": "Houston, we got 99 problems."})

# or alternatively, to use it with python stdlib logger
logger = logging.getLogger("my-logger")
handler = naz.log.BreachHandler()
formatter = logging.Formatter("%(message)s")
if not logger.handlers:

logger.info("I did records for Tweet before y'all could even tweet - Dr. Missy Elliot")
__init__(flushLevel=30, capacity=1000, target=None, flushOnClose=False, heartbeatInterval=None, targetLevel='DEBUG')[source]
  • flushLevel (int) – the log level that will trigger this handler to flush logs to target

  • capacity (int) – the maximum number of log records to store in the ring buffer

  • target (Union[None, Handler]) – the log handler that will be used.

  • flushOnClose (bool) – whether to flush the buffer when the handler is closed even if the flush level hasn’t been exceeded

  • heartbeatInterval (Union[None, float]) – can be a float or None. If it is a float, then a heartbeat log record will be emitted every heartbeatInterval seconds. If it is None(the default), then no heartbeat log record is emitted. If you do decide to set it, a good value is at least 1800(ie 30 minutes).

  • targetLevel (str) – the log level to be applied/set to target

Return type



Emit a record. Append the record. If shouldFlush() tells us to, call flush() to process the buffer.

Implementation is taken from logging.handlers.MemoryHandler

Return type



Check for record at the flushLevel or higher. Implementation is mostly taken from logging.handlers.MemoryHandler

Return type