Replies: 19 comments
-
|
Hi @ari-jain013, if your logs don't require the response object, you could create a dependency for logging (that depends on user dependency) and inject it on all routes. For logging, check: #778 (comment) For adding the dependency on all paths, check: https://fastapi.tiangolo.com/tutorial/bigger-applications/
EDIT: Just to add an example from fastapi import FastAPI, APIRouter, Depends
app = FastAPI()
def user_dep() -> int:
print("CALLED USER DEPENDENCY")
user = 0
return user
def logger_dep(user: int = Depends(user_dep)):
print('CALLED LOGGER', user)
logged_router = APIRouter(dependencies=[Depends(logger_dep)])
@app.get("/not-logged")
async def not_logged(user: int = Depends(user_dep)):
return user
@logged_router.get("/logged")
async def logged(user: int = Depends(user_dep)):
return user
app.include_router(logged_router)You can confirm, user dependency is only called once for each path (other calls use cached value): from fastapi.testclient import TestClient
client = TestClient(app)
client.get('/logged')Gives:
|
Beta Was this translation helpful? Give feedback.
-
|
Okay, I think I can start with this but again it would be great analytics if I could also track is the response was successful or not. Thank you for the quick reply |
Beta Was this translation helpful? Give feedback.
-
|
If you need to wait for the response, I would add a middleware for logging. For user info, starlette allows you attach states to the request object, which you can then access from the middleware. Not sure if there is a downside to using this with FastAPI, but the following example runs correctly. from fastapi import FastAPI, Depends, Request
async def user_dep() -> int:
user = 0
return user
async def add_request_state(request: Request, user: int = Depends(user_dep)):
request.state.user = user
app = FastAPI(dependencies=[Depends(add_request_state)])
@app.middleware("http")
async def add_logs(request: Request, call_next):
response = await call_next(request)
print ("some logging logic for user", request.state.user)
print ("response status code: ", response.status_code)
return response
@app.get("/test")
async def logged(user: int=Depends(user_dep)):
return user
# Test behavior
from fastapi.testclient import TestClient
client = TestClient(app)
client.get('/test')
|
Beta Was this translation helpful? Give feedback.
-
|
Hi Ahmed, I tried adding a middleware as you suggested And got the following error
|
Beta Was this translation helpful? Give feedback.
-
|
Hi Ahmed, I tried the first option as well And got the following error
|
Beta Was this translation helpful? Give feedback.
-
|
Hi @ari-jain013, I just realized shared parameters (e.g. |
Beta Was this translation helpful? Give feedback.
-
|
You can use a middleware like the one below which gives timing, generates a unique request id and prints status code as well. current_request_id is a context variable class RequestTimeMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
idem = "".join(random.choices(string.ascii_uppercase + string.digits, k=20))
current_request_id.set(idem)
logger.info(f"rid={idem} start request path={request.url.path}")
start_time = time.time()
response = await call_next(request)
response.headers["X-Request-Id"] = idem
process_time = (time.time() - start_time) * 1000
formatted_process_time = "{0:.2f}".format(process_time)
logger.info(
f"rid={idem} client-ip={request.client.host} completed_in={formatted_process_time}ms status_code={response.status_code}"
)
return response |
Beta Was this translation helpful? Give feedback.
-
Yes, I realized the same while looking at the second error. |
Beta Was this translation helpful? Give feedback.
-
Can you please provide an example on how to use the Middleware class? |
Beta Was this translation helpful? Give feedback.
-
|
Just add to the list of middlewares of the app as below: See documentation here: https://fastapi.tiangolo.com/advanced/middleware/ |
Beta Was this translation helpful? Give feedback.
-
Hey Ahmed, I upgraded my fastapi version and was able to make shared parameter work. Any suggestion on the other option where I can track response along with request? But either way, thanks a lot for your help with clean, simple and easy to implement examples. |
Beta Was this translation helpful? Give feedback.
-
Gonna try this now! Thanks @upeshphable |
Beta Was this translation helpful? Give feedback.
-
|
@ari-jain013 Please close the issue if it worked. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @upeshphable i tried the custom middleware and still got the same response
|
Beta Was this translation helpful? Give feedback.
-
|
This is not related to the middleware. You need to check what your dependency, fastapi_users.get_current_user yields and then that user needs to have the id field because you are printing it. How come you have dependency in dispatch arguments? I don't think you can do that. |
Beta Was this translation helpful? Give feedback.
-
The dependency yields user object which has id, email and other fields. but it only works on endpoints or other dependencies. I'm trying to find a way to get user info and response status for all endpoints so I can maintain records of the number of times an endpoint was accessed and the response status. |
Beta Was this translation helpful? Give feedback.
-
This method worked after updating fastapi version but as it is a dependency, I was unable to get the response status to log |
Beta Was this translation helpful? Give feedback.
-
I think you cannot do it in middleware since it's handled in starlette. You might want to set user as a context variable and then use it here in this method to print out. |
Beta Was this translation helpful? Give feedback.
-
|
A similar issue would be |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
Hi, I'm looking for a way to track api usage on user basis. We are using fastapi-users for user management. Can anyone please suggest a way to do this. I tried using a custom API Router but was unable to fetch user details as it done through dependency injection and I kept getting errors like Depends object has no attribute ID/ Depends object is not subscriptable.
Any help would be greatly appreciated.
Thank you!!
Operating System
Linux
Operating System Details
No response
FastAPI Version
fastapi==0.61.1
Python Version
3.8
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions