Skip to main content

HyperLog

One import. Better logging. Simple. Batteries included.

Thin ergonomic layer: decorator + timing + prefixes + minimal structured context. Zero config by default.

Features:

  • Dual‑purpose object: log is both a decorator (@log() / @log) and logger (log.info(...))
  • Decorator adds automatic timing + success (✓) / failure (✗) logs (sync & async)
  • Granular timing utilities: marks, elapsed, timer context, sequential checkpoints
  • Performance threshold filtering (threshold_ms) & verbose argument logging (verbose=True)
  • Lightweight structured context via bind() (and utilities to manage it)
  • Custom log levels (add_level) & optional SUCCESS convenience
  • File logging with sane rotation/retention defaults (add_file)
  • Simple global prefix (log.prefix) for service / component labeling

Install

pip install -U hyperlog

Smallest Possible Use

from hyperlog import log

@log  # or @log()
def embed_user_query(query):
    ...
    return embedded_query

Console (ms timing + success mark):

12:34:56.011 INFO     ✓ embed_user_query completed in 9.20ms

Walkthrough

Timing (4 ways)

1. Decorator timing – automatic for any function:

@log()
def search_vectors(query):
    # work
    return results
# → ✓ search_vectors completed in 45.23ms

2. Mark & elapsed – ad‑hoc sections:

log.mark("db_query")
results = database.search(query)
log.elapsed("db_query", log_level="info")  # logs Elapsed (db_query): 23.1ms

3. Timer context manager – block timing:

with log.timer("vectorstore_connection"):
    credentials = authenticate()
    client = get_client(credentials)
# → vectorstore_connection: 847.3ms

4. Checkpoints – sequential step timeline:

log.checkpoint("Initialize", reset=True)
results = search_vectors(query)
log.checkpoint("Vector search")
response = generate_response(context)
log.checkpoint("LLM inference")

Current output (numbered steps – the provided names are stored internally but not displayed yet):

→ Step 1: 0.0ms | Total: 0.0ms
→ Step 2: 45.2ms | Total: 45.2ms
→ Step 3: 10.2ms | Total: 55.4ms

Logging & Structured Data

Basic logging with structured data:

log.info("Vector search", query=query[:50], collection="docs", threshold=0.8)
# Output: Vector search | query=What is machine learning? collection=docs threshold=0.8

log.debug("Cache hit", key="user:123", ttl=3600)
log.warning("Rate limit approaching", current=95, max=100, endpoint="/api/search")
log.error("Payment failed", user_id=456, amount=29.99, error_code="INSUFFICIENT_FUNDS")

Binding Context Fields

Create logger instances with persistent fields that attach to all subsequent logs:

# Create a bound logger for a specific service
billing_log = log.bind(service="billing", version="1.0")
billing_log.info("Charge created", amount=19.99)
# Fields service=billing version=1.0 amount=19.99 are in record.extra

# Managing bound fields on the global logger
log.bind(request_id="abc-123")  # Adds request_id to all subsequent logs
log.info("Processing request")  # Includes request_id=abc-123
log.unbind("request_id")  # Remove specific field
log.unbind_all()  # Remove all bound fields

Decorator Options

@log(
    level="DEBUG",        # override completion log level (default INFO)
    prefix="[Stage] ",     # per-function prefix (prepended to messages)
    tags=["etl", "batch"], # stored in record extra (not shown unless format includes {extra})
    threshold_ms=50,        # only emit completion log if runtime >= 50ms
    verbose=True,           # log call args at DEBUG before execution
    catch=True              # wrap with loguru.catch (re-raises after logging)
)
def transform(df):
    ...

Decorator behavior:

  • On success: ✓ function_name completed in XX.XXms
  • On exception: ✗ function_name failed after XX.XXms (logged at ERROR) then re-raised
  • verbose=True adds a DEBUG line like: → transform((args_repr), {'kw': 'vals'})
  • threshold_ms suppresses fast successes (still logs failures)

Custom Levels

log.add_level("TRACE", 5, color="<magenta>")
log.trace("Deep details")

# SUCCESS may already exist (recent loguru). Only add if missing.
log.add_level("SUCCESS", 25, color="<green>")
log.success("Pipeline complete")

File Logging

log.add_file("app.log", rotation="10 MB", retention="1 week")
# rotation examples: "10 MB", "1 day", "1 week"
# retention can be duration ("1 week") or number (e.g. 3)

Sensible defaults enabled: backtrace & diagnose for rich tracebacks.

Prefixes

Set a prefix to identify different services or modules:

# auth.py
from hyperlog import log
log.prefix = "[AUTH] "
log.info("Login attempt")  # [AUTH] Login attempt

# database.py
from hyperlog import log
log.prefix = "[DB] "
log.info("Query executed")  # [DB] Query executed

# main.py
from hyperlog import log
log.prefix = "[MAIN] "
log.info("Application started")  # [MAIN] Application started

The prefix applies to every emission (including decorator success/failure outputs).


Put It All Together (RAG Mini Pipeline)

from hyperlog import log

log.prefix = "[RAG] "
log.add_file("rag.log", rotation="1 day")

@log()
def search_vectors(query, collection="documents"):
    log.mark("db_connection")
    log.info("Vector search", query=query[:50], collection=collection, threshold=0.85)
    # ... search logic ...
    log.elapsed("db_connection", log_level="debug")
    return [{"doc": "ml_guide.pdf", "score": 0.91}]

@log()
def generate_response(context, model="gpt-4"):
    with log.timer("llm_inference"):
        log.info("LLM call", model=model, context_tokens=len(context.split()), max_tokens=200)
        # ... LLM call ...
        return "Machine learning is a subset of AI..."

log.checkpoint("Pipeline start", reset=True)
results = search_vectors("What is machine learning?", collection="ml_docs")
log.checkpoint("Vector search complete")

context = f"Context: {results[0]['doc']} (relevance: {results[0]['score']})"
response = generate_response(context, model="gpt-4-turbo")
log.checkpoint("Response generated")

log.info("Pipeline complete", docs_found=len(results), response_length=len(response))

Sample console (note: decorator completion in ms, timer may auto-switch to seconds if >1s):

12:45:30.001 INFO     [RAG] → Step 1: 0.0ms | Total: 0.0ms
12:45:30.002 INFO     [RAG] Vector search
12:45:30.352 DEBUG    [RAG] Elapsed (db_connection): 349.8ms
12:45:30.353 INFO     [RAG] ✓ search_vectors completed in 351.20ms
12:45:30.354 INFO     [RAG] → Step 2: 351.2ms | Total: 351.2ms
12:45:30.355 INFO     [RAG] LLM call
12:45:31.878 INFO     [RAG] llm_inference: 1.52s
12:45:31.879 INFO     [RAG] ✓ generate_response completed in 1520.10ms
12:45:31.880 INFO     [RAG] → Step 3: 1.52s | Total: 1.87s
12:45:31.881 INFO     [RAG] Pipeline complete

Observability Benefits:

  • Identify bottlenecks instantly (search vs inference)
  • Sequential timeline of multi-step flows
  • Optional structured metadata (via bind / kwargs) without config
  • Production friendly file sinks & prefixes

Public API Quick Reference

log.debug/info/warning/error/critical/success/<whatever_else_you_add>
@log / @log(...) decorator (options above)
log.prefix (string)
log.add_file(path, rotation, retention, compression, level)
log.add_level(name, severity, color)
log.mark(name) / log.elapsed(name, unit, log_level)
log.checkpoint(name, reset)
log.timer(name, log_level, unit)
log.bind / log.unbind / log.unbind_all log.catch (direct access to loguru catcher)


Notes / Gotchas

  • Extra fields (kwargs, bound fields, tags, duration_ms) are present in record.extra even if not visible. Include {extra} in your format to display.
  • Decorator duration units are always ms; timer & checkpoint total/step formatting auto-switch between μs/ms/s/min.
  • Checkpoint names currently not printed (only step numbers) – future enhancement may show them.
  • SUCCESS level: Added automatically only if you call add_level and it doesn't already exist in your loguru version.

Enjoy. Minimal surface, progressive enhancement. If a feature adds mental overhead for marginal benefit, it probably won’t be added.

Metadata

Release files for hyperlog 0.2.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 hyperlog 0.2.0
File Size Uploaded
hyperlog-0.2.0.tar.gz 38.3 kB Details

Built distribution (wheel)

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

Total release size: 50.4 kB

Release files / hyperlog-0.2.0.tar.gz

Download URL hyperlog-0.2.0.tar.gz
Size 38.3 kB
Tags Source
SHA-256 checksum
How to use checksums
88c336af513a162d86b9200a757c99b073092b8119e746a8d0008c1c576f1924
BLAKE2b-256 checksum
How to use checksums
e4f5d788b7f3048495245f0c52960d70e0d6ecadc07d05acf8215b3828479c70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.13

Release files / hyperlog-0.2.0-py3-none-any.whl

Download URL hyperlog-0.2.0-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ce9220d0119b2030d73a64d520f10bd272e73a0801db1894dd2fc37c4c583fd
BLAKE2b-256 checksum
How to use checksums
156e3a45f7f5d418e8de35b623274e859525f6fef6fa2e779b7aafca9e4518c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.13

Release history Release notifications | RSS feed

This release

0.2.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