Custmon loggers to make debugging easy
Project description
๐งช logger-lab
Logging, reimagined as a system.
logger-lab is a composable Python logging toolkit built around a simple idea:
logging should be modular, readable, and adaptable โ for both humans and machines.
Instead of writing repetitive logging setup, you select from experiments, apply profiles, or compose your own logger by assembling them like a system.
๐ Installation
pip install logger-lab
โก Quick Start
from logger_lab import get_logger
logger = get_logger(__name__, profile="INVESTIGATOR")
logger.info("System online")
logger.debug("Inspecting state")
logger.error("Something broke")
Summary of usage
Both enums and strings can be used as parameters for both get_logger() and lab():
import logging
from logger_lab import lab, get_logger, ExperimentType
# Profiles (prebuilt combinations):
profile_logger = get_logger(name="profile_test", profile="conspiracy_theorist")
# Experiments (single handler factories):
experiment_logger = get_logger(name="experiment_test", experiment=ExperimentType.MINIMALIST)
# Fluent builder (custom composition):
built_logger = (
lab()
.with_experiment('STANDARD')
.with_experiment(ExperimentType.FILE)
.with_level(logging.DEBUG)
.build(__name__)
)
๐งช Experiments
Experiments are atomic logging behaviours โ pure functions that return a list of configured handlers.
Each experiment controls exactly one thing: how logs are formatted and where they go.
| Experiment | Handler | Description |
|---|---|---|
standard |
RichHandler |
Colourised console output with traceback support |
minimalist |
StreamHandler |
Plain LEVEL: message โ warnings only by default |
verbose |
StreamHandler |
Full context: timestamp, module, function, line |
file |
FileHandler |
Persistent plain-text log at logs/app.log |
rotating_file |
RotatingFileHandler |
Auto-rotates at 5 MiB, keeps 3 backups |
ai |
StreamHandler (stderr) |
Structured JSON โ Mosquito Lab Standard v1 |
Using a single experiment
from logger_lab import get_logger
logger = get_logger(__name__, experiment="minimalist")
logger.info("Ready")
๐งซ Profiles
Profiles are prebuilt combinations of experiments tuned for common use cases.
| Profile | Experiments | Use case |
|---|---|---|
observer |
minimalist |
Production โ warnings and above only |
investigator |
standard + file |
Development โ Rich console + disk |
conspiracy_theorist |
verbose + file + rotating_file |
Deep archival โ nothing missed |
ai_agent |
ai |
Structured JSON for pipelines |
from logger_lab import get_logger, ProfileType
payload = "super dangerous and malicious payload!"
logger = get_logger(__name__, profile=ProfileType.CONSPIRATOR)
logger.debug("Payload received: %s", payload)
logger.error("Unexpected response", exc_info=True)
๐งฌ Custom Composition
For full control, build your logger like a system:
from logger_lab import lab, ExperimentType
logger = (
lab()
.with_experiment(ExperimentType.MINIMALIST)
.with_experiment(ExperimentType.FILE)
.with_level("DEBUG")
.build(__name__)
)
Mix a profile with additional experiments:
from logger_lab import lab, ExperimentType, ProfileType
logger = (
lab()
.with_profile(ProfileType.INVESTIGATOR)
.with_experiment(ExperimentType.AI)
.with_level("INFO")
.build(__name__)
)
๐ค AI Logging (Core Feature)
logger-lab includes a structured logging format designed for AI systems.
Logs become machine-readable events, not just text.
Example Output
{
"timestamp": "2026-05-05T12:00:00+00:00",
"level": "INFO",
"message": "User logged in",
"source": {
"module": "auth",
"function": "login",
"line": 88
},
"extra": {
"event": "user_login",
"context": { "user_id": 42 },
"tags": ["auth"]
}
}
Usage
Use log_event() โ it constructs a fresh extra dict on every call so successive calls never share mutable state:
from logger_lab import get_logger, log_event, ProfileType
import logging
logger = get_logger(__name__, profile=ProfileType.AGENT)
log_event(
logger, logging.INFO, "User logged in",
event="user_login",
context={"user_id": 42},
tags=["auth"],
)
๐จ Error Handling
All exceptions inherit from LabError so you can catch broadly or precisely.
LabError
โโโ LabRegistryError
โ โโโ ExperimentNotFoundError โ valid ExperimentType not registered
โ โโโ ProfileNotFoundError โ valid ProfileType not registered
โ โโโ InvalidExperimentName โ unrecognised experiment string
โ โโโ InvalidProfileName โ unrecognised profile string
โโโ LabConfigurationError
โ โโโ InvalidLevelError โ bad level string or int
โ โโโ HandlerConfigurationError โ handler failed to initialise
โ โ โโโ LogDirectoryError โ log directory mkdir/access failure
โ โโโ ExperimentRegistrationError โ callable doesn't satisfy ExperimentFactory
โ โโโ ProfileRegistrationError โ callable doesn't satisfy ProfileFactory
โโโ BuilderError โ build() called with nothing queued
Broad catch
from logger_lab import get_logger, LabError
try:
logger = get_logger(__name__, profile="typo")
except LabError as exc:
print(f"logger-lab error: {exc}")
Precise catch
from logger_lab import get_logger, InvalidProfileName, BuilderError
try:
logger = get_logger(__name__, profile="typo")
except InvalidProfileName as exc:
print(f"Unknown profile: {exc}") # lists valid names in the message
except BuilderError as exc:
print(f"Builder misconfigured: {exc}")
๐๏ธ Architecture
logger_lab/
โโโ __init__.py โ public API: get_logger(), lab(), log_event()
โโโ core/
โ โโโ enums.py โ ExperimentType, ProfileType
โ โโโ registry.py โ EXPERIMENTS + PROFILES dicts, validated registration
โ โโโ builder.py โ LabBuilder fluent interface + lab() factory
โโโ experiments/ โ atomic handler factories (level) โ list[Handler]
โ โโโ standard.py โ RichHandler
โ โโโ minimalist.py โ StreamHandler, warnings only
โ โโโ verbose.py โ StreamHandler, full context
โ โโโ file.py โ FileHandler
โ โโโ rotating_file.py โ RotatingFileHandler
โ โโโ ai.py โ StreamHandler + JSONFormatter
โโโ profiles/ โ prebuilt logger configurations
โ โโโ _base.py โ _build_profile() shared skeleton
โ โโโ observer.py
โ โโโ investigator.py
โ โโโ conspiracy_theorist.py
โ โโโ ai_agent.py
โโโ theories/ โ explore different theories to invent new experiments
โ โโโ _test_theory.py โ test a theory (even I don't know what'll happen)
โ โโโ my_stuff_exp.py
โ โโโ your_stuff_exp.py
โโโ logging_kernel/ โ shared infrastructure
โโโ errors.py โ full exception hierarchy
โโโ formatters.py โ JSONFormatter, log_event(), formatter factories
โโโ handlers.py โ _configure_handler(), get_log_dir()
โโโ normalisers.py โ normalises all params,
๐งฌ Philosophy
logger-lab is built on three principles:
- Modularity โ Logging behaviour should be reusable and composable.
- Clarity โ Logs should be easy to read and understand.
- Structure โ Logs should be usable as data, not just text.
Logs are not just for debugging. They are inputs for analysis, automation, and intelligence.
๐งช Experimental Features
Some features live in the experimental zone (theories):
from logger_lab import get_logger
from logger_lab.core.enums import TheoryType
# THEORIES (single handler factories):
theory_logger = get_logger(name="doom", theory=TheoryType.TIMED_FILE)
These are unstable and may change.
๐ค Contributing
Contributions are welcome.
Adding a new experiment
- Create
logger_lab/theories/your_name_exp.py - Define
your_name_experiment(level: int = DEBUG, **kwargs) -> list[logging.Handler] - Add the enum value to
TheoryTypeincore/enums.py - Manually register it in the THEORIES registry
- Test in
_test_theory.py - Document its purpose and behaviour
- After review, the Lab will add it to experiments logic
Adding a new profile
Currently just on a suggestion basis. I don't know about adding experimental logic for a profile
๐งญ Roadmap
- More experiments (
async,http,db,performance) - Advanced profiles
- AI-assisted debugging tools
- Distributed tracing support
-
py.typedmarker + full type stub coverage
๐งโ๐ป Author
Mosquito Lab (Cyber-Smoke) ๐ง mosquitolab2024@protonmail.com ๐ github.com/Mosquito-Lab/logger-lab
๐ License
MIT LICENSE
๐ฑ Status
STABLE RELEASE: v0.1.1
- Still in active development. New experiments, profiles, and capabilities are being added continuously.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file logger_lab-0.1.1.tar.gz.
File metadata
- Download URL: logger_lab-0.1.1.tar.gz
- Upload date:
- Size: 28.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
846743885e2e382b1c18ecfd9399d6596fcf7811231e2ced835ab5d3a77ff442
|
|
| MD5 |
4899b6fc3720571f0756cce426c2baf8
|
|
| BLAKE2b-256 |
a6c3c183d5e2962ac3b17089133cec59e30264d5b624420ae11e1f7364e1c86e
|
File details
Details for the file logger_lab-0.1.1-py3-none-any.whl.
File metadata
- Download URL: logger_lab-0.1.1-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6eee0210ceeecbc45a899212c74963949eaa030e9ee20a15054a0be082a4f683
|
|
| MD5 |
5540887f34a1a6078b06f90589b8dc76
|
|
| BLAKE2b-256 |
21463a52e656858c8b3d085c205256e944451a5d59a1ff8505356e301333c92c
|