/

Fluent Syntax

Fluent Syntax

The fluent interface allows you to chain method calls together for expressive, readable logging code. Python's method chaining creates a natural, self-documenting style.

Method Chaining Basics

Chain methods together for elegant code:

Python
from bytehide_logs import Log

# Fluent chaining
Log.with_tags("payment") \
    .with_context("transaction_id", "txn_123") \
    .with_correlation_id("req_456") \
    .info("Payment processed")

Each method returns the same Log instance, allowing further method calls:

  • Log.with_tags() - Add tags
  • Log.with_context() - Add context data
  • Log.with_correlation_id() - Add correlation ID
  • Final logging method - info(), error(), warning(), etc.

Line Continuation with Backslash

Use backslash for line continuation in fluent chains:

Python
Log.with_tags("auth", "login") \
    .with_context("user_id", "user_123") \
    .with_context("ip_address", "192.168.1.1") \
    .with_context("timestamp", "2026-03-02T15:30:00Z") \
    .info("User login successful")

The backslash tells Python the statement continues on the next line. This keeps each method call clear and readable.

Formatting Chain Patterns

Different formatting styles for fluent chains:

Narrow Column Format (for files with width constraints)

Python
Log \
    .with_tags("payment") \
    .with_context("user_id", "u123") \
    .info("Payment complete")

Indented Format (most readable)

Python
Log.with_tags("order") \
    .with_context("order_id", "ord_456") \
    .with_context("total", 99.99) \
    .info("Order placed")

Compact Format (for simple chains)

Python
Log.with_tags("api").with_context("endpoint", "/users").info("API called")

Building Complex Context

Build rich context through fluent chaining:

Python
Log.with_tags("checkout", "payment", "card") \
    .with_context("customer_id", "cust_789") \
    .with_context("amount_cents", 2999) \
    .with_context("currency", "USD") \
    .with_context("card_last_four", "4242") \
    .with_correlation_id("checkout_req_123") \
    .info("Credit card processed successfully")

Multiple Tags in Fluent Style

Add multiple tags in a single call:

Python
# All tags in one call
Log.with_tags("user", "profile", "update").info("Profile updated")

# Tags in separate calls (also works)
Log.with_tags("user") \
    .with_tags("profile") \
    .with_tags("update") \
    .info("Profile updated")

Error Logging with Fluent Syntax

Build detailed error logs fluently:

Python
Log.with_tags("database", "query", "error") \
    .with_context("query_id", "q_abc123") \
    .with_context("table", "users") \
    .with_context("retry_attempt", 2) \
    .with_context("max_retries", 3) \
    .error("Database query failed", exception=db_error)

Fluent vs Non-Fluent Styles

Both approaches produce identical results:

Python
# Fluent style - expressive chaining
Log.with_tags("auth") \
    .with_context("method", "oauth") \
    .with_correlation_id("req_xyz") \
    .info("OAuth authentication successful")

# Direct style - all at once (if using exception= or context= parameters)
Log.info("OAuth authentication successful", context={
    "method": "oauth",
    "tags": ["auth"],
    "correlation_id": "req_xyz"
})

# Mixed style - some methods, some parameters
Log.with_tags("auth").info("OAuth authentication successful", context={
    "method": "oauth"
})

Choose the style that fits your code. The fluent style is often preferred for:

  • Long chains with many attributes
  • Progressive building of log entries
  • Readability in complex operations

Fluent Syntax in Functions

Write helper functions using fluent syntax:

Python
from bytehide_logs import Log

def log_payment_event(event_type, transaction_id, amount, status="pending"):
    """Log payment events with fluent syntax."""
    return Log.with_tags("payment", event_type) \
        .with_context("transaction_id", transaction_id) \
        .with_context("amount_cents", amount) \
        .with_context("status", status) \
        .with_correlation_id(get_current_correlation_id())

# Usage
log_payment_event("charge", "txn_123", 5999).info("Payment initiated")
log_payment_event("charge", "txn_123", 5999).info("Payment completed")
log_payment_event("refund", "txn_123", 5999).warning("Payment refunded")

Conditional Fluent Chains

Build chains conditionally:

Python
from bytehide_logs import Log

def log_user_action(action, user, **metadata):
    """Log user action with optional context."""
    log_entry = Log.with_tags("user", action)
    
    # Add user context if authenticated
    if user:
        log_entry = log_entry.with_context("user_id", user.id)
        if hasattr(user, "email"):
            log_entry = log_entry.with_context("email", user.email)
    
    # Add optional metadata
    for key, value in metadata.items():
        log_entry = log_entry.with_context(key, value)
    
    return log_entry

# Usage
user = get_current_user()
log_user_action("login", user, ip="192.168.1.1").info("User logged in")
log_user_action("logout", user).info("User logged out")

Fluent Syntax with Context Manager

Combine fluent syntax with Python's context managers:

Python
from contextlib import contextmanager
from bytehide_logs import Log
import time

@contextmanager
def log_operation(operation_name, **tags):
    """Log operation start and completion with timing."""
    log = Log.with_tags(operation_name, *tags.keys()) \
        .with_context("operation", operation_name)
    
    for key, value in tags.items():
        log = log.with_context(key, value)
    
    log.info("Operation started")
    start_time = time.time()
    
    try:
        yield log
    finally:
        elapsed = time.time() - start_time
        log.with_context("elapsed_ms", int(elapsed * 1000)).info("Operation completed")

# Usage
with log_operation("data_import", source="csv", count=1000) as log:
    import_data_from_csv()

Fluent Syntax with Exceptions

Chain methods while logging exceptions:

Python
from bytehide_logs import Log

try:
    risky_operation()
except PaymentError as e:
    Log.with_tags("payment", "error") \
        .with_context("error_code", e.code) \
        .with_context("retry_available", e.retry_available) \
        .with_correlation_id(get_correlation_id()) \
        .error("Payment processing failed", exception=e)

except Exception as e:
    Log.with_tags("error", "unexpected") \
        .with_context("error_type", type(e).__name__) \
        .error("Unexpected error occurred", exception=e)

Fluent Syntax in Loops

Log repetitive operations fluently:

Python
from bytehide_logs import Log

for item in items:
    try:
        result = process_item(item)
        Log.with_tags("batch", "item") \
            .with_context("item_id", item.id) \
            .with_context("batch_id", batch_id) \
            .with_context("result", result) \
            .info("Item processed successfully")
    except Exception as e:
        Log.with_tags("batch", "item", "error") \
            .with_context("item_id", item.id) \
            .with_context("batch_id", batch_id) \
            .error("Item processing failed", exception=e)

Formatting Guidelines

For consistent fluent syntax formatting:

Use backslash continuation for clarity:

Python
# Good - clear method order
Log.with_tags("operation") \
    .with_context("key", value) \
    .with_correlation_id("id") \
    .info("Message")

Keep lines within reasonable width (80-100 characters):

Python
# Good - readable line length
Log.with_tags("auth") \
    .with_context("user_id", user_id) \
    .info("Authentication successful")

# Avoid - very long single line
Log.with_tags("auth").with_context("user_id", user_id).with_context("auth_method", "oauth").with_context("timestamp", current_time).info("Authentication successful")

Align continuations for readability:

Python
# Good - aligned indentation
Log.with_tags("payment", "stripe") \
    .with_context("amount", 9999) \
    .with_context("currency", "USD") \
    .info("Charge created")

Complete Example

Python
from bytehide_logs import Log, LogSettings, AuthUser
from datetime import timedelta
import uuid

# Configure logging
settings = LogSettings(
    duplicate_suppression_window=timedelta(seconds=5),
    mask_sensitive_data=["password", "token", "api_key"]
)
Log.configure(settings)

def process_user_order(order_id, user_email, payment_token):
    """Process user order with fluent logging."""
    # Generate tracking IDs
    correlation_id = str(uuid.uuid4())
    user = AuthUser(id=order_id, email=user_email, token=payment_token)
    
    # Identify user
    Log.identify(user)
    
    # Log order start
    Log.with_tags("order", "processing") \
        .with_context("order_id", order_id) \
        .with_context("user_email", user_email) \
        .with_correlation_id(correlation_id) \
        .info("Order processing initiated")
    
    try:
        # Validate order
        Log.with_tags("order", "validation") \
            .with_context("order_id", order_id) \
            .with_correlation_id(correlation_id) \
            .info("Validating order details")
        validate_order(order_id)
        
        # Process payment
        Log.with_tags("order", "payment", "stripe") \
            .with_context("order_id", order_id) \
            .with_context("amount_cents", get_order_total(order_id)) \
            .with_correlation_id(correlation_id) \
            .info("Processing payment with Stripe")
        payment_result = process_stripe_payment(order_id)
        
        # Create shipment
        Log.with_tags("order", "fulfillment") \
            .with_context("order_id", order_id) \
            .with_context("transaction_id", payment_result.id) \
            .with_correlation_id(correlation_id) \
            .info("Creating shipment")
        shipment = create_shipment(order_id)
        
        # Success
        Log.with_tags("order", "complete") \
            .with_context("order_id", order_id) \
            .with_context("shipment_id", shipment.id) \
            .with_context("transaction_id", payment_result.id) \
            .with_correlation_id(correlation_id) \
            .info("Order processed successfully")
        
        return shipment
        
    except Exception as e:
        Log.with_tags("order", "error") \
            .with_context("order_id", order_id) \
            .with_context("error_message", str(e)) \
            .with_correlation_id(correlation_id) \
            .error("Order processing failed", exception=e)
        raise
    
    finally:
        Log.logout()

# Usage
try:
    shipment = process_user_order("ord_123", "user@example.com", "token_xyz")
except Exception as e:
    print(f"Order processing failed: {e}")

Next Steps

Previous
Exception Handling