📊 Logging

One-time logging configuration for all fh_saas modules.

🎯 Overview

Function Purpose
configure_logging One-time setup at app startup

📋 Environment Variables

Variable Default Description
FH_SAAS_LOG_LEVEL WARNING DEBUG, INFO, WARNING, ERROR
FH_SAAS_LOG_FILE (none) Path to log file (optional)

⚙️ configure_logging

from nbdev.showdoc import show_doc

source

configure_logging


def configure_logging(
    log_file:str=None, level:str=None, max_bytes:int=10000000, backup_count:int=5
):

Configure logging for all fh_saas modules - call once at app startup.

📖 Usage Examples

1. App Startup (call once in main.py)

from fh_saas.utils_log import configure_logging

# Option A: Use environment variables (recommended for production)
# Set FH_SAAS_LOG_LEVEL=INFO and FH_SAAS_LOG_FILE=./logs/app.log in .env
configure_logging()

# Option B: Explicit - console only
configure_logging(level='INFO')

# Option C: Console + rotating file
configure_logging(level='INFO', log_file='./logs/app.log')

2. In Any fh_saas Module (already done)

Every module in fh_saas declares a logger at the top:

# fh_saas/utils_oauth.py
import logging
logger = logging.getLogger(__name__)

def handle_login_request(request, session):
    logger.debug('Login request initiated')
    # ... do work ...
    logger.info(f'OAuth complete, redirecting to {redirect_url}')

3. Where Do Logs Go?

Configuration Console File
configure_logging()
configure_logging(log_file='app.log')
No configure_logging() call ❌ silent

4. Log Levels

Level When to Use Example
DEBUG Detailed diagnostic logger.debug('Checking user session')
INFO Normal operations logger.info('User logged in')
WARNING Unexpected but not failing logger.warning('Token expiring soon')
ERROR Operation failed logger.error('Auth failed', exc_info=True)

5. Real Example from fh_saas

# In your FastHTML app
from fasthtml.common import *
from fh_saas.utils_log import configure_logging
from fh_saas.utils_oauth import handle_login_request, handle_oauth_callback

# Configure logging ONCE at startup
configure_logging(level='INFO', log_file='./logs/app.log')

app = FastHTML()

@app.get('/login')
def login(request, session):
    return handle_login_request(request, session)  # Logs automatically

@app.get('/auth/callback') 
def callback(code: str, state: str, request, session):
    return handle_oauth_callback(code, state, request, session)  # Logs automatically

Output in console and file:

2026-01-10 14:30:00 | fh_saas.utils_oauth | DEBUG | Login request initiated
2026-01-10 14:30:05 | fh_saas.utils_oauth | DEBUG | OAuth callback received
2026-01-10 14:30:05 | fh_saas.utils_oauth | INFO | OAuth complete, redirecting to /dashboard