Blocking FastAPI Access Logs
Tags: fastapi, python, filter, logs
Published: 2024-07-14 03:55:08

Have you ever found your FastAPI deployment cluttered with unnecessary access logs? These logs can create more noise than value, obscuring important information. Let's explore a neat trick to selectively block these access logs in FastAPI.

![The Problem](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsa7soxyvzg4k84pdzek.png)

Access logs can quickly overwhelm your console, making it difficult to spot critical information.

---

## No B.S. Solution


![No Drama, No BS](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExamN3YnNpb3NqNzA0czJ0NjVkMWFqODVjZG95enY0Y253aXBxeGNobiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Dd7eqfJIDTnEmSVRGn/giphy.gif)

```py
# main.py
import logging

block_endpoints = ["/endpoint1", "/endpoint2"]

class LogFilter(logging.Filter):
    def filter(self, record):
        if record.args and len(record.args) >= 3:
            if record.args[2] in block_endpoints:
                return False
        return True

uvicorn_logger = logging.getLogger("uvicorn.access")
uvicorn_logger.addFilter(LogFilter())
```

### How It Works

We create a `LogFilter` class that inherits from `logging.Filter`.
The filter method checks if the log record corresponds to one of our blocked endpoints.

- If the endpoint is in our `block_endpoints` list, we return 
**False**, preventing the log from being processed.
- By default we return **True** to log as usual.

We apply this filter to Uvicorn's access logger, which FastAPI uses under the hood.

---

### Going Deep


![The Deep from The Boys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ee7r7tpa4whjjbwmhpig.jpg)

When working with Python's logging module, each log entry is represented by a `LogRecord` object. In our `LogFilter` class, the `record` parameter is an instance of this `LogRecord` class.

The `args` attribute of a `LogRecord` contains a tuple of arguments which are merged into the log message. In the context of Uvicorn's access logs, these arguments hold valuable information about each request. Here's a breakdown of what each argument typically represents:

```py
# Typical structure of record.args for Uvicorn access logs
remote_address = record.args[0]  # IP address of the client
request_method = record.args[1]  # HTTP method (GET, POST, etc.)
query_string = record.args[2]    # Full path including query parameters
html_version = record.args[3]    # HTTP version used
status_code = record.args[4]     # HTTP status code of the response
```

Understanding this structure allows us to create more sophisticated filters. For example, we could filter logs based on status codes, specific IP addresses, or HTTP methods, not just endpoint paths.

---

### Gotchas and Tips

- This method works with Uvicorn's default logging setup. If you've customized your logging configuration, you might need to adjust the logger name.
- At times you might have a separate file for logging config such as `logger.py`. You may define the class **LogFilter** there but make sure to apply `.addFilter` in `main.py`.

Remember that completely blocking logs for certain endpoints might make debugging more challenging. Use this technique judiciously.

As **thank you** for making it to the end of this post, here is a trick I use for maximum benefit.

```py
# main.py
import logging

block_endpoints = ["/endpoint1", "/endpoint2"]

class LogFilter(logging.Filter):
    def filter(self, record):
        if record.args and len(record.args) >= 4:
            if (record.args[2] in block_endpoints 
                and record.args[4] == "200"):
                return False
        return True

uvicorn_logger = logging.getLogger("uvicorn.access")
uvicorn_logger.addFilter(LogFilter())
```

This will only block the request if the status code is _200_. This is super helpful when blocking `INFO` endpoints where you only need to be informed if an unexpected status code was returned.

---

### Conclusion
By implementing this simple logging filter, you can significantly reduce noise in your FastAPI application logs. This allows you to focus on the information that truly matters, making your debugging and monitoring processes more efficient.


#### What to do next?

- Feel free to ask questions and share your experience in the comments below!
- For further reading, check [this](https://github.com/encode/starlette/issues/864) GitHub discussion.
- Check out my LinkedIn [here](https://www.linkedin.com/in/mukuliskul).