loggio 2025.12.14
Comprehensive logging utility with colored output, user context tracking, and automatic truncation.
Requires Python: >=3.10
Keywords: automatic truncation, colored, debugging, enhanced, logger, logging, terminal, user context

# Enhanced Logger Loggio

A comprehensive logging utility for project that provides:

- Timestamp information in logs
- User ID tracking for authenticated requests
- File name and line number of the log call
- Clean and consistent log formatting
- Multiple usage patterns for different scenarios

## Features

- **Contextual Information**: Every log includes timestamp, log level, file
  name, and line number
- **Timezone Support**: Configure timestamps to display in any timezone (UTC,
  US/Pacific, Europe/London, etc.)
- **Authentication Awareness**: Can include user ID in logs when available
- **Format String Support**: Supports Python's standard string formatting with
  %s, %d, etc.
- **Flexible Configuration**: Configurable output destination (terminal and/or
  file)
- **Consistent API**: Familiar logging methods (debug, info, warning, error,
  critical)
- **Colored Output**: Color-coded log levels for better readability in terminal

## Installation

### From PyPI (Recommended)

```bash
pip install loggio
```

Then import in your code:

```python
from loggio import get_logger
```

### From Source

To use standalone, use as a fork.

To get updates, use as a submodule.

#### As standalone

Go to inside your project.

Clone the repository:

```bash
git clone https://github.com/xcollantes/loggio loggio
```

#### As submodule to existing repo

Go to where you want to dependency.

Clone the repository as submodule:

`loggio` must be maintained since Python import statements don't work
work hyphens.

```bash
git submodule add https://github.com/xcollantes/loggio loggio
```

#### Cloning your project that contains submodules

Clone the repository with submodules:

```bash
git clone --recursive https://github.com/xcollantes/my-project-with-submodules
```

Remember `--recursive` for submodules.

If you clone without --recursive:

```bash
git submodule update --init --recursive
```

#### Create and Activate Virtual Environment

```bash
# Create virtual environment.
python3 -m venv env

# Activate virtual environment.
# On macOS/Linux:
source env/bin/activate

# On Windows:
# venv\Scripts\activate
```

#### Install Dependencies

```bash
pip install -r requirements.txt
```

#### Environment Configuration

Create a `.env` file in the project root with the required environment
variables. The following variables are used by the application:

#### Running the Application

#### Basic Usage

```bash
python3 main.py
```

## Usage Examples

### Basic Usage (No Authentication)

For utility functions, background tasks, or non-authenticated endpoints:

```python
from loggio import get_logger

# Create a logger instance.
logger = get_logger(name="module.name")

# Log messages with different levels
logger.debug("This is a debug message.")
logger.info("This is an info message.")
logger.warning("This is a warning message.")
```

Output example:

```text
INFO:2023-05-01 14:30:45:example.py:24:This is an info message.
```

### Using Format Strings

The logger supports Python's standard string formatting:

```python
from loggio import get_logger

logger = get_logger(name="module.formatter")

# Using format strings
item_id = "A123"
priority = 2
logger.info("Processing item %s with priority %d", item_id, priority)
```

Output example:

```text
INFO:2023-05-01 14:31:22:formatter.py:15:Processing item A123 with priority 2
```

### Usage with User Context

When you have authentication info:

```python
from loggio import get_logger

# Create a logger instance.
logger = get_logger(name="module.auth")

# Get user info from somewhere (e.g., decoded token)
user_info = {"uid": "user123", "email": "user@example.com"}

# Log with user context
logger.info("User performed an action.", user_context=user_info)
```

Output example:

```text
INFO:2023-05-01 14:32:10:auth_service.py:45:user123: User performed an action.
```

### Format Strings with User Context

Combining format strings with user context:

```python
logger.info("Processing file %s for action %s", filename, action, user_context=user_info)
```

### Error Handling with Logging

```python
try:
    # Some risky operation
    result = perform_risky_operation()
    logger.info(f"Operation successful: {result}")
except Exception as e:
    logger.error(f"Operation failed: {str(e)}")
    # Handle or re-raise as appropriate
```

## Configuration Options

When creating a logger instance, you can configure:

- `name`: Logger name for filtering and organization (e.g., "api.auth",
  "service.processor")
- `level`: Minimum log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) - defaults
  to "INFO"
- `fileout_path`: Path for log file. Set to `None` to disable file logging
  (default: "logs/app.log")
- `terminal`: Whether to output logs to the terminal/console (default: True)
- `timezone`: Timezone for timestamps (e.g., "UTC", "US/Pacific", "Europe/London").
  Defaults to None (local time)
- `use_colors`: Whether to use colored output in terminal (default: True)
- `truncate`: Whether to truncate long messages (default: True)
- `truncate_length`: Maximum message length before truncation (default: 10000)
- `json_format`: Whether to format arguments as JSON (default: False)

Example with custom configuration:

```python
logger = get_logger(
    name="batch.processor",
    level="DEBUG",
    fileout_path="logs/batch_processor.log",
    terminal=True,
    timezone="UTC"
)
```

## Log Format

The logger produces logs in the following format:

```text
LEVEL:[TIMESTAMP]FILENAME:LINE_NUMBER:MESSAGE
```

Timestamps include timezone information with both timezone name and UTC offset:

```text
INFO:[2025-12-14 00:20:03 PST-0800]demo.py:42:This is a log message
INFO:[2025-12-14 08:20:03 UTC+0000]demo.py:42:Same message in UTC
INFO:[2025-12-14 17:20:03 JST+0900]demo.py:42:Same message in Tokyo time
```

With user context:

```text
INFO:[2025-12-14 14:35:22 UTC+0000]auth_routes.py:28:user123: Processing
protected resource request
```

## Timezone Configuration

### Using Timezones

By default, logs use your local system timezone. You can configure any IANA
timezone identifier:

```python
from loggio import get_logger

# Use UTC
logger = get_logger(timezone="UTC")
logger.info("This log is in UTC")

# Use US Pacific time
logger = get_logger(timezone="US/Pacific")
logger.info("This log is in Pacific time")

# Use Tokyo time
logger = get_logger(timezone="Asia/Tokyo")
logger.info("This log is in Tokyo time")
```

### Validating Timezones

The logger uses Python's `zoneinfo` module with the IANA timezone database.
You can validate timezone strings before using them:

```python
from loggio import get_logger, is_valid_timezone, get_available_timezones

# Check if a timezone is valid
if is_valid_timezone("America/New_York"):
    logger = get_logger(timezone="America/New_York")
    logger.info("Using valid timezone")

# Get all available timezones (598 total)
timezones = get_available_timezones()
print(f"Total timezones: {len(timezones)}")

# Find timezones for a region
europe_tzs = [tz for tz in timezones if tz.startswith("Europe")]
print(f"European timezones: {europe_tzs[:5]}")
```

### Changing Timezone Dynamically

Since the logger is a singleton, reconfiguring it will update the timezone for
all subsequent logs:

```python
# Start with UTC
logger = get_logger(timezone="UTC")
logger.info("Log in UTC")

# Switch to Pacific time
logger = get_logger(timezone="US/Pacific")
logger.info("Now logging in Pacific time")
```

### Common Timezones

**IANA Timezone Format:**

All timezone identifiers follow the IANA timezone database format:
`Region/City` (e.g., `America/New_York`, `Europe/London`)

**Americas:**

- `America/New_York` (EST/EDT)
- `America/Chicago` (CST/CDT)
- `America/Denver` (MST/MDT)
- `America/Los_Angeles` (PST/PDT)
- `US/Pacific`, `US/Eastern`, `US/Central`, `US/Mountain` (POSIX-style)

**Europe:**

- `Europe/London` (GMT/BST)
- `Europe/Paris` (CET/CEST)
- `Europe/Berlin` (CET/CEST)
- `Europe/Moscow` (MSK)

**Asia:**

- `Asia/Tokyo` (JST)
- `Asia/Shanghai` (CST)
- `Asia/Hong_Kong` (HKT)
- `Asia/Singapore` (SGT)

**Pacific:**

- `Australia/Sydney` (AEDT/AEST)
- `Pacific/Auckland` (NZDT/NZST)

**Special:**

- `UTC` - Coordinated Universal Time

**Note:** Abbreviations like "PST" or "EST" are NOT valid IANA identifiers.
Use `America/Los_Angeles` or `US/Pacific` instead of "PST", and
`America/New_York` or `US/Eastern` instead of "EST".

For a complete list of 598+ available timezones, use
`get_available_timezones()` or see the
[IANA timezone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).

## Best Practices

1. Use a hierarchical naming scheme for loggers (e.g., `api.auth`,
   `service.processor`)
2. Include meaningful context in log messages
3. Use the appropriate log level for different scenarios:
   - DEBUG: Detailed information for debugging
   - INFO: Confirmation that things are working as expected
   - WARNING: Something unexpected happened, but the application can continue
   - ERROR: A more serious problem that prevented a function from working
   - CRITICAL: A very serious error that might prevent the program from
     continuing
4. Include user context when available for better traceability
5. Include error details when logging exceptions
6. Consider using UTC timezone for production systems to avoid confusion across
   different timezones

## Implementation Details

The Enhanced Logger builds on Python's built-in logging module with custom
formatting and context handling. It uses:

- `stacklevel=2` to ensure the correct file and line number are recorded in
  the logs rather than showing the logger implementation file itself
- Python's `zoneinfo` module (Python 3.9+) for timezone support, providing
  access to the IANA timezone database
- ANSI color codes for terminal output with automatic color removal for file
  logging
- Singleton pattern to ensure consistent configuration across the application