Skip to main content

Stack log messages

Project description

PyPI Shield Downloads .github/workflows/test.yml

stacklog

Stack log messages

Overview

Stacklog is a tiny Python library to stack log messages.

A stack-structured log is an approach to logging in which log messages are (conceptually) pushed onto a stack and emitted only when the corresponding block returns. Stacklog provides a single method, stacklog, which serves as either a decorator or a context manager. This is exceptionally useful in small projects or one-off scripts.

This is illustrated best with an example:

with stacklog(print, 'Running some code'):
    with stacklog(print, 'Running some other code'):
        pass

This produces the following logging output:

Running some code...
Running some other code...
Running some other code...DONE
Running some code...DONE

When the code within a stacklog context completes, the provided message is echoed along with the return status, one of DONE or FAILURE. That's pretty much it. Customization and advanced features are available through callbacks.

Install

stacklog has been developed and tested on Python 2.7 and 3.5+.

pip install stacklog

Quickstart

How often do you find yourself using the following logging anti-pattern in Python?

import logging

def a():
    logging.info('Running a')
    do_something()
    logging.info('Done with a')

def b():
    logging.info('Running b')
    a()
    logging.info('Done with b')

try:
    b()
except:
    logging.info('There was an error running b')

The intention here is to log the beginning and end of procedure calls for use in debugging or user monitoring. I call this an anti-pattern because:

  • it requires excessive manual attention to writing/updating logging calls at entry/exit sites
  • it results in redundant exception handling logic
  • the resulting log messages can be misleading if errors occur

Instead, the approach taken by stacklog is to accomplish this using only decorators and context managers.

Usage as decorator

Here is the above example using the stacklog as a decorator:

@stacklog(logging.info, 'Running a')
def a():
    raise Exception

@stacklog(logging.info, 'Running b')
def b():
    a()

b()

This produces logging output:

INFO:root:Running b...
INFO:root:Running a...
INFO:root:Running a...FAILURE
INFO:root:Running b...FAILURE

Usage as context manager

Here is another example using stacklog as a context manager:

>>> with stacklog(logging.info, 'Running some code'):
...     do_something()
...
INFO:root:Running some code...
INFO:root:Running some code...DONE

Advanced usage

Providing custom conditions

A condition is a tuple exception, status. If the provided exception is raised during the execution of the provided code, the provided status is logged instead of the default FAILURE.

>>> with stacklog(logging.info, 'Running some code', conditions=[(NotImplementedError,
'SKIPPED')]):
...     raise NotImplementedError
...
INFO:root:Running some code...
INFO:root:Running some code...SKIPPED

Customization with callbacks

The behavior of stacklog is fully customizable with callbacks.

The main thing that a callback will do is call the passed stacklog instance's log method with some custom suffix.

First, there are three callbacks to customize the behavior of logging at the beginning of the block, at successful completion of the block, and at failure of the block. Only one function can be registered at a time for each of these events.

  • on_begin(func: stacklog -> None)
  • on_success(func: stacklog -> None)
  • on_failure(func: stacklog -> None)

Second, one can customize failure behavior given different possible exceptions that are raised, by passing a pair of functions, the first to match an exception that was raised during block execution and the second to respond to the exception. Many pairs of functions can be registered, but only the most recent one to be registered will be executed in the case that multiple functions match.

  • on_condition(match: *exc_info -> bool, func: stacklog, *exc_info -> None)

Third, one can initialize and dispose of resources before and after the block's execution. This is relevant for starting/stopping timers, etc. Many functions can be registered and they will all be executed.

  • on_enter(func: stacklog -> None)
  • on_exit(func: stacklog -> None)

See the implementation of stacktime for an example.

Adding timing information

One can customize stacklog with callbacks to, for example, add information on the duration of block execution. This is packaged with the library itself as the stacktime decorator/context manager. It's usage is the same as stacklog except that it also logs timing information at the successful completion of block.

>>> with stacktime(print, 'Running some code', unit='ms'):
...     time.sleep(1e-2)
...
Running some code...
Running some code...DONE in 11.11 ms

History

2.0.2 (2024-07-29)

  • Use poetry and pyproject.toml for all config

2.0.1 (2024-07-29)

  • Move some py3 compat inside import guards

2.0 (2024-07-26)

  • Drop support for python 2
  • Drop support for python 3.5, 3.6, and 3.7
  • Add type annotations
  • Reimplement stacktime as a subclass

1.1 (2020-03-19)

  • Refactored to use callbacks everywhere
  • Implemented stacktime

1.0 (2019-12-10)

Initial release.

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

stacklog-2.0.2.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

stacklog-2.0.2-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file stacklog-2.0.2.tar.gz.

File metadata

  • Download URL: stacklog-2.0.2.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.3 Darwin/23.5.0

File hashes

Hashes for stacklog-2.0.2.tar.gz
Algorithm Hash digest
SHA256 010f076d51f69e5e86aa6f1ad8d57beaa1001a88a5a7a2583a2e2b28ad52b94f
MD5 800c12bfe7cb07f353f51ffd6166ffaf
BLAKE2b-256 60d4aebe6d88f0e46d47abfbb5fc5f5ec4c6f79cdc1f1025009f03919ca246a3

See more details on using hashes here.

File details

Details for the file stacklog-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: stacklog-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.3 Darwin/23.5.0

File hashes

Hashes for stacklog-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8b7f9b6fde0c6dcef7bbb187a11ab26f8afbd6eee8bffe96e7152bdfd5e0359b
MD5 45e5f29bb88691e4cdc77ee5bd616f1c
BLAKE2b-256 395389bf50d7a424ac75455de44b188ce1085f7524a530628bf11f3245a9901a

See more details on using hashes here.

Supported by

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