Skip to main content

Fully async, modular logging system for Python with time-based rollover and mirror streams.

Project description

Chronologix

Chronologix is a fully asynchronous, modular logging system for Python.

It writes structured log files across multiple named streams, supports time-based chunking, and avoids the standard logging module completely.


Features

  • Fully async logging
  • Time-based rollover (e.g. every 24h, 1h, 15min)
  • Log stream isolation (e.g. errors, debug, events)
  • Configurable mirror streams (errorsdebug)
  • Safe, stateless async file writes
  • Config validation with clear error feedback
  • Custom log paths via str or pathlib.Path
  • Predictable file and folder structure for automated processing

Installation

Chronologix requires Python 3.7+.

pip install chronologix

Usage example

from chronologix import LogConfig, LogManager

config = LogConfig(
    base_log_dir="my_logs",                 # can also be a pathlib.Path
    interval="1h",                          # rollover interval
    log_streams=["app", "errors", "audit"], # named log streams
    mirror_map={"errors": ["app"]},         # errors are mirrored into "app"
    timestamp_format="%H:%M:%S.%f"          # timestamp format
)

logger = LogManager(config)

async def divide(a, b):
    try:
        result = a / b
        await logger.log(f"Division result: {result}", target="app")
    except Exception as e:
        await logger.log(f"Exception occurred: {e}", target="errors")

async def main():
    await logger.start()
    await logger.log("Starting batch job", target="app")
    await logger.log("Auditing step 1", target="audit")
    await divide(10, 0)  # this will raise and log to both "errors" and "app"
    await logger.stop()

This example will produce following:

  • A new folder per hour like: 2025-05-04__14-00/
  • Three log files inside: app.log, errors.log, audit.log
  • The exception will be logged to both errors.log and app.log
  • The audit message will only go to audit.log with no mirroring

Path structure

You can set the log output directory using either a string path or a pathlib.Path object.

Examples:

LogConfig(base_log_dir="logs")  # relative to current working dir
LogConfig(base_log_dir="/var/log/chronologix")  # absolute path (Linux)
LogConfig(base_log_dir=Path("~/.chronologix").expanduser())  # user home dir

Chronologix will create any missing directories automatically.


Intervals

The interval controls how frequently Chronologix creates a new folder and rotates the log files.

Supported values:

  • "24h"
  • "12h"
  • "6h"
  • "3h"
  • "1h"
  • "30m"
  • "15m"
  • "5m"

Each interval corresponds to a different granularity of time-based chunking.

  • interval="24h" → folders like 2025-05-04/
  • interval="1h" → folders like 2025-05-04__14-00/

Log streams

Log streams define the named .log files Chronologix will manage.

Each stream corresponds to a separate log file inside each time-based folder.

Example:

log_streams=["app", "errors", "audit"]

This would create:

my_logs/
└── 2025-05-04/
    ├── app.log
    ├── errors.log
    └── audit.log

Each call to .log(message, target=...) writes to the stream you specify.

You can define as many log streams as needed or just a single one.

Example:

LogConfig(
    log_streams=["app"],
    mirror_map={}
)

This will create a single app.log file per interval. Mirroring is optional, and is not required when using only one stream.


Mirroring

Mirroring can be configured like this:

mirror_map = {
    "errors": ["app"],    # messages logged to "errors" will mirror to "app"
    "debug":  ["all"]
}

Mirroring is optional. Any stream can exist without mirrors, and mirrors can point to multiple targets.


Timestamp formatting

Customize timestamp formatting using any valid strftime directive.

Examples:

- %H:%M:%S → 14:02:19

- %H:%M:%S.%f → 14:02:19.123456

- %Y-%m-%d %H:%M:%S → 2025-05-04 14:02:19

Invalid formats are rejected with a descriptive LogConfigError.


Log structure

my_logs/
└── 2025-05-04__14-00/
    ├── app.log
    ├── errors.log
    └── audit.log
└── 2025-05-04__15-00/
    ├── app.log
    ├── errors.log
    └── audit.log

Folders are aligned to the start of the interval (__14-00) and created ahead of time to mitigate latency for smooth rollover.


Default config

If you use the default constructor, Chronologix behaves like this:

from chronologix import LogConfig

config = LogConfig()
logger = LogManager(config)
await logger.start()

Which is equivalent to:

LogConfig(
    base_log_dir="logs",
    interval="24h",
    log_streams=["all", "errors"],
    mirror_map={"errors": ["all"]},
    timestamp_format="%H:%M:%S"
)

But why?

The idea to build this package came from direct need while working on my private trading software. I hadn't found anything that would check all the boxes and satisfy my OCD, so I decided to build it myself. At first, it was just a module tailored for my program, but then I realized it could be useful for others. So it felt like the perfect opportunity to finally open source something. The core of Chronologix is built on my original logging module, but I tried to make it as flexible as possible to cater to different needs.


Contributing

Feel free to reach out if you have any suggestions or ideas. I'm open to collaboration and improvements.

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

chronologix-0.1.1.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

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

chronologix-0.1.1-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file chronologix-0.1.1.tar.gz.

File metadata

  • Download URL: chronologix-0.1.1.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.2

File hashes

Hashes for chronologix-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bf1144e6ce61aa642e2adab5ecbcaceaeb4c6dfdb89aded0317d48cebefd2a81
MD5 0450d3c860339d8794adfd574e827bbf
BLAKE2b-256 0b9dbc8227837f3c13620e28dee7e5d7bce6376e6ccc4541d289dc5c5e294491

See more details on using hashes here.

File details

Details for the file chronologix-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: chronologix-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.2

File hashes

Hashes for chronologix-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ffa204b5bef931ce4a8015b57385e9611d155af740db43e653f4d73326e5550d
MD5 31e27050b06e48fffaf1ef817aff538e
BLAKE2b-256 47e9ef9e261d43416a435ac1c239b292bfeaa12593881a2031f5f03c5aac6a15

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