Skip to content

Logging in FastAPI Apps / Writing a FastAPI Middleware

Learn how to set up logging and middleware in FastAPI apps and ship logs to Better Stack for analysis.

Ask about this video. Answers come from its transcript only — with the timestamp, so you can check them.

Generated from the transcript and can be wrong — check the timestamp.

Key Takeaways

  • Middleware can be used in FastAPI to log all incoming requests and outgoing responses.
  • Better Stack platform enables centralized log analysis and event detection.
  • Uvicorn is the recommended async web server to run FastAPI applications.
  • Python’s logging module allows detailed customization of log output format and handlers.
  • Organizing logging code in separate modules improves maintainability.

What the video covers

  • Introduction to setting up logging in FastAPI applications using Python.
  • Creating middleware to log details of every request and response.
  • Shipping logs to Better Stack platform for analysis and searching important events.
  • Setting up a Python virtual environment and installing FastAPI and Uvicorn.
  • Building basic FastAPI endpoints with async handlers.
  • Running the FastAPI app with Uvicorn and enabling auto-reload.
  • Configuring Python logging with formatters and handlers.
  • Creating a dedicated logger.py file for logging utilities.
  • Implementing middleware to capture and log request/response data.
  • Using Better Stack’s logging tools and documentation for enhanced log management.

Answers

Questions about this video

How do you set up logging in a FastAPI application?

You set up logging by importing Python's logging module, configuring formatters and handlers, and optionally creating middleware to log each request and response.

What is the role of middleware in FastAPI logging?

Middleware intercepts every request and response, allowing you to log detailed information about them before passing control to the application handlers.

How can logs be shipped to Better Stack from a FastAPI app?

Logs can be sent to Better Stack by configuring your logging handlers to forward log messages to Better Stack's platform for centralized analysis and searching.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
In this video, we're going to learn how to set up logging with the FastAPI framework in Python. We're going to see how to set up middleware in order to log out details of every single request and response that comes into your application. We'll also see how to ship those logs to Better Stacks platform in order to analyze and search the logs and find important events that are occurring in our application. Let's get started.
00:13
Speaker A
application and we'll also see how to ship those logs to better Stacks platform in order to analyze and search the logs and find important events that are occurring in our application let's get started now let's start by creating
00:26
Speaker A
Now, let's start by creating a Python virtual environment and installing FastAPI into that environment. I have the documentation open at the moment, and we'll leave a link to this below the video. What we're going to do is go to the install FastAPI section, and we're going to run this command here: pip install fastapi all.
00:37
Speaker A
API section and we're going to run this command here pip install fast API all now I'm going to cross over to VSS code where I have a directory with a main.py file that's all that's in that folder and what we're going to do to start with
00:50
Speaker A
Now, I'm going to cross over to VS Code where I have a directory with a main.py file. That's all that's in that folder. What we're going to do to start with on the terminal is create a Python virtual environment using the venv module. So python -m venv, and let's give this environment a name of venv_fastapi. Once we've run that command, you need to activate the virtual environment. I'm on Windows at the moment, so what I'm going to do is activate it with this command, and you can see that that is activated. Now, if you're on a Unix system, you can use the source command in order to do that.
01:04
Speaker A
on windows at the moment so what I'm going to do is activate it with this command and you can see that that is activated now if you're on a Unix system you can use the source command in order
01:12
Speaker A
What we can then do is install FastAPI, and actually, I'm going to just paste that command that I copied from the documentation. That's going to install FastAPI as well as other dependencies such as Uvicorn. Uvicorn is the async-ready web server that we're going to use to serve the FastAPI application.
01:25
Speaker A
is the async ready web server that we're going to use to serve the fast API application once that's done what we can do is we can actually create a small fast API application and we'll build some logging into that application
01:37
Speaker A
Once that's done, what we can do is we can actually create a small FastAPI application, and we'll build some logging into that application, including building a middleware slightly later in the video. So to start with, let's import from FastAPI the FastAPI object. In order to create a FastAPI application, the most simple thing you can do is instantiate that and store it in a variable, which we will call app.
01:49
Speaker A
in a variable which we will call app and then using this app object we can Define handlers and endpoints in the fast API application so I'm going to Define an endpoint that takes a get request and the path for that is just going to be a
02:02
Speaker A
Then, using this app object, we can define handlers and endpoints in the FastAPI application. So I'm going to define an endpoint that takes a GET request, and the path for that is just going to be a slash. So it's the base path in the application. Then, what we can do is define an async Python function, and this is the handler for the root. So let's call this function index. Then, we can return a bit of content, and in my case, I'm going to return a dictionary here, and we'll give it a message of hello.
02:16
Speaker A
case I'm going to return a dictionary here and we'll give it a message of hello so a very simple endpoint here it returns a python dictionary containing a key message and we can type in that return type if we want using this syntax
02:29
Speaker A
So a very simple endpoint here. It returns a Python dictionary containing a key message, and we can type in that return type if we want using this syntax here, until the FastAPI function that this is going to return a dictionary. FastAPI will then convert that to JSON.
02:41
Speaker A
be to a URL that we're going to give a path of upload videos and I'm also going to name the function upload videos and we can change the message here to video uploading and later on in the video
02:52
Speaker A
Now, what I'm going to do is replicate this endpoint. We're going to create one more endpoint, and this one is going to be to a URL that we're going to give a path of uploadvideos. I'm also going to name the function uploadvideos, and we can change the message here to video uploading.
03:05
Speaker A
that was the web server that we're going to use and at the bottom we're going to run the web server here we're going to check if we're running this file as a python command and then we're going to
03:14
Speaker A
Later on in the video, we're going to introduce a bit of latency for this function to simulate a long-running request that you might get, for example, when you upload a video.
03:26
Speaker A
order to run this is make the terminal a little bit bigger here and we're going to run the uicorn main app command and I'm going to pass the D- reload flag to this so that the server will reload when
03:37
Speaker A
So now we have two handlers. Let's import Uvicorn at the top, and remember I said that was the web server that we're going to use. At the bottom, we're going to run the web server here. We're going to check if we're running this file as a Python command, and then we're going to call the Uvicorn.run function if that's the case. We pass our app object into that function, as well as some details here for the host and the port, and you can change those if you need to.
03:48
Speaker A
can add the other endpoint here of upload D videos and we're going to get back that different message for the second Endo so we have a fast API application albeit very basic but how do we add logging to this application let's
04:02
Speaker A
Now, what I'm going to do in order to run this is make the terminal a little bit bigger here, and we're going to run the Uvicorn main:app command. I'm going to pass the --reload flag to this so that the server will reload when any changes are made to the code.
04:14
Speaker A
to bring a couple of imports in we're going to import the logging module and also the CIS module from Python and then what we're going to do below that is get the root logger so I'm going to get that
04:23
Speaker A
So we now have a server running on localhost:8000. If you go to the browser, you can see that at the main endpoint here, we get the response of message hello. We can add the other endpoint here of uploadvideos, and we're going to get back that different message for the second endpoint.
04:36
Speaker A
string or none and that's going to return a logger with the specified name and create it if necessary and if you don't specify a name as it says here it's going to return the root logger so this line of code is going to give us
04:48
Speaker A
So we have a FastAPI application, albeit very basic. But how do we add logging to this application? Let's go back to VS Code, and we're going to create a new file in the project that's going to be called logger.py. We're going to define some utilities from Python's logging module in this particular file.
05:01
Speaker A
create a variable here called formatter and that's going to be equal to an instance of a logging do formatter object now this takes some arguments the most important one is the format so let's pass in a format string here and
05:13
Speaker A
So at the top, I'm going to bring a couple of imports in. We're going to import the logging module and also the sys module from Python. Then, what we're going to do below that is get the root logger. So I'm going to get that logger by calling a function in the logging module, and that's going to give us back an instance of a logger in Python.
05:25
Speaker A
hand side here it's the log record attributes so a log record basically repres presents a piece of log output and this log output can have some attributes that are predefined in the logging module so if we scroll down here
05:37
Speaker A
So what we're going to call is logging.getLogger. This function can optionally take a name; it can be a string or None. That's going to return a logger with the specified name and create it if necessary. If you don't specify a name, as it says here, it's going to return the root logger. So this line of code is going to give us back a logger instance in Python.
05:51
Speaker A
the level name in the logging package refers to the debug info warning error or critical log level and each of these have a corresponding number that determines the severity and the higher the number the more severe the log event
06:04
Speaker A
What we're going to do after that is create what's called a format. A formatter in the Python logging package is going to determine the output format of your log records. So let's create a variable here called formatter, and that's going to be equal to an instance of a logging.Formatter object.
06:16
Speaker A
code and we're going to create a log format here so the first thing we're going to Output is the time at which the log record was created and then we're going to put a space and a Dash and
06:25
Speaker A
Now, this takes some arguments. The most important one is the format, so let's pass in a format string here. We're going to set that equal to a string that will determine the output format of our logs.
06:34
Speaker A
defined in your application and then I'm just going to put another Dash here and we're going to Output the message that's the actual message passed into the log method as we're going to see very soon so this is a very simple format for our
06:46
Speaker A
Now, what I'm going to do is go back to the documentation for the logging package in Python. What we're going to look at is on the left-hand side here, it's the log record attributes. A log record basically represents a piece of log output, and this log output can have some attributes that are predefined in the logging module.
06:57
Speaker A
going to be a loging do stream Handler and and this can take any stream as a parameter but if you don't specify one it's going to send the output to standard error so just to demonstrate this I'm going to pass in standard out
07:09
Speaker A
If we scroll down here, you can see some of these attributes that we can reference in our log format. For example, this one here is for a human-readable time when the log record was created. We also have other ones such as the level name and level number.
07:21
Speaker A
Handler instance and the main argument we need to provide here is a file name so let's provide a file name of app. log once we've done that we can set the formatter so basically we're going to take each of the handlers like the
07:32
Speaker A
The level name in the logging package refers to the debug, info, warning, error, or critical log level. Each of these has a corresponding number that determines the severity, and the higher the number, the more severe the log event is. We'll leave a link to this below the video.
07:43
Speaker A
also going to do it for the file Handler and we're nearly done what we need to do now is we need to add the handlers to the logger instance so we have the logger that we created at the top here
07:53
Speaker A
There are many of these log attributes, but what we're going to also reference is the message, and that's the output message that's passed into the log level method.
08:03
Speaker A
this application so I'm going to use the stream Handler and also the file Handler and the Handler's property is telling the logger where to send the output records so it's going to send them to standard output and also to the file
08:14
Speaker A
So let's go back to VS Code, and we're going to create a log format here. The first thing we're going to output is the time at which the log record was created. Then, we're going to put a space and a dash.
08:24
Speaker A
logging doino so we now have the configuration for this logger and we've set some format Ms and handlers on the logger what we can do now is go back to main.py and at the top here what I'm going to do is import from logger the
08:37
Speaker A
Actually, I'm going to move this to a new line so we can see the entire line better. After the dash, we're going to put the level name, which could be info or error or any other log level that's defined in your application.
08:50
Speaker A
we can do is make the terminal a bit bigger at the bottom and if I save this file it's going to reload the application and it says starting API that was the message we passed in and it's got the format that we specified
09:01
Speaker A
Then, I'm just going to put another dash here, and we're going to output the message. That's the actual message passed into the log method, as we're going to see very soon.
09:11
Speaker A
log statements to our Handler functions in fast API so let's go to the index function and I'm going to put a very simple log message in here and again we're going to call the logger doino function and the message I'm going to
09:23
Speaker A
So this is a very simple format for our log records. What we're now going to do is create some handlers that are going to determine where the log records are going to be shipped to. Let's create a couple of these.
09:36
Speaker A
if we go back to the browser here and go to our upload videos endpoint if I refresh this page and go back to the terminal on vs code you can see we get this output log here containing the time
09:47
Speaker A
The first one's going to be called streamHandler, and that's going to be a logging.StreamHandler. This can take any stream as a parameter, but if you don't specify one, it's going to send the output to standard error. Just to demonstrate this, I'm going to pass in sta...
09:59
Speaker A
have in the main.py the ability to import that logger and use that logger so we use it here and we also use it in our Handler functions as well now soon we're going to add a middleware to log
10:09
Speaker A
output for every request but what we're going to do before that is we're going to add a Handler that allows us to ship our logs to better stack and this is vital for centralizing your logs across different services in a single place
10:21
Speaker A
where you can then search through them and build some analytics around those logs and also helps with identifying events or anomaly that are occurring in your application so what we're going to do now is go to the better stack log
10:34
Speaker A
page and we're going to create a source that allows us to take the logs from a particular service so let's connect our source now and we're going to give it a name here and let's give it a name of
10:43
Speaker A
fast API demo and we're going to select a platform and we can search through the list available here and we're going to select python so let's create that source and then we're going to get back a token as you can see here let's copy
10:55
Speaker A
that token and what I'm going to do is go to logger dopy and right at the top of the this module I'm going to add the token here so let's create a variable called token and we're going to set that
11:04
Speaker A
equal to the string that we get back now in a real application you should extract that token to the environment and then read that in securely and of course that should not be put on GitHub or any other
11:15
Speaker A
source control system but we're just going to leave this here for demonstration purposes in this video but make sure you don't hardcode these types of tokens in your applications so what we have now is a source and we can now
11:25
Speaker A
ship our logs to this source using the token that we've been given and in order to to do that we need to bring a new package from better stack into our application so I'm going to go to the
11:34
Speaker A
better stack documentation for logging in a python application there'll be a link to this just below the video what we're going to do to start with is copy the PIP install command and we're going to install the log toil python package
11:46
Speaker A
and this is basically a package that allows you to ship your logs to better stack so let's copy that command and go back to VSS code I'm going to stop the fast API server and we're going to paste
11:56
Speaker A
that command in and install the log tail python package once once we've got that installed we can then use that package in our application I'm going to go back to the documentation and you can find the instructions on how to use this with
12:07
Speaker A
a python app in this documentation so what we're going to do is import the log tail Handler so this package gives us the log tail Handler that we can use to ship logs to better stack so let's import that at the top and we're then
12:20
Speaker A
going to take the log tail Handler and we're going to go to the section that we have here where we created two handlers and we're going to create another one just below this and this is going to be
12:29
Speaker A
called the better stack Handler now we're going to set that equal to an instance of the log tail Handler and what we need to pass in here is a source token and we need to set that equal to the Token that we got from
12:42
Speaker A
the better stack user interface when we created that source and of course we saved that token at the top of this file on line five so we're going to reference that token here in the argument and once we've created this better stack Handler
12:54
Speaker A
what we can then do is go down to the logger do handlers line and we're going to add our new better stack Handler to that list so now we have three handlers in the application and of course you can
13:04
Speaker A
add and remove these as you wish you don't need to use all of them if you don't need to log to a file you can just remove that Handler but I'm just going to keep logging to all three of these
13:14
Speaker A
and what I didn't show earlier on was actually the app. log file you can see the logs that are being collected in this app. log file and this corresponds to the file Handler that we defined here where we told the file Handler we're
13:26
Speaker A
going to send those logs to the app. log file so we have that on the left hand side our logs are going to standard output they're going to the file and now hopefully they're going to go to our
13:36
Speaker A
better stack Source via this log tail Handler so let's run the application again on the terminal and once that's running what we're going to do is go back to this page here for upload videos and we're going to refresh the page and
13:48
Speaker A
we can do the same at the other end point where we just get back the message of hello if we go back to the better stack platform here and we go to the live tail for the logs we should now see
13:58
Speaker A
that we are actually getting getting these logs coming back to the better stack platform and we can click these logs to get more information about them so for example we get the fil name that emitted that log we get the message and
14:10
Speaker A
these contain very basic messages at the moment and we also get some information about the level and severity as well now you can add your own key value pairs to the python log output and we're going to see an example of that very soon what
14:23
Speaker A
we're going to do now is we're going to create a middleware in our fast API application that's going to log details of every request that's coming into the application now let's start by going to the fast API middleware page so a
14:35
Speaker A
middleware is a function that works with every request before it's processed by a specific path operation which is basically a Handler function and this function also can process every response before it returns it to the client and the benefit of that if we go back to vs
14:51
Speaker A
code and look at the code that we have in main.py if we look at the two Handler functions we have two outputs here to logger doino now imagine that contained the same data and we had it in 50
15:03
Speaker A
different endpoints we might want to consolidate that and instead of adding log calls in every single Handler if we have a common functionality there we can extract that to a middleware that's going to run before every request so how
15:15
Speaker A
do you define a middleware in a fast API application let's go back to the middleware page and as we've seen we have an app object when we instantiate fast API we can also use another decorator here the app. middle we
15:29
Speaker A
decorator so I'm going to copy that decorator and we're going to go back to main. Pi and I'm going to Define this middleware just above the handlers and later on we're going to extract that middleware to its own file so we use The
15:41
Speaker A
app. middleware Decorator and then I'm going to Define another async function and let's call this one log middleware now a middleware in fast API it can take two arguments first of all the request object that is passed in as the first
15:54
Speaker A
argument and then we have a function passed in as the second argument called call next so let me just copy these and we're going to bring them into the code here and we need to import the request object from Fast API so let's do that at
16:07
Speaker A
the top now what I'm going to do within the middle wear function is I'm going to create a python dictionary that we're going to call log dictionary and that's going to be equal to a dictionary with two keys and the first key that we want
16:17
Speaker A
to add is for the URL we can get the URL for this request by using the request.
16:23
Speaker A
URL property that gives us back a URL object that contains another property called path and that will give us the full path for that request and we can also add a second property to the dictionary and that's going to be the
16:35
Speaker A
request. method and that's going to tell us what kind of method that was sent to the back end was it a get request a post request or so on so our middleware now has a dictionary containing a URL and a
16:47
Speaker A
method what we can do is we can call logger doino here and I'm going to pass the log dictionary through to that and what that's going to do is it's going to Output that log dictionary as the message for this logger info call and
17:00
Speaker A
because we're using this as a middleware this is going to be run on every single request that comes into the fast API application now we need to then progress the middleware onto the next middleware in the chain or to the actual Handler
17:13
Speaker A
function if it's the last middleware so what we're going to do in order to do that is we're going to create a variable called response and we're going to call this function here that was passed in as a second argument it was called call
17:23
Speaker A
next we can call that and pass the request into that now because we're in an async function here we can await that function returning and what this is going to do is it's going to return the actual response that's to be sent to the
17:36
Speaker A
client and at this stage we can modify that response for example we could add an HTTP header that we want to send back but all we want to do is just log out this data so what I'm going to do for
17:46
Speaker A
now is just return the response to the client so this is a middleware that does some operations on the request coming into the client and it logs out some data and then it simply Returns the response we're going to see later later
17:59
Speaker A
on that we're going to add another property to this log dictionary that can only be calculated when we've generated the response for the client so we are going to modify the code in between generating that response and returning
18:10
Speaker A
it a bit later in the video so let's now test this out I'm going to remove these log calls that we have in the function we don't need those anymore and we're just going to see the log output for
18:20
Speaker A
this middleware here so let's save the file and go back to our page here I'm going to refresh this page and we get back the same response but what we need to know is has the middle wear run in
18:30
Speaker A
the application so let's go back to better stack and you can see this log record at the bottom here if I expand that you can see we get back the message containing those two properties that we added to the dictionary so the URL which
18:41
Speaker A
is just slash and the method which in this case is get and we can test that for the other endpoint so slash upload videos if we do that and go back to the live tail this time at the bottom you
18:53
Speaker A
can see we get back the message here containing a different URL it's still a get request but the UR URL has changed to/ upload videos so the log output generated by the middleware is now being sent to better stack what we're going to
19:06
Speaker A
do now is show how to consolidate the middleware in its own module so what I'm going to do is cut this out of main.py and we're going to create a new file here called middleware dop and I'm going
19:17
Speaker A
to paste the function in here and then we're going to remove The Decorator because we haven't imported the app and we can't do that which we'll show in a second because it will result in a circular depend y now I need a couple of
19:30
Speaker A
imports at the top here we need the request object from Fast API which we're using as a type hint and we also need the logger object from the logging module which we're also using in order to call methods like logger doino so we
19:43
Speaker A
now have an async function called log middleware and it lives in its own module the middleware dop module so now that we've defined this module let's go back to main. Pi and we don't need to import the request object and we need to
19:55
Speaker A
now add this middleware to our app that we have here on line five and we're not using that decorator anymore how do we register the middleware well it turns out the app object has a function called add middleware so we can use that
20:07
Speaker A
function but the problem that we have here is that that expects a middleware class and what we have in middleware DOP is a function called log middleware so let's go back to main.py and to start with let's import from middleware that
20:21
Speaker A
function that we defined called log middleware and now we need to add it to the app object but as I said it needs a class so what I'm going to do is go to this documentation or rather this issue
20:31
Speaker A
that was raised on the fast API GitHub page and the issue question here is how can you get access to the app object in a different file from main.py now if we scroll down we can get the answer to
20:42
Speaker A
this and this answer is very relevant to us it's about adding a middleware that's defined in another module of the application what we can do is we can use the base HTTP middleware class from starlet. middleware so let's bring that
20:55
Speaker A
Import in at the top here we're going to go back to main. p and just underneath our middleware import let's import the base HTTP middleware now fast API basically runs on top of a framework called Starlet and this is an async
21:09
Speaker A
framework for developing web applications and this base HTTP middleware we can go to the documentation for that so let's cross over to the Starlet documentation and what you need to do in order to implement a middle wear class that uses
21:22
Speaker A
this as its Base Class is you must override the function called dispatch and you can see that in the signal below we have a class that inherits from the base HTTP middleware and it defines a function called dispatch and then within
21:36
Speaker A
the dispatch function it defines the code for the actual middleware now what we're going to do is we're going to follow the guide on this GitHub issue we're going to pass the base HTTP middleware into the app. adds middleware
21:47
Speaker A
function and then we can pass a dispatch method and what we're going to do is we're going to set it equal to that method that we defined in the middleware dop file and that's the log middleware method so let's go back to main.py and
22:00
Speaker A
to the add middleware call on the app we're going to pass the base HTTP middleware from Starlet and then we're going to pass a dispatch function that's equal to log middleware and at the bottom we're getting this error that we
22:12
Speaker A
cannot import base HTTP middleware now we can go back to Starlet here and see what's wrong I've copied that import from this issue on GitHub that was raised in 2019 I believe the module has changed that is now starlet. middleware
22:27
Speaker A
dobas so we're going to copy base and we're going to add that into the path at the top here and if we save that and reload the server you can see it's now starting up with no issues so this is
22:38
Speaker A
just showing a way in which you can extract your middleware into its own module and then register or add that middleware in the main.py file to the app object by referencing That Base HTTP middleware now let's check that this is
22:51
Speaker A
still working if we go back to the browser and on the video upload page I'm going to refresh this and we see we get the same output if we go back to to vs code you can see that we're getting that
23:00
Speaker A
same message output as a log and that message is coming from the middleware so everything is still working but we've now managed to extract the middleware to its own file and this file can then be used basically for the roots in the
23:13
Speaker A
application now let's go back to the better stack live tail for these logs and I'm going to open this out here so we can see it better this is one of the logs that we had and it contains that
23:23
Speaker A
message where we have as the message basically some Json data all right I think this is the string version of that dictionary that we had we have a URL pointing to whatever URL generated the output and also a method but these are
23:37
Speaker A
embedded within the dictionary we might want to get these as top level Keys such as the file name or the level so that we can then search for them as in this example at the top here where we search
23:48
Speaker A
for all the logs that have a level equal to info so how do we extract this key value structure here from the message and embed those keys at the top level so they become searchable it turns out it's
24:00
Speaker A
very easy to do this let's go back to middleware dop and when we output that log dictionary what we can do is we can actually pass the dictionary in as a keyword argument called extra so I'm going to do that just now and save this
24:13
Speaker A
file and go back to one of the pages and generate these log outputs using the middleware if we then go back to better stack let's go back to the live tail that we have on the left hand side and
24:23
Speaker A
we're going to scroll right to the bottom here and when we expand that log record we see that we get the same message but the keys and values within that log output have been extracted into top level keys and values such as URL
24:35
Speaker A
here and we also have method of get here so we can then search for that for example at the top method and if we want to get only requests where the method is equal to get we can search for that and
24:47
Speaker A
it's going to return that single record because now method is a top level key it's been index by better stack and we can now search over that content and we can see the output here now you can custom imiz these records as you'd like
24:59
Speaker A
you could use Json data and Implement your own custom format or class but if you have simple keys and values that you want to appear in the top level and be searchable you can simply pass a dictionary as the extra key to the
25:11
Speaker A
logger doino warn error and so on these methods all accept this extra parameter and it allows you to pass in the custom data that you need so let's finish this video by calculating the time it takes to generate a response for each of the
25:25
Speaker A
end points in the application and we're going to do this in the middleware So within the middleware dopy file I'm going to go to the top and I'm going to import the time module that's built into Python's standard library and then right
25:37
Speaker A
at the top of the middleware function I'm going to create a variable called start and I'm going to call the time.time method that's going to give us back a time stamp at which this middleware is first invoked and remember
25:47
Speaker A
this will happen for every request that comes into the application so we have a start time and then what we do is we call this next function and await the response and that is going to give us back the response but we want to
25:59
Speaker A
calculate the time it takes in order to generate that response so we can create another variable here just below the response and that's going to be called process time and again we're going to call the time. time function here and
26:10
Speaker A
we're going to subtract the start time that we calculated at the start of this middleware function and that's going to give us back a Delta and that Delta represents the time it takes for this request to be processed and generate a
26:22
Speaker A
response now the last thing I want to do is move these calls to logger doino down below the response here so after we generate the process time let's paste that code back in here we create the log dictionary and this time I'm going to
26:35
Speaker A
add another key to that and it's going to be called process time and we're going to set that equal to the process time that we've calculated just above so that gives us our log dictionary we can then call logger doino and again we're
26:47
Speaker A
outputting that dictionary as the message but we're also passing it to the extra key in order to make those keys in the dictionary top level keys on better stack let's now save this and go back to the page for the video upload we're
27:01
Speaker A
going to refresh this and you can see we get back the response and if we do that on the main URL in the application we also get back the response we can go to the terminal and we can look at the
27:11
Speaker A
process time for these and you can see it's a very small number for that main URL and also for the video upload URL also a very small number now what we're going to do is we're going to generate
27:22
Speaker A
some artificial latency in one of these functions now when you upload a video that typically takes quite a long time so what I'm going to do at the top is I'm going to import the python async iio module this is built into Python's
27:34
Speaker A
standard library and that contains a function that you can use in an asynchronous endpoint So within the upload videos endpoint let's await asyn do sleep and we're going to sleep for 1.5 seconds we can then go back to our
27:48
Speaker A
endpoint here and I'm going to refresh this page and also go to upload videos here and you can see that that takes a little bit more time to process that request and generate the response and again if we go back to the terminal here
28:01
Speaker A
and look at the process time that's been calculated by our middleware you can see that that is basically 1.5 seconds now what I'm going to do now just to end the video is go to better stack so let's go
28:12
Speaker A
over to better Stack's UI here and go to the live tail now you might want to find the long running requests the slow requests in your application so let's now see how we can maybe do that now that we're logging out the process time
28:25
Speaker A
on every single request if we look at the record at the very bottom here you can see the process time is now a top level key here and the value is the actual time taken to process that request so we can then search the logs
28:38
Speaker A
for a process time and you can see the suggestions here better stack knows that that is a floating Point number we can then look for a processing time that's greater than 1 second and that would help us maybe diagnose very slow running
28:50
Speaker A
requests in our application so let's search for those and we get back to results and these are results for the upload videos in end point after we introduced that ASN k. sleep call and you can see the process time is now 1.49
29:04
Speaker A
seconds so we can use these search values and it doesn't need to be an equality that we use we can search for values that are greater than a number or less than a number or if it's a string
29:14
Speaker A
values that contain a substring so there are lots of options here on better stack and this is one example that you can use if you want to find slow running requests in a fast API application and similarly because we added the U to the
29:28
Speaker A
top level Keys what we can also do at the top is we can look at the URL and that's a string as it says here but we can look for URLs that contain a particular string or are equal to a
29:39
Speaker A
string so let's look for all logs at the URL upload videos and that's going to give us back all of those log outputs for that URL and again these have been generated by the middleware so that's all for this video in this video we've
29:53
Speaker A
shown how to generate a fast API application that contains a logger into instance that sends your logs to different Handler locations with a particular format and we've seen how to add a Handler for better stack and send our logs to the better stack platform
30:08
Speaker A
where you can effectively analyze them and find interesting incidents and outputs that are occurring in your application and in this video we also saw how to create a fast API middleware function that performs some kind of logic on every request response cycle in
30:24
Speaker A
your application and then in this case it's generating some log output and sending that log output to better stack where we have analyzed it and found an endpoint in our application that's running slower than we would expect we
30:37
Speaker A
can find that information and then respond to it accordingly and that's vital when you're building applications you need to know if something is performing slowly and then address that issue so thank you for watching this video if you've enjoyed the video please
30:48
Speaker A
subscribe to the better stack Channel and please give the video a thumbs up if you've enjoyed this content if you have any suggestions for similar content please let us know in the comments and we'll see you in a future video
Topics:FastAPIPython loggingmiddlewareUvicornBetter Stacklog managementasync web serverlogging formatterrequest loggingresponse logging

Get More with the SozAI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →