Centralized logging configuration using loguru with environment-based levels, third-party interception, and structured logging.
home / developer / concepts / core / logging
Logging System¶
Tux uses loguru for all logging, providing a single global logger configured once at startup. The logging system routes all application and third-party library logs through loguru with consistent formatting, making debugging easier.
Overview¶
The logging system provides:
- Single Global Logger - One logger configured for the entire application
- Environment-Based Configuration - Log levels set via
.envfile - Third-Party Interception - All library logs routed through loguru
- IDE-Clickable Paths - File paths in logs are clickable in your IDE
- Structured Logging - Support for structured data in log messages
Basic Usage¶
Import and use the logger directly—it's pre-configured:
from loguru import logger
logger.info("Bot started successfully")
logger.debug("Processing user request", user_id=12345)
logger.warning("Rate limit approaching", remaining=5)
logger.error("Database connection failed", error=str(e))
The logger is configured automatically when Tux starts. You don't need to set it up yourself.
Log Levels¶
Tux uses standard loguru log levels. Choose the appropriate level based on the importance and detail of your message:
TRACE¶
Use for very detailed debugging—function entry/exit, variable dumps, and step-by-step execution tracking. Only enabled in development.
logger.trace("Function entered", arg1=value1, arg2=value2)
DEBUG¶
Use for development debugging—SQL queries, API calls, internal state, and detailed execution flow. Helpful when troubleshooting issues.
logger.debug("Database query executed", query=sql, duration=0.045)
logger.debug("Cache miss, fetching from database", key=cache_key)
INFO¶
Use for normal operations—startup/shutdown messages, user actions, important state changes, and general application flow.
logger.info("Bot connected to Discord")
logger.info(f"User {user_id} executed command '{command}'")
logger.info("Database migration completed", version="abc123")
SUCCESS¶
Use for successful operations, achievements, and positive outcomes. More visible than INFO for important successes.
logger.success("User account created successfully", user_id=12345)
logger.success("Configuration saved", guild_id=67890)
WARNING¶
Use for potentially problematic situations—rate limits approaching, deprecated features, configuration issues, and recoverable errors.
logger.warning("Rate limit approaching", remaining=5)
logger.warning("Using deprecated configuration option", option="old_setting")
ERROR¶
Use for errors that don't stop the application—failed operations, caught exceptions, and recoverable failures.
logger.error("Failed to send message", channel_id=12345, error=str(e))
logger.error("Database query failed", query=sql, error=str(e))
CRITICAL¶
Use for critical errors that might stop the application—unrecoverable failures, missing critical configuration, and fatal errors.
logger.critical("Database connection lost", error=str(e))
logger.critical("Missing required configuration", setting="BOT_TOKEN")
Configuration¶
Log Level Priority¶
Log levels are determined in this order (highest to lowest priority):
- Explicit Parameter -
configure_logging(level="DEBUG")for testing - Environment Variable -
LOG_LEVEL=DEBUGin.envfile - Debug Flag -
DEBUG=1in.envsets DEBUG level automatically - Default -
INFOlevel if nothing is configured
Environment Configuration¶
Set the log level in your .env file:
# Set specific log level
LOG_LEVEL=DEBUG
# Or enable debug mode (sets DEBUG level)
DEBUG=1
The logging system reads these values automatically at startup.
Testing Configuration¶
For tests, use explicit level configuration:
from tux.core.logging import configure_testing_logging
configure_testing_logging() # Sets DEBUG level for tests
Log Formatting¶
Logs are formatted with consistent structure:
HH:mm:ss.SSS | LEVEL | location:line | message
For Tux code, the location shows clickable file paths like src/tux/core/app.py:167. For third-party libraries, it shows module and function names like discord.gateway:on_ready.
Structured Logging¶
Include structured data in your log messages:
logger.info("User action", user_id=12345, action="ban", target_id=67890)
logger.debug("Cache operation", operation="get", key="user:12345", hit=True)
Structured data appears in logs and can be parsed by log aggregation tools.
Third-Party Library Logs¶
The logging system automatically intercepts logs from third-party libraries and routes them through loguru. This includes:
- Discord.py (discord, discord.client, discord.gateway, discord.http)
- Database libraries (sqlalchemy, asyncpg, psycopg)
- HTTP clients (httpx, aiohttp, urllib3)
- Other common libraries
Third-party logs use appropriate log levels to reduce noise. For example, Discord gateway events are logged at INFO level, while verbose DEBUG messages are suppressed.
IDE Integration¶
Log messages include clickable file paths for Tux code. Clicking a path in your IDE opens the file at that line, making debugging faster. Paths are relative to the project root, so they work across different development environments.
Best Practices¶
Use Appropriate Levels¶
Choose log levels based on importance. Don't use ERROR for warnings, or DEBUG for normal operations. Consistent level usage makes logs easier to filter and understand.
Include Context¶
Add relevant context to log messages. Include user IDs, guild IDs, command names, or other identifiers that help trace issues:
# Good: Includes context
logger.error("Failed to ban user", user_id=12345, guild_id=67890, error=str(e))
# Bad: Missing context
logger.error("Failed to ban user")
Avoid Sensitive Data¶
Never log passwords, API keys, tokens, or other sensitive information. Log enough context to debug issues without exposing secrets.
Use Structured Data¶
Prefer structured logging over string formatting for better parsing:
# Good: Structured data
logger.info("Command executed", command="ban", user_id=12345, success=True)
# Less ideal: String formatting
logger.info(f"Command ban executed by user {user_id}, success: {success}")
Don't Over-Log¶
Avoid logging in tight loops or high-frequency operations. Too many logs make it hard to find important information. Use DEBUG level for detailed logging that can be disabled in production.
Troubleshooting¶
Logs Not Appearing¶
If logs aren't appearing:
- Check your log level configuration in
.env - Verify the logging system is initialized at startup
- Ensure you're using the correct log level for your messages
Too Many Logs¶
If logs are too verbose:
- Increase log level to WARNING or ERROR
- Check third-party library log levels
- Reduce DEBUG logging in your code
Missing Context¶
If logs lack context:
- Add structured data to log messages
- Include relevant IDs and identifiers
- Use appropriate log levels for visibility
Resources¶
- Source Code:
src/tux/core/logging.py - Loguru Documentation: https://loguru.readthedocs.io/
- Best Practices: See
developer/best-practices/logging.mdfor detailed guidelines