FastAPI Logs in Azure App Service Log stream

If you have deployed a FastAPI based App Service on Azure, chances are that you may have followed this tutorial. One thing that this tutorial doesn’t cover is how to display the logs in the Logstream of Azure App Service. Any logging.info() statement that you might add to your APIs has no effect on the logstream.

After searching Google extensively for a way around, here’s a hack that I found

Step 1: Add the following include statements in your FastAPI code

import logging
from fastapi.logger import logger

Step 2: Link your FastAPI logger to gunicorn’s error log

gunicorn_logger = logging.getLogger('gunicorn.error')
logger.handlers = gunicorn_logger.handlers
logger.setLevel(gunicorn_logger.level)

Step 3: Replace logging with logger in the functions

Thus,

logging.info('Python HTTP trigger function processed a request.')

becomes

logger.info('Python HTTP trigger function processed a request.')

That’s it. Now, any logging statements in your code will get printed in the Log stream on the function invocation.

Testing it out

We’ll test this out with a very short code, given below:

from fastapi import FastAPI, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.logger import logger
import urllib
import logging

gunicorn_logger = logging.getLogger('gunicorn.error')
logger.handlers = gunicorn_logger.handlers
logger.setLevel(gunicorn_logger.level)

app = FastAPI(title="FastAPI Logs Demo",debug=True)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"]
)

@app.post("/fast_api_test/", status_code = status.HTTP_200_OK)
def fast_api_test(req_body: dict):
    logger.info('Python HTTP trigger function processed a request.')
    name = req_body.get('name')

    if name:
        return {"Hello, " + str(name)+". This HTTP triggered function executed successfully."}
    else:
        return {"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."}

As you can see, every time the fast_api_test function is invoked, the statement ‘Python HTTP trigger function processed a request.’ should get printed in the logs.

Now, for some reason, after pushing a commit, the gunicorn logs are visible in Azure App Service Log Stream approx. 12-24 hours later. I still haven’t figured out the reason for this; if you can figure this out, please let me know in the comments.

But once the gunicorn logs start getting printed in the Log stream, you can use them for live debugging and monitoring. See the image below.

As you can see, the log statements begin with [ERROR] because they are being written to the gunicorn error log. Next, after the time stamp, you see the PID of the worker which processed the request [42], and then you see [INFO], because this statement was added in the logging.info() function. Finally, you see the log statement that you wanted printed.

Closing Thoughts

I hope this tutorial helped you. Click here for more tutorials on FastAPI. Also, note that in general, if you are searching Google for FastAPI and don’t find an answer, run a similar query for Flask. You are much more likely to get an answer and there is a high probability that it will apply to FastAPI as well.


If you are planning to appear for the Azure Administrator Exam Certification, check out this course on Udemy.

Leave a comment

Your email address will not be published. Required fields are marked *