Basic Logging in Fastapi using Logger module

Published: (January 4, 2026 at 07:09 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

When an Application Crashes in Production

An application crashed in production and users weren’t sure what to do next.
I experienced this last year on a project I was working on. As the programmer, I had to race to the terminal to check the error and start debugging.

It wasn’t a pleasant experience—until a senior developer introduced me to catching and logging errors. I was familiar with the concepts but had never applied them in real life. After adding proper error handling, my programming life got a lot smoother.

Benefits of Logging and Catching Errors

  • Faster Debugging – Logs tell you what happened, when it happened, where it happened, and who triggered it.
  • Better Error Visibility in Production – In production you can’t print errors or attach a debugger. Logs are your only window into the production environment, which is especially critical for remote servers and APIs consumed by external clients.
  • Graceful Failure (Better UX) – Catching errors lets you return meaningful HTTP responses, avoid crashing the entire app, and keep services running even when something fails.
  • Security and Auditing – Logs help you detect suspicious behaviour, track who accessed what, and audit sensitive operations.

Practical Approach: Logging & Error Handling in FastAPI

Below is a minimal e‑commerce example that demonstrates how to set up logging and error handling in a FastAPI application.

Folder Structure

Folder Structure

schemas.py – Define Your Pydantic Models

from pydantic import BaseModel
from enum import Enum

class Status(str, Enum):
    AVAILABLE = "AVAILABLE"
    UNAVAILABLE = "UNAVAILABLE"

class ProductBase(BaseModel):
    name: str
    description: str
    price: float
    status: Status

class ProductCreate(ProductBase):
    pass

class ProductUpdate(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    status: Status | None = None

class Product(ProductBase):
    id: int

main.py – Set Up FastAPI, Logging, and In‑Memory “Database”

from fastapi import FastAPI, HTTPException, status, Response
import logging

from app.schemas import Product, ProductCreate, ProductUpdate

app = FastAPI()

# Configure logging – all logs go to app.log
logging.basicConfig(
    filename="app.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger(__name__)

# In‑memory list acting as a simple database
products: list[dict] = []

def fetch_product(product_id: int) -> dict | None:
    """Return a product dict matching the given id, or None if not found."""
    for product in products:
        if product["id"] == product_id:
            return product
    return None

Endpoints – Retrieve All Products & a Single Product

@app.get("/", response_model=list[Product])
def get_products():
    """Return the list of all products."""
    try:
        return products
    except Exception as e:
        logger.error(f"Unexpected error while getting products: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="An unexpected error occurred while getting products",
        )

@app.get("/{product_id}", response_model=Product)
def get_product(product_id: int):
    """Return a single product by its id."""
    try:
        product = fetch_product(product_id)
        if not product:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, detail="Product not found"
            )
        return product
    except Exception as e:
        logger.error(f"Unexpected error while getting product {product_id}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="An unexpected error occurred while getting the product",
        )

Notice the try/except blocks:

  • If something goes wrong (e.g., products is undefined), the exception is logged and the client receives a generic 500 response instead of a raw traceback.

Example: Creating a Product (with intentional error for demo)

@app.post("/", status_code=status.HTTP_201_CREATED, response_model=Product)
def create_product(product: ProductCreate):
    """Create a new product and add it to the in‑memory list."""
    try:
        # Uncomment the line below to simulate a coding error and see logging in action
        # kkk  # <-- intentional NameError for demonstration

        product_data = product.model_dump()
        product_data["id"] = len(products) + 1
        products.append(product_data)
        return product_data
    except Exception as e:
        logger.error(f"Unexpected error while creating product: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="An unexpected error occurred while creating the product",
        )

If you insert a syntax or runtime error (e.g., the kkk line), the exception will be caught, logged to app.log, and the client will receive a clean 500 response.

Running the Application

  1. Create a virtual environment (optional but recommended).

  2. Install dependencies:

    pip install fastapi uvicorn
  3. Start the server:

    uvicorn main:app --reload

    The --reload flag enables auto‑reloading during development.

  4. Test the endpoints (e.g., with curl, HTTPie, Postman, or a browser).

  5. Check the logs – Open app.log to see the recorded messages whenever an exception occurs.

TL;DR

  • Log everything you need to know about errors.
  • Catch exceptions at the API‑boundary level to return user‑friendly responses.
  • Never expose raw tracebacks to end users; keep them in logs for developers.

Implementing these practices makes your production services more reliable, debuggable, and secure. Happy coding!

Basic Logging in FastAPI

When an error occurs while creating a product, you might see a message like:

error occurred while creating the product')

How to View the Logs

  1. Run the create_product endpoint.
  2. Open the app.log file that is generated.
    The file will automatically update with any new errors that occur.

Logs File

This is basic error logging in FastAPI.

Project Repository

Basic Logging FastAPI Github

Back to Blog

Related posts

Read more »