1- # coding=utf-8
2- import logging
3-
4- from starlette .middleware .base import BaseHTTPMiddleware , RequestResponseEndpoint
5- from starlette .requests import Request
6- from starlette .responses import Response
7- from starlette .types import ASGIApp
8-
9- import json_logging
10- import json_logging .framework
11- from json_logging .framework_base import AppRequestInstrumentationConfigurator , RequestAdapter , ResponseAdapter
12-
13- from json_logging .util import is_not_match_any_pattern
14-
151
162def is_fastapi_present ():
173 # noinspection PyPep8,PyBroadException
@@ -24,114 +10,4 @@ def is_fastapi_present():
2410
2511
2612if is_fastapi_present ():
27- import fastapi
28- import starlette .requests
29- import starlette .responses
30-
31-
32- class JSONLoggingASGIMiddleware (BaseHTTPMiddleware ):
33- def __init__ (self , app : ASGIApp , exclude_url_patterns = tuple ()) -> None :
34- super ().__init__ (app )
35- self .request_logger = logging .getLogger ('fastapi-request-logger' )
36- self .exclude_url_patterns = exclude_url_patterns
37- logging .getLogger ("uvicorn.access" ).propagate = False
38-
39- async def dispatch (self , request : Request , call_next : RequestResponseEndpoint ) -> Response :
40- log_request = is_not_match_any_pattern (request .url .path , self .exclude_url_patterns )
41-
42- if not log_request :
43- return await call_next (request )
44-
45- request_info = json_logging .RequestInfo (request )
46- response = await call_next (request )
47- request_info .update_response_status (response )
48- self .request_logger .info (
49- "" , extra = {"request_info" : request_info , "type" : "request" }
50- )
51- return response
52-
53-
54- class FastAPIAppRequestInstrumentationConfigurator (AppRequestInstrumentationConfigurator ):
55- def config (self , app , exclude_url_patterns = tuple ()):
56- if not is_fastapi_present ():
57- raise RuntimeError ("fastapi is not available in system runtime" )
58- if not isinstance (app , fastapi .FastAPI ):
59- raise RuntimeError ("app is not a valid fastapi.FastAPI instance" )
60-
61- # Disable standard logging
62- logging .getLogger ('uvicorn.access' ).disabled = True
63-
64- # noinspection PyAttributeOutsideInit
65- self .request_logger = logging .getLogger ('fastapi-request-logger' )
66-
67- app .add_middleware (JSONLoggingASGIMiddleware , exclude_url_patterns = exclude_url_patterns )
68-
69-
70- class FastAPIRequestAdapter (RequestAdapter ):
71- @staticmethod
72- def get_request_class_type ():
73- return starlette .requests .Request
74-
75- @staticmethod
76- def support_global_request_object ():
77- return False
78-
79- @staticmethod
80- def get_current_request ():
81- raise NotImplementedError
82-
83- def get_remote_user (self , request : starlette .requests .Request ):
84- try :
85- return request .user
86- except AssertionError :
87- return json_logging .EMPTY_VALUE
88-
89- def get_http_header (self , request : starlette .requests .Request , header_name , default = None ):
90- try :
91- if header_name in request .headers :
92- return request .headers .get (header_name )
93- except :
94- pass
95- return default
96-
97- def set_correlation_id (self , request_ , value ):
98- request_ .state .correlation_id = value
99-
100- def get_correlation_id_in_request_context (self , request : starlette .requests .Request ):
101- try :
102- return request .state .correlation_id
103- except AttributeError :
104- return None
105-
106- def get_protocol (self , request : starlette .requests .Request ):
107- protocol = str (request .scope .get ('type' , '' ))
108- http_version = str (request .scope .get ('http_version' , '' ))
109- if protocol .lower () == 'http' and http_version :
110- return protocol .upper () + "/" + http_version
111- return json_logging .EMPTY_VALUE
112-
113- def get_path (self , request : starlette .requests .Request ):
114- return request .url .path
115-
116- def get_content_length (self , request : starlette .requests .Request ):
117- return request .headers .get ('content-length' , json_logging .EMPTY_VALUE )
118-
119- def get_method (self , request : starlette .requests .Request ):
120- return request .method
121-
122- def get_remote_ip (self , request : starlette .requests .Request ):
123- return request .client .host
124-
125- def get_remote_port (self , request : starlette .requests .Request ):
126- return request .client .port
127-
128-
129- class FastAPIResponseAdapter (ResponseAdapter ):
130- def get_status_code (self , response : starlette .responses .Response ):
131- return response .status_code
132-
133- def get_response_size (self , response : starlette .responses .Response ):
134- return response .headers .get ('content-length' , json_logging .EMPTY_VALUE )
135-
136- def get_content_type (self , response : starlette .responses .Response ):
137- return response .headers .get ('content-type' , json_logging .EMPTY_VALUE )
13+ from .implementation import FastAPIAppRequestInstrumentationConfigurator , FastAPIRequestAdapter , FastAPIResponseAdapter
0 commit comments