Logging

The Cloudflare SaaS Platform library includes a comprehensive, configurable logging system to help you monitor operations, debug issues, and track platform activity.

Overview

The logging system provides:

  • Multiple log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL

  • Flexible formats: Simple, detailed, and JSON formats

  • Console and file output: Log to stdout and/or files

  • Rotating file handlers: Automatic log rotation with size limits

  • Per-module loggers: Fine-grained control over logging

  • Third-party library control: Manage verbosity of dependencies

Quick Start

Basic Configuration

from cloudflare_saas import configure_logging, LogLevel, LogFormat

# Configure logging at application startup
configure_logging(
    level=LogLevel.INFO,
    log_format=LogFormat.DETAILED
)

With File Output

from cloudflare_saas import configure_logging, LogLevel, LogFormat

configure_logging(
    level=LogLevel.DEBUG,
    log_format=LogFormat.JSON,
    log_file="cloudflare-saas.log",
    enable_console=True
)

Log Levels

The library supports standard Python logging levels:

Level

Numeric

Use Case

DEBUG

10

Detailed information for diagnosing problems

INFO

20

General informational messages about operations

WARNING

30

Warning messages for potentially harmful situations

ERROR

40

Error events that might still allow operation

CRITICAL

50

Serious errors indicating system failure

Example Usage

from cloudflare_saas import LogLevel, configure_logging

# Development
configure_logging(level=LogLevel.DEBUG)

# Production
configure_logging(level=LogLevel.WARNING)

# Critical issues only
configure_logging(level=LogLevel.CRITICAL)

Log Formats

Three built-in formats are available:

Simple Format

Minimal output for development:

INFO: Creating tenant: name=Acme Inc, slug=acme
WARNING: Deployment path does not exist: /invalid/path
from cloudflare_saas import LogFormat, configure_logging

configure_logging(log_format=LogFormat.SIMPLE)

Detailed Format

Comprehensive information with timestamps and source location:

2025-12-17 10:30:45 - CloudflareSaaSPlatform - INFO - [platform.py:65] - Creating tenant: name=Acme Inc, slug=acme
2025-12-17 10:30:46 - R2Client - DEBUG - [r2_client.py:45] - Uploading file: /path/to/file
configure_logging(log_format=LogFormat.DETAILED)

JSON Format

Structured logging for production systems and log aggregators:

{"time": "2025-12-17 10:30:45", "name": "CloudflareSaaSPlatform", "level": "INFO", "file": "platform.py", "line": 65, "message": "Creating tenant: name=Acme Inc, slug=acme"}
configure_logging(log_format=LogFormat.JSON)

File Logging

Rotating File Handler

Logs automatically rotate when they reach 10MB:

from cloudflare_saas import configure_logging, LogLevel

configure_logging(
    level=LogLevel.INFO,
    log_file="/var/log/cloudflare-saas/app.log",
    enable_console=False
)

This creates: - app.log (current log) - app.log.1 (first backup) - app.log.2 (second backup) - … up to app.log.5 (fifth backup)

Console and File Together

Log to both console and file:

configure_logging(
    level=LogLevel.INFO,
    log_file="app.log",
    enable_console=True
)

Using Loggers

Getting a Logger

from cloudflare_saas import get_logger

logger = get_logger(__name__)

logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical message")

Logger Mixin

For classes, use the LoggerMixin:

from cloudflare_saas import LoggerMixin

class MyService(LoggerMixin):
    def do_work(self):
        self.logger.info("Starting work")
        try:
            # ... work ...
            self.logger.info("Work completed successfully")
        except Exception as e:
            self.logger.error(f"Work failed: {e}")
            raise

Configuration Reference

configure_logging()

cloudflare_saas.configure_logging(level: LogLevel = LogLevel.INFO, log_format: LogFormat = LogFormat.DETAILED, log_file: str | None = None, enable_console: bool = True) None[source]

Configure logging for the application.

Parameters:
  • level – The logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)

  • log_format – The format of log messages (simple, detailed, json)

  • log_file – Optional file path to write logs to

  • enable_console – Whether to enable console output

Examples

>>> from cloudflare_saas.logging_config import configure_logging, LogLevel, LogFormat
>>> configure_logging(level=LogLevel.DEBUG, log_format=LogFormat.JSON)
>>> configure_logging(level=LogLevel.INFO, log_file="app.log")

get_logger()

cloudflare_saas.get_logger(name: str) Logger[source]

Get a logger instance.

Parameters:

name – The name of the logger (typically __name__)

Returns:

A configured logger instance

Examples

>>> from cloudflare_saas.logging_config import get_logger
>>> logger = get_logger(__name__)
>>> logger.info("Starting operation")

LogLevel

class cloudflare_saas.LogLevel(value)[source]

Logging levels.

DEBUG = 'DEBUG'
INFO = 'INFO'
WARNING = 'WARNING'
ERROR = 'ERROR'
CRITICAL = 'CRITICAL'

LogFormat

class cloudflare_saas.LogFormat(value)[source]

Log output formats.

SIMPLE = 'simple'
DETAILED = 'detailed'
JSON = 'json'

LoggerMixin

class cloudflare_saas.LoggerMixin[source]

Mixin class to add logging capability to any class.

Examples

>>> class MyService(LoggerMixin):
...     def do_work(self):
...         self.logger.info("Doing work")
property logger: Logger

Get logger for this class.

Examples

Development Setup

from cloudflare_saas import configure_logging, LogLevel, LogFormat

configure_logging(
    level=LogLevel.DEBUG,
    log_format=LogFormat.DETAILED,
    enable_console=True
)

Production Setup

from cloudflare_saas import configure_logging, LogLevel, LogFormat

configure_logging(
    level=LogLevel.WARNING,
    log_format=LogFormat.JSON,
    log_file="/var/log/cloudflare-saas/production.log",
    enable_console=False
)

Docker/Container Setup

import os
from cloudflare_saas import configure_logging, LogLevel, LogFormat

configure_logging(
    level=LogLevel(os.getenv("LOG_LEVEL", "INFO")),
    log_format=LogFormat.JSON,  # JSON for log aggregation
    enable_console=True,  # Log to stdout for container logs
    log_file=None  # Don't use file in containers
)

Custom Logger Configuration

from cloudflare_saas import get_logger

# Get logger for specific module
logger = get_logger("my_module")

# Use throughout your code
logger.info("Starting operation")
logger.debug(f"Processing {count} items")
logger.error(f"Failed to process item {item_id}")

Integration with Config

The Config class includes logging options:

from cloudflare_saas import Config, CloudflareSaaSPlatform

config = Config(
    # ... other config ...
    log_level="DEBUG",
    log_format="json",
    log_file="app.log",
    enable_console_logging=True
)

# Platform automatically configures logging
platform = CloudflareSaaSPlatform(config)

Environment Variables

# .env file
LOG_LEVEL=DEBUG
LOG_FORMAT=json
LOG_FILE=/var/log/cloudflare-saas.log
ENABLE_CONSOLE_LOGGING=true
from cloudflare_saas import Config, CloudflareSaaSPlatform

config = Config.from_env()
platform = CloudflareSaaSPlatform(config)  # Logging auto-configured

Third-Party Library Logging

The logging configuration automatically manages verbosity of dependencies:

  • httpx: Set to WARNING (reduces HTTP request logging noise)

  • httpcore: Set to WARNING

  • aioboto3: Set to WARNING

You can override these by accessing the logger directly:

import logging

# Enable debug logging for httpx
logging.getLogger("httpx").setLevel(logging.DEBUG)

Best Practices

  1. Configure Early: Set up logging at application startup

  2. Use Appropriate Levels: DEBUG for development, WARNING/ERROR for production

  3. Structured Logging: Use JSON format for production log aggregation

  4. Context in Messages: Include relevant details in log messages

  5. Avoid Secrets: Never log sensitive information (tokens, passwords, etc.)

  6. File Rotation: Let the system handle log rotation automatically

  7. Container Logging: Use console output (stdout) in containers

Troubleshooting

Logs Not Appearing

Check that:

  1. Logging is configured before other imports

  2. Log level is not too restrictive

  3. Console output is enabled if expecting stdout

  4. File path is writable

Too Verbose

Reduce log level:

configure_logging(level=LogLevel.WARNING)

Or disable console output:

configure_logging(enable_console=False)

See Also