DEV Community

Cover image for Blocking FastAPI Access Logs
Mukul Sharma
Mukul Sharma

Posted on • Updated on

Blocking FastAPI Access Logs

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

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


No B.S. Solution

No Drama, No BS

# 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())
Enter fullscreen mode Exit fullscreen mode

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

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:

# 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
Enter fullscreen mode Exit fullscreen mode

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.

# 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())
Enter fullscreen mode Exit fullscreen mode

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 GitHub discussion.
  • Check out my LinkedIn here.

Top comments (0)