Skip to content

Commit ce04b7d

Browse files
committed
added support for quart framework
1 parent 1460d4a commit ce04b7d

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

json_logging/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,11 @@ def format(self, record):
290290
SanicAppRequestInstrumentationConfigurator,
291291
SanicRequestAdapter,
292292
SanicResponseAdapter)
293+
294+
# register quart support
295+
# noinspection PyPep8
296+
import json_logging.framework.quart as quart_support
297+
298+
register_framework_support('quart', None, quart_support.QuartAppRequestInstrumentationConfigurator,
299+
quart_support.QuartRequestAdapter,
300+
quart_support.QuartResponseAdapter)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# coding=utf-8
2+
import logging
3+
import sys
4+
5+
import json_logging
6+
import json_logging.framework
7+
from json_logging import JSONLogWebFormatter
8+
from json_logging.framework_base import AppRequestInstrumentationConfigurator, RequestAdapter, ResponseAdapter
9+
10+
11+
def is_quart_present():
12+
# noinspection PyPep8,PyBroadException
13+
try:
14+
import quart
15+
return True
16+
except:
17+
return False
18+
19+
20+
if is_quart_present():
21+
from quart import request as request_obj
22+
import quart as quart
23+
24+
_current_request = request_obj
25+
_quart = quart
26+
27+
28+
class QuartAppRequestInstrumentationConfigurator(AppRequestInstrumentationConfigurator):
29+
def config(self, app):
30+
if not is_quart_present():
31+
raise RuntimeError("quart is not available in system runtime")
32+
from quart.app import Quart
33+
if not isinstance(app, Quart):
34+
raise RuntimeError("app is not a valid quart.app.Quart app instance")
35+
36+
# Remove quart logging handlers
37+
from quart.logging import default_handler, serving_handler
38+
logging.getLogger('quart.app').removeHandler(default_handler)
39+
logging.getLogger('quart.serving').removeHandler(serving_handler)
40+
41+
42+
json_logging.util.use_cf_logging_formatter([
43+
# logging.getLogger('quart.app'),
44+
# logging.getLogger('quart.serving'),
45+
], JSONLogWebFormatter)
46+
47+
# noinspection PyAttributeOutsideInit
48+
self.request_logger = logging.getLogger('quart.app')
49+
self.request_logger.setLevel(logging.DEBUG)
50+
self.request_logger.addHandler(logging.StreamHandler(sys.stdout))
51+
52+
from quart import g
53+
54+
@app.before_request
55+
def before_request():
56+
g.request_info = json_logging.RequestInfo(_current_request)
57+
58+
@app.after_request
59+
def after_request(response):
60+
request_info = g.request_info
61+
request_info.update_response_status(response)
62+
# TODO:handle to print out request instrumentation in non-JSON mode
63+
self.request_logger.info("", extra={'request_info': request_info})
64+
return response
65+
66+
67+
class QuartRequestAdapter(RequestAdapter):
68+
@staticmethod
69+
def get_request_class_type():
70+
raise NotImplementedError
71+
72+
@staticmethod
73+
def support_global_request_object():
74+
return True
75+
76+
@staticmethod
77+
def get_current_request():
78+
return _current_request
79+
80+
def get_remote_user(self, request):
81+
if request.authorization is not None:
82+
return request.authorization.username
83+
else:
84+
return json_logging.EMPTY_VALUE
85+
86+
def is_in_request_context(self, request_):
87+
return _quart.has_request_context()
88+
89+
def get_http_header(self, request, header_name, default=None):
90+
if header_name in request.headers:
91+
return request.headers.get(header_name)
92+
return default
93+
94+
def set_correlation_id(self, request_, value):
95+
_quart.g.correlation_id = value
96+
97+
def get_correlation_id_in_request_context(self, request):
98+
return _quart.g.get('correlation_id', None)
99+
100+
def get_protocol(self, request):
101+
return request.scheme
102+
103+
def get_path(self, request):
104+
return request.path
105+
106+
def get_content_length(self, request):
107+
return request.content_length
108+
109+
def get_method(self, request):
110+
return request.method
111+
112+
def get_remote_ip(self, request):
113+
return request.remote_addr
114+
115+
def get_remote_port(self, request):
116+
return request.host.split(":", 2)[1]
117+
118+
119+
class QuartResponseAdapter(ResponseAdapter):
120+
def get_status_code(self, response):
121+
return response.status_code
122+
123+
def get_response_size(self, response):
124+
return response.content_length
125+
126+
def get_content_type(self, response):
127+
return response.content_type

0 commit comments

Comments
 (0)