Skip to main content

What is TermaLogger

A straightworward, centralized way of using Structlog that makes common functionality dead simple and adds some nice extras along the way.

Usage

Simply import and create an instance of TermaLogger:

from termalogger import TermaLogger

log = TermaLogger("coolapp")

target_dir = Path("images/coolphotos")
for file in target_dir.iterdir():
    log.info("Processing a photo...", label="photos", path=file)
    ...

You can provide a number of initial args, but the bound logger's name is the only required one.

The methodology behind TermaLogger follows that of the prevailant Twelve-Factor Logging, in that files are not of its concern. However, if you want that functionality, you can enable JSON output and set log.json_factory to use a factory such as structlog.BytesLoggerFactory(file="logfile"), where logfile is any Bytes file instance. Alternatively, you could do something like log.json_processors.append(log.line_tracker) and dump log.bytes_lines to a file, but using the line trackers is only really a good idea for tests.

Filtering

level - [__init__, settings, set_level] - (str | int)

Typical loglevel filtering. This uses Structlog's quite efficient make_filtering_bound_logger and is useful to set up the overall run environment. Can be either a number corresponding to a native loglevel or the level's name.

cache_logger_on_first_use - [__init__, settings] - (bool)

Directly corresponds to the Structlog opt: See Structlog performance docs

format_json - [__init__, set_json_output] - (bool)

Sets appropriate configurations for structured JSON output using orjson

filter - [__init__, settings, set_filter] - (list[str])

The real power behind LogWrapper is the label filtering. Labels effectively offer a much more versatile way of getting the information you want than jankily adding custom levels and trying to sift through them. This is the future, after all.

To use labels, simply add an event to a log message:

for fruit in fruit_list:
    try:
        log.debug("Processing a fruit...", labels=["fruit", "loop"], fruit=fruit)
        # Do some fruity processing stuff
    except Exception as exc:
        log.error("Couldn't process a fruit!", label="fruit", fruit=fruit, exc_info=exc)

label and labels can be used interchangeably with either a single label or list of them. While debugging, you can start filtering out unwanted noise by setting:

log.settings(level="debug", filter={"debug": ["fruit"]})

Which would drop any debug messages not containing a "fruit" label.

Filtering is only performed on debug messages by default, meaning that if you set loglevel to debug, then any debug message with labels won't be shown if log.debug_filter=[] (default). This is not the case for higher levels unless you explicitly set log.set_filter({"warn": []}) or log.filter_enable["warn"] = True.

Tracking & Tests

Structlog's immensely powerful processor pipeline and the self-contained nature of using a class to pull its strings comes with another, quite convenient bonus: Event tracking. TermaLogger has three noteworthy attributes (lists) for keeping historical data:

  • self.events: Event dictionaries.
  • self.str_lines: Rendered lines (strings)
  • self.bytes_lines Rendered lines (bytes)

Normally, these lists won't be populated with anything. It's only until you add the respective processors when they become useful:

from termalogger import TermaLogger

log = TermaLogger("app_tests")

# Event dictionary list
log.shared_processors.append(log.event_tracker)
# Rendered lines list (str or bytes, respectively)
log.console_processors.append(log.lines_tracker)
log.json_processors.append(log.lines_tracker)
# Recreate the logger with updated processors
log.settings()

At which point you'll see the aforementioned lists start to be populated by log entries! This is especially useful when building your tests, a more complete example of which can be found in TermaLogger's own test routines.

Other Stuff

Contributing

Contributions are very welcome!

  • Issues: Don't hesitate to report something, even if it's as small as a semantics inconsistency.
  • PRs: The main pointer to keep in mind is to take advantage Structlog's versatility wherever sensible when adding new things. Also ideally creating relevant tests!

Resources

  • Come hang out and share cool stuff with the community on Discord!
  • The (so far) one other project in the Terma* series: TermaConfig

License

GNU General Public License v3.0

Metadata

Release files for termalogger 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for termalogger 1.0.0
File Size Uploaded
termalogger-1.0.0.tar.gz 18.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for termalogger 1.0.0
File Interpreter ABI Platform
termalogger-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 38.9 kB

Release files / termalogger-1.0.0.tar.gz

Download URL termalogger-1.0.0.tar.gz
Size 18.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f1548a52bab5cec4147b41721f27225ce4caa33367a376ffc0fee921a691e245
BLAKE2b-256 checksum
How to use checksums
cbc6099a35dad35c476e1ba047bd84f9224d7cadac83ae87054e90d91ff2b52a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2025.

Transparency log

Release files / termalogger-1.0.0-py3-none-any.whl

Download URL termalogger-1.0.0-py3-none-any.whl
Size 20.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
01b7bc424c8a614382ff364e562c5f745906fa719eae6ac7aada9355d0d82c84
BLAKE2b-256 checksum
How to use checksums
0f79fed4ae5e6665f26d2d16b032bd9c132fd812bcd9e782a1836afd7bc8bccc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page