Logger Binding and Registry Management

LogEverything provides powerful binding capabilities that allow you to create contextual loggers with additional structured data. This guide explains how binding works, registry management, and best practices for memory-safe logging.

🔗 Understanding Logger Binding

Logger binding follows the Loguru-style pattern where bound loggers share the same name and underlying logger instance, but add contextual information to all log records.

Key Concepts:

  • Base Logger: The original logger instance that’s registered in the global registry

  • Bound Logger: A new logger instance that shares the same name but adds context

  • Registry: The global store of logger instances for decorator and system use

  • Additive Context: Each bind operation adds new context while preserving existing context

Basic Binding Example

from logeverything import Logger

# Create a base logger (automatically registered)
log = Logger("user_service")
log.info("Service started")  # Basic log

# Create a bound logger with user context
user_log = log.bind(user_id=12345, session_id="abc123")
user_log.info("User logged in")  # Includes user_id and session_id

# Create another bound logger with additional context
request_log = user_log.bind(request_id="req-789", endpoint="/api/users")
request_log.info("Processing request")  # Includes all context: user_id, session_id, request_id, endpoint

# Original logger is unchanged
log.info("Service status check")  # Still basic log without extra context

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | Service started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | [user_id=12345 | session_id=abc123] User logged in
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | [user_id=12345 | session_id=abc123 | request_id=req-789 | endpoint=/api/users] Processing request
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | Service status check

Registry Behavior

Important Registry Rules:

  1. Only base loggers are registered in the global registry

  2. Bound loggers are NOT registered - they exist independently

  3. Bound loggers share the same name as their base logger

  4. Deleting a bound logger does NOT affect the base logger or registry

from logeverything import Logger
from logeverything.core import get_active_loggers

# Base logger gets registered
base_log = Logger("payment_service")
print(f"Active loggers: {list(get_active_loggers().keys())}")  # ['payment_service']

# Bound loggers are NOT registered
payment_log = base_log.bind(transaction_id="tx-123")
order_log = payment_log.bind(order_id="ord-456")

print(f"Active loggers: {list(get_active_loggers().keys())}")  # Still ['payment_service']
print(f"Base logger name: {base_log.name}")      # payment_service
print(f"Bound logger name: {payment_log.name}")  # payment_service (same name!)
print(f"Order logger name: {order_log.name}")    # payment_service (same name!)

# All loggers can log, but only base affects registry
base_log.info("Base logger message")
payment_log.info("Payment transaction started")
order_log.info("Order processing payment")

Output:

Active loggers: ['payment_service']
Active loggers: ['payment_service']
Base logger name: payment_service
Bound logger name: payment_service
Order logger name: payment_service
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | payment_service | Base logger message
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | payment_service | [transaction_id=tx-123] Payment transaction started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | payment_service | [transaction_id=tx-123 | order_id=ord-456] Order processing payment

Memory Management

LogEverything automatically manages memory for bound loggers:

from logeverything import Logger
import gc

def create_bound_loggers():
    """Create bound loggers that will go out of scope."""
    base_log = Logger("memory_test")

    # Create many bound loggers
    for i in range(100):
        bound_log = base_log.bind(iteration=i, timestamp=f"2024-01-{i:02d}")
        bound_log.info(f"Processing iteration {i}")

    # bound_log instances will be garbage collected when function exits
    return base_log

# Base logger remains in registry
base_logger = create_bound_loggers()

# Force garbage collection
gc.collect()

# Base logger still works and is registered
base_logger.info("All bound loggers cleaned up, base logger remains")

from logeverything.core import get_active_loggers
print(f"Registry still contains: {list(get_active_loggers().keys())}")

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=0 | timestamp=2024-01-00] Processing iteration 0
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=1 | timestamp=2024-01-01] Processing iteration 1
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=2 | timestamp=2024-01-02] Processing iteration 2
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=3 | timestamp=2024-01-03] Processing iteration 3
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=4 | timestamp=2024-01-04] Processing iteration 4
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=5 | timestamp=2024-01-05] Processing iteration 5
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=6 | timestamp=2024-01-06] Processing iteration 6
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=7 | timestamp=2024-01-07] Processing iteration 7
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=8 | timestamp=2024-01-08] Processing iteration 8
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=9 | timestamp=2024-01-09] Processing iteration 9
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=10 | timestamp=2024-01-10] Processing iteration 10
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=11 | timestamp=2024-01-11] Processing iteration 11
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=12 | timestamp=2024-01-12] Processing iteration 12
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=13 | timestamp=2024-01-13] Processing iteration 13
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=14 | timestamp=2024-01-14] Processing iteration 14
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=15 | timestamp=2024-01-15] Processing iteration 15
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=16 | timestamp=2024-01-16] Processing iteration 16
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=17 | timestamp=2024-01-17] Processing iteration 17
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=18 | timestamp=2024-01-18] Processing iteration 18
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=19 | timestamp=2024-01-19] Processing iteration 19
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=20 | timestamp=2024-01-20] Processing iteration 20
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=21 | timestamp=2024-01-21] Processing iteration 21
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=22 | timestamp=2024-01-22] Processing iteration 22
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=23 | timestamp=2024-01-23] Processing iteration 23
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=24 | timestamp=2024-01-24] Processing iteration 24
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=25 | timestamp=2024-01-25] Processing iteration 25
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=26 | timestamp=2024-01-26] Processing iteration 26
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=27 | timestamp=2024-01-27] Processing iteration 27
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=28 | timestamp=2024-01-28] Processing iteration 28
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=29 | timestamp=2024-01-29] Processing iteration 29
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=30 | timestamp=2024-01-30] Processing iteration 30
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=31 | timestamp=2024-01-31] Processing iteration 31
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=32 | timestamp=2024-01-32] Processing iteration 32
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=33 | timestamp=2024-01-33] Processing iteration 33
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=34 | timestamp=2024-01-34] Processing iteration 34
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=35 | timestamp=2024-01-35] Processing iteration 35
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=36 | timestamp=2024-01-36] Processing iteration 36
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=37 | timestamp=2024-01-37] Processing iteration 37
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=38 | timestamp=2024-01-38] Processing iteration 38
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=39 | timestamp=2024-01-39] Processing iteration 39
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=40 | timestamp=2024-01-40] Processing iteration 40
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=41 | timestamp=2024-01-41] Processing iteration 41
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=42 | timestamp=2024-01-42] Processing iteration 42
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=43 | timestamp=2024-01-43] Processing iteration 43
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=44 | timestamp=2024-01-44] Processing iteration 44
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=45 | timestamp=2024-01-45] Processing iteration 45
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=46 | timestamp=2024-01-46] Processing iteration 46
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=47 | timestamp=2024-01-47] Processing iteration 47
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=48 | timestamp=2024-01-48] Processing iteration 48
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=49 | timestamp=2024-01-49] Processing iteration 49
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=50 | timestamp=2024-01-50] Processing iteration 50
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=51 | timestamp=2024-01-51] Processing iteration 51
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=52 | timestamp=2024-01-52] Processing iteration 52
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=53 | timestamp=2024-01-53] Processing iteration 53
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=54 | timestamp=2024-01-54] Processing iteration 54
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=55 | timestamp=2024-01-55] Processing iteration 55
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=56 | timestamp=2024-01-56] Processing iteration 56
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=57 | timestamp=2024-01-57] Processing iteration 57
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=58 | timestamp=2024-01-58] Processing iteration 58
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=59 | timestamp=2024-01-59] Processing iteration 59
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=60 | timestamp=2024-01-60] Processing iteration 60
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=61 | timestamp=2024-01-61] Processing iteration 61
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=62 | timestamp=2024-01-62] Processing iteration 62
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=63 | timestamp=2024-01-63] Processing iteration 63
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=64 | timestamp=2024-01-64] Processing iteration 64
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=65 | timestamp=2024-01-65] Processing iteration 65
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=66 | timestamp=2024-01-66] Processing iteration 66
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=67 | timestamp=2024-01-67] Processing iteration 67
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=68 | timestamp=2024-01-68] Processing iteration 68
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=69 | timestamp=2024-01-69] Processing iteration 69
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=70 | timestamp=2024-01-70] Processing iteration 70
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=71 | timestamp=2024-01-71] Processing iteration 71
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=72 | timestamp=2024-01-72] Processing iteration 72
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=73 | timestamp=2024-01-73] Processing iteration 73
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=74 | timestamp=2024-01-74] Processing iteration 74
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=75 | timestamp=2024-01-75] Processing iteration 75
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=76 | timestamp=2024-01-76] Processing iteration 76
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=77 | timestamp=2024-01-77] Processing iteration 77
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=78 | timestamp=2024-01-78] Processing iteration 78
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=79 | timestamp=2024-01-79] Processing iteration 79
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=80 | timestamp=2024-01-80] Processing iteration 80
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=81 | timestamp=2024-01-81] Processing iteration 81
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=82 | timestamp=2024-01-82] Processing iteration 82
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=83 | timestamp=2024-01-83] Processing iteration 83
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=84 | timestamp=2024-01-84] Processing iteration 84
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=85 | timestamp=2024-01-85] Processing iteration 85
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=86 | timestamp=2024-01-86] Processing iteration 86
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=87 | timestamp=2024-01-87] Processing iteration 87
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=88 | timestamp=2024-01-88] Processing iteration 88
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=89 | timestamp=2024-01-89] Processing iteration 89
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=90 | timestamp=2024-01-90] Processing iteration 90
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=91 | timestamp=2024-01-91] Processing iteration 91
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=92 | timestamp=2024-01-92] Processing iteration 92
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=93 | timestamp=2024-01-93] Processing iteration 93
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=94 | timestamp=2024-01-94] Processing iteration 94
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=95 | timestamp=2024-01-95] Processing iteration 95
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=96 | timestamp=2024-01-96] Processing iteration 96
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=97 | timestamp=2024-01-97] Processing iteration 97
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=98 | timestamp=2024-01-98] Processing iteration 98
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | [iteration=99 | timestamp=2024-01-99] Processing iteration 99
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | memory_test | All bound loggers cleaned up, base logger remains
Registry still contains: ['memory_test']

Async Logger Binding

AsyncLogger follows the same binding principles as the synchronous Logger:

from logeverything.asyncio import AsyncLogger
import asyncio

async def async_binding_demo():
    # Base async logger (registered)
    log = AsyncLogger("async_service")
    await log.ainfo("Async service started")

    # Bound async logger (not registered)
    user_log = log.bind(user_id=67890, session_type="async")
    await user_log.ainfo("Async user session started")

    # Chained binding
    request_log = user_log.bind(request_id="async-req-123")
    await request_log.ainfo("Async request processing")

    # All share the same name but have different contexts
    print(f"Base name: {log.name}")          # async_service
    print(f"User log name: {user_log.name}") # async_service
    print(f"Request log name: {request_log.name}") # async_service

await async_binding_demo()

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | async_service | Async service started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | async_service | [user_id=67890 | session_type=async] Async user session started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | async_service | [user_id=67890 | session_type=async | request_id=async-req-123] Async request processing
Base name: async_service
User log name: async_service
Request log name: async_service

Best Practices

1. Use Binding for Structured Logging

from logeverything import Logger

log = Logger("api_server")

# Good: Create request-scoped logger
def handle_request(request_id, user_id):
    request_log = log.bind(request_id=request_id, user_id=user_id)

    request_log.info("Request started")
    # ... process request ...
    request_log.info("Request completed")

# Simulate multiple requests
handle_request("req-001", 123)
handle_request("req-002", 456)

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | api_server | [request_id=req-001 | user_id=123] Request started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | api_server | [request_id=req-001 | user_id=123] Request completed
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | api_server | [request_id=req-002 | user_id=456] Request started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | api_server | [request_id=req-002 | user_id=456] Request completed

2. Bind Early, Use Throughout

from logeverything import Logger

class UserService:
    def __init__(self):
        self.log = Logger("user_service")

    def login_user(self, user_id, session_id):
        # Create user-scoped logger early
        user_log = self.log.bind(user_id=user_id, session_id=session_id)

        user_log.info("Login attempt")

        if self._validate_credentials(user_log):
            user_log.info("Login successful")
            return self._create_session(user_log)
        else:
            user_log.warning("Login failed")
            return None

    def _validate_credentials(self, user_log):
        user_log.debug("Validating credentials")
        return True  # Simplified

    def _create_session(self, user_log):
        user_log.debug("Creating user session")
        return "session_token"

# Usage
service = UserService()
service.login_user(user_id=789, session_id="sess-xyz")

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | [user_id=789 | session_id=sess-xyz] Login attempt
2026-05-01 05:38:59 | [ 🔍 DEBUG  ] | user_service | [user_id=789 | session_id=sess-xyz] Validating credentials
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | user_service | [user_id=789 | session_id=sess-xyz] Login successful
2026-05-01 05:38:59 | [ 🔍 DEBUG  ] | user_service | [user_id=789 | session_id=sess-xyz] Creating user session

3. Don’t Worry About Cleanup

from logeverything import Logger

# ✅ Good: Let bound loggers be garbage collected naturally
def process_batch(items):
    log = Logger("batch_processor")

    for item in items:
        # Create item-scoped logger
        item_log = log.bind(item_id=item["id"], item_type=item["type"])
        item_log.info("Processing item")

        # item_log will be cleaned up automatically when loop iteration ends

# ❌ Don't do this: Manual cleanup is unnecessary
def process_batch_manual_cleanup(items):
    log = Logger("batch_processor")
    bound_loggers = []

    for item in items:
        item_log = log.bind(item_id=item["id"])
        bound_loggers.append(item_log)  # Keeping references unnecessarily
        item_log.info("Processing item")

    # Manual cleanup is not needed
    del bound_loggers

# Test both approaches
test_items = [{"id": 1, "type": "A"}, {"id": 2, "type": "B"}]
process_batch(test_items)

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | batch_processor | [item_id=1 | item_type=A] Processing item
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | batch_processor | [item_id=2 | item_type=B] Processing item

Context vs Binding

Understand the difference between context managers and binding:

from logeverything import Logger

log = Logger("comparison_demo")
log.configure(visual_mode=True, use_symbols=True)

# Context managers: Hierarchical, temporary, visual indentation
with log.context("Data Processing"):
    log.info("🚀 Starting data processing")

    with log.context("Validation"):
        log.info("✅ Data validation passed")

    log.info("📊 Processing completed")

print("\\n" + "="*50 + "\\n")

# Binding: Persistent context, structured data, same indentation
batch_log = log.bind(batch_id="batch-123", source="api")
batch_log.info("📦 Batch processing started")

item_log = batch_log.bind(item_count=150)
item_log.info("📋 Items loaded for processing")

validation_log = item_log.bind(validation_rule="schema_v2")
validation_log.info("🔍 Running validation")
validation_log.info("✅ Validation successful")

# You can combine both approaches
with batch_log.context("Final Steps"):
    completion_log = batch_log.bind(processed_items=150, failed_items=0)
    completion_log.info("🎉 Batch processing completed successfully")

Output:

2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | ┌─► Data Processing
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |    🚀 Starting data processing
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |    ┌─► Validation
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |       ✅ Data validation passed
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |    └─◄ Validation complete
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |    📊 Processing completed
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | └─◄ Data Processing complete
\n==================================================\n
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | [batch_id=batch-123 | source=api] 📦 Batch processing started
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | [batch_id=batch-123 | source=api | item_count=150] 📋 Items loaded for processing
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | [batch_id=batch-123 | source=api | item_count=150 | validation_rule=schema_v2] 🔍 Running validation
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | [batch_id=batch-123 | source=api | item_count=150 | validation_rule=schema_v2] ✅ Validation successful
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | ┌─► Final Steps
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo |    [batch_id=batch-123 | source=api | processed_items=150 | failed_items=0] 🎉 Batch processing completed successfully
2026-05-01 05:38:59 | [  ℹ️ INFO  ] | comparison_demo | └─◄ Final Steps complete

Advanced Binding Patterns

Contextual Decorators with Binding

from logeverything import Logger, log_function

# Base logger for service
service_log = Logger("order_service")

@log_function(using="order_service")
def process_order(order_id, user_id):
    # Get the logger from the decorator context and bind it
    from logeverything.core import get_logger

    # Create order-scoped logger
    order_log = service_log.bind(order_id=order_id, user_id=user_id)

    order_log.info("Order processing started")

    # Simulate processing
    order_log.info("Inventory checked")
    order_log.info("Payment processed")
    order_log.info("Order fulfillment initiated")

    return {"status": "completed", "order_id": order_id}

# The decorator will log function entry/exit,
# while our bound logger provides detailed context
result = process_order("ord-789", 12345)

Output:

2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service | 🔵 CALL process_order(order_id='ord-789', user_id=12345) [tmpt67_n33s.py:70]
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service |    [order_id=ord-789 | user_id=12345] Order processing started
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service |    [order_id=ord-789 | user_id=12345] Inventory checked
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service |    [order_id=ord-789 | user_id=12345] Payment processed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service |    [order_id=ord-789 | user_id=12345] Order fulfillment initiated
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | order_service | ✅ DONE process_order (4.99ms) ➜ {'status': 'completed', 'order_id': 'ord-789'}

Thread-Safe Binding

from logeverything import Logger
import threading
import time

log = Logger("threaded_service")

def worker_thread(worker_id, tasks):
    # Each thread gets its own bound logger
    worker_log = log.bind(worker_id=worker_id, thread_name=threading.current_thread().name)

    worker_log.info("Worker started")

    for task_id in tasks:
        # Further bind for each task
        task_log = worker_log.bind(task_id=task_id)
        task_log.info("Processing task")
        time.sleep(0.1)  # Simulate work
        task_log.info("Task completed")

    worker_log.info("Worker finished")

# Start multiple threads
threads = []
for i in range(3):
    tasks = [f"task-{i}-{j}" for j in range(2)]
    t = threading.Thread(target=worker_thread, args=(f"worker-{i}", tasks))
    threads.append(t)
    t.start()

# Wait for completion
for t in threads:
    t.join()

log.info("All workers completed")

Output:

2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread)] Worker started
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread)] Worker started
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread) | task_id=task-0-0] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread) | task_id=task-1-0] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread)] Worker started
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread) | task_id=task-2-0] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread) | task_id=task-0-0] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread) | task_id=task-1-0] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread) | task_id=task-2-0] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread) | task_id=task-0-1] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread) | task_id=task-1-1] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread) | task_id=task-2-1] Processing task
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread) | task_id=task-1-1] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread) | task_id=task-0-1] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-0 | thread_name=Thread-1 (worker_thread)] Worker finished
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-1 | thread_name=Thread-2 (worker_thread)] Worker finished
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread) | task_id=task-2-1] Task completed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | [worker_id=worker-2 | thread_name=Thread-3 (worker_thread)] Worker finished
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | threaded_service | All workers completed

Registry Inspection

You can inspect the logger registry for debugging:

from logeverything import Logger
from logeverything.core import get_active_loggers

# Create several base loggers
auth_log = Logger("auth_service")
user_log = Logger("user_service")
order_log = Logger("order_service")

# Create bound loggers
admin_log = auth_log.bind(role="admin")
guest_log = auth_log.bind(role="guest")
vip_user_log = user_log.bind(tier="vip")

# Check registry - only base loggers appear
active_loggers = get_active_loggers()
print("Registered loggers:")
for name, logger in active_loggers.items():
    print(f"  {name}: {logger}")

print(f"\\nTotal registered: {len(active_loggers)}")
print(f"Expected: 3 (auth_service, user_service, order_service)")

# Bound loggers work but aren't registered
admin_log.info("Admin action performed")
vip_user_log.info("VIP user activity")

Output:

Registered loggers:
  auth_service: Logger(name='auth_service')
  user_service: Logger(name='user_service')
  order_service: Logger(name='order_service')
\nTotal registered: 3
Expected: 3 (auth_service, user_service, order_service)
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | auth_service  | [role=admin] Admin action performed
2026-05-01 05:39:00 | [  ℹ️ INFO  ] | user_service  | [tier=vip] VIP user activity

Migration from Other Libraries

If migrating from other logging libraries, here’s how LogEverything’s binding compares:

From Python’s logging with extra

# Old way with Python logging
import logging
logger = logging.getLogger("app")
logger.info("User action", extra={"user_id": 123, "action": "login"})

# LogEverything way
from logeverything import Logger
log = Logger("app")
user_log = log.bind(user_id=123)
user_log.info("User action", action="login")  # Cleaner and more reusable

From Loguru

# Loguru
from loguru import logger
user_logger = logger.bind(user_id=123)
user_logger.info("User action")

# LogEverything (similar pattern!)
from logeverything import Logger
log = Logger("app")
user_log = log.bind(user_id=123)
user_log.info("User action")

From structlog

# structlog
import structlog
logger = structlog.get_logger()
user_logger = logger.bind(user_id=123)
user_logger.info("User action")

# LogEverything
from logeverything import Logger
log = Logger("app")
user_log = log.bind(user_id=123)
user_log.info("User action")

Summary

Key Takeaways:

Use binding for structured, contextual loggingBound loggers share names but add contextOnly base loggers are registered in the global registryMemory management is automatic - no manual cleanup neededBinding works the same for both Logger and AsyncLoggerCombine binding with context managers for powerful logging patterns

Registry Safety: - Base loggers: Registered and managed by the system - Bound loggers: Independent, automatically cleaned up - No risk of registry pollution or memory leaks - Thread-safe and async-safe operations

This binding system provides the structured logging benefits of libraries like Loguru and structlog while maintaining LogEverything’s performance advantages and visual formatting capabilities.