Skip to main content

Tree based logging for async python

Project description

lumberjack

Tree based logging for python.

Normal logging struggles in async python, since logs will often get mixed up, and it may not be clear what happened in what order. lumberjack instead groups logs into a tree like structure. This way, any result can be easily broken down into its steps. The tree structure is to isolate different synchronous paths through the async system, so that each log is ordered, and the logic can be easily followed.

Basic Usage

Creating a Logger

Creating a logger is as easy as defining a backend, and then creating a TreeLogger. Generally, it is advisable to use lumberjack loggers as context managers.

import lumberjack
import lumberjack.backends

logging_backend = lumberjack.backends.FileWriter("some_folder_path")
with lumberjack.TreeLogger(logging_backend):
    ...

Logging

Once a logger has been created, you can begin logging. There are two ways to do so: First, if you are in the context of a TreeLogger, you can simply log directly.

with lumberjack.TreeLogger(logging_backend):
    lumberjack.log(message="Some message to log")

If you do not wish to use TreeLogger as a context manager, you will instead need to call the logging methods of your Treelogger's branches.

tree_logger = lumberjack.TreeLogger(logging_backend)
root_branch = tree_logger.root
another_branch = root_branch.branch("new branch")
another_branch.log(message="Some message to log")

Branching

The main feature of lumberjack is the ability to branch logs, so that logs are separate between concurrently running functions. Once again, there is the context approach, and the manual approach.

If you are using a context manager, then you can simply decorate any functions that you wish to be branch points. Any time these functions are called, lumberjack will automatically create a new branch for logging. For example:

@lumberjack.branch
async def async_fn():
    lumberjack.log("some log message")
    sync_fn()

@lumberjack.branch
def sync_fn():
    lumberjack.log("another log message")

with lumberjack.TreeLogger(logging_backend):
    asyncio.run(async_fn())

In the above example, the logs in each function will be kept separate, even between runs of the same function. While this may not be useful for this toy example, anytime your code includes asyncio.gather or similar, it can be invaluable.

The manual branching approach can be easily demonstrated by this previous example:

tree_logger = lumberjack.TreeLogger(logging_backend)
root_branch = tree_logger.root
another_branch = root_branch.branch("new branch")
another_branch.log(message="Some message to log")

Anytime a logger branch is branched, a log entry will be added to parent branch at the appropriate location.

Demo File

For a more full example of lumberjack in use, please refer to demo.py.

Installing

To install lumberjack, simply use pip

pip install lumberjack

However, if you want to use the built-in Streamlit UI to view the logs that you create, you should install lumberjack with the ui extras.

pip install lumberjack[ui]

Some backends will also require extras, such as redis.

pip install lumberjack[redis]

UI

If you install lumberjack with the ui extras, lumberjack provides access to a simple Streamlit UI which you can use to view the logs. If you have installed lumberjack with the ui extras, simply use the command lumberjack-ui to run the UI. Currently, you can choose to point the UI at either a file-based or redis backend.

Usage: lumberjack-ui run [OPTIONS]

  Launch the lumberjack UI to view logs.

Options:
  --port INTEGER           Port to run the Streamlit app on.
  --backend [redis|files]  Backend to use.  [required]
  --redis-host TEXT        Redis host (if using redis backend).
  --redis-port INTEGER     Redis port (if using redis backend).
  --filepath PATH          Path to log file (if using files backend).
  --help                   Show this message and exit.

Once you have launched the UI, you can access it on your local machine via the port that you provided, in a browser of your choice, where you will see the search screen. This screen will allow you to select from any branch that was saved to the currently running backend.

Search View Example

From there, you can open any branch that you wish to view, and you will enter the logs screen. This screen allows you to navigate the tree of the branch you selected, as well as return to the search screen.

Log View Example

Best Practices

Message Types

The flow logger has 3 message types: SYSTEM, USER, and ERROR. Each message type is used to indicate a different kind of log message, and should be used in accordance with the following guidelines:

SYSTEM

  • Indicating when a branch has occurred (handled internally by the logger)
  • Indicating the function arguments of a called function (handled by either the user or the @branch decorator)
  • Indicating the return value of a called function (handled by either the user or the @branch decorator)

ERROR

  • Indicating an error which occurred during the function call (handled by the user or the @branch decorator)

USER

  • Logging potentially error-prone modifications/transformations of variables
  • Logging calls to external services and the parameters of those calls
  • Logging the results of external services and the parameters of those results
  • Logging important control flow

Branching

Branching should be done whenever entering a new context, as mentioned above. Follow the following guidelines for branching:

  • Fork whenever calling a new function
  • Fork whenever the execution path becomes asynchronous

As a general guideline, do not have a logger associated with an object or class, instead log on the function level.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bramble-0.0.1.tar.gz (196.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bramble-0.0.1-py3-none-any.whl (26.5 kB view details)

Uploaded Python 3

File details

Details for the file bramble-0.0.1.tar.gz.

File metadata

  • Download URL: bramble-0.0.1.tar.gz
  • Upload date:
  • Size: 196.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for bramble-0.0.1.tar.gz
Algorithm Hash digest
SHA256 b859b851aa2fb0d55830cdb841d465cab035fb9798bcdfc4e28d938bdb21268f
MD5 5e0e4589c84311ebed662c0b95d0c2c7
BLAKE2b-256 0994c68a8da01465a16155d037ec82bc4c9433516a78883545ef21eee38df81b

See more details on using hashes here.

File details

Details for the file bramble-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: bramble-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 26.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for bramble-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5ffee21cf7b722bb8b94d553e7791a47e3abd3e3265f7af0cc66a8995861dc9b
MD5 11a916cba33f7bd2138fb8bb2c9475c9
BLAKE2b-256 031676b305f35cee83d972dac84101cfa9c2e6a38b08cb7141a090af1d63f094

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page