-
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from Darkless012/quart-framework-support
added support for quart framework
- Loading branch information
Showing
5 changed files
with
234 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import asyncio | ||
import logging | ||
import sys | ||
|
||
import quart | ||
|
||
import json_logging | ||
|
||
app = quart.Quart(__name__) | ||
json_logging.ENABLE_JSON_LOGGING = True | ||
json_logging.init(framework_name='quart') | ||
json_logging.init_request_instrument(app) | ||
|
||
# init the logger as usual | ||
logger = logging.getLogger("test logger") | ||
logger.setLevel(logging.DEBUG) | ||
logger.addHandler(logging.StreamHandler(sys.stdout)) | ||
|
||
|
||
@app.route('/') | ||
async def home(): | ||
logger.info("test log statement") | ||
logger.info("test log statement", extra={'props': {"extra_property": 'extra_value'}}) | ||
return "Hello world" | ||
|
||
|
||
if __name__ == "__main__": | ||
loop = asyncio.get_event_loop() | ||
app.run(host='0.0.0.0', port=int(5000), use_reloader=False, loop=loop) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# coding=utf-8 | ||
import logging | ||
import sys | ||
|
||
import json_logging | ||
import json_logging.framework | ||
from json_logging import JSONLogWebFormatter | ||
from json_logging.framework_base import AppRequestInstrumentationConfigurator, RequestAdapter, ResponseAdapter | ||
|
||
|
||
def is_quart_present(): | ||
# noinspection PyPep8,PyBroadException | ||
try: | ||
import quart | ||
return True | ||
except: | ||
return False | ||
|
||
|
||
if is_quart_present(): | ||
from quart import request as request_obj | ||
import quart as quart | ||
|
||
_current_request = request_obj | ||
_quart = quart | ||
|
||
|
||
class QuartAppRequestInstrumentationConfigurator(AppRequestInstrumentationConfigurator): | ||
def config(self, app): | ||
if not is_quart_present(): | ||
raise RuntimeError("quart is not available in system runtime") | ||
from quart.app import Quart | ||
if not isinstance(app, Quart): | ||
raise RuntimeError("app is not a valid quart.app.Quart app instance") | ||
|
||
# Remove quart logging handlers | ||
from quart.logging import default_handler, serving_handler | ||
logging.getLogger('quart.app').removeHandler(default_handler) | ||
logging.getLogger('quart.serving').removeHandler(serving_handler) | ||
|
||
|
||
json_logging.util.use_cf_logging_formatter([ | ||
# logging.getLogger('quart.app'), | ||
# logging.getLogger('quart.serving'), | ||
], JSONLogWebFormatter) | ||
|
||
# noinspection PyAttributeOutsideInit | ||
self.request_logger = logging.getLogger('quart.app') | ||
self.request_logger.setLevel(logging.DEBUG) | ||
self.request_logger.addHandler(logging.StreamHandler(sys.stdout)) | ||
|
||
from quart import g | ||
|
||
@app.before_request | ||
def before_request(): | ||
g.request_info = json_logging.RequestInfo(_current_request) | ||
|
||
@app.after_request | ||
def after_request(response): | ||
request_info = g.request_info | ||
request_info.update_response_status(response) | ||
# TODO:handle to print out request instrumentation in non-JSON mode | ||
self.request_logger.info("", extra={'request_info': request_info}) | ||
return response | ||
|
||
|
||
class QuartRequestAdapter(RequestAdapter): | ||
@staticmethod | ||
def get_request_class_type(): | ||
raise NotImplementedError | ||
|
||
@staticmethod | ||
def support_global_request_object(): | ||
return True | ||
|
||
@staticmethod | ||
def get_current_request(): | ||
return _current_request | ||
|
||
def get_remote_user(self, request): | ||
if request.authorization is not None: | ||
return request.authorization.username | ||
else: | ||
return json_logging.EMPTY_VALUE | ||
|
||
def is_in_request_context(self, request_): | ||
return _quart.has_request_context() | ||
|
||
def get_http_header(self, request, header_name, default=None): | ||
if header_name in request.headers: | ||
return request.headers.get(header_name) | ||
return default | ||
|
||
def set_correlation_id(self, request_, value): | ||
_quart.g.correlation_id = value | ||
|
||
def get_correlation_id_in_request_context(self, request): | ||
return _quart.g.get('correlation_id', None) | ||
|
||
def get_protocol(self, request): | ||
return request.scheme | ||
|
||
def get_path(self, request): | ||
return request.path | ||
|
||
def get_content_length(self, request): | ||
return request.content_length | ||
|
||
def get_method(self, request): | ||
return request.method | ||
|
||
def get_remote_ip(self, request): | ||
return request.remote_addr | ||
|
||
def get_remote_port(self, request): | ||
return request.host.split(":", 2)[1] | ||
|
||
|
||
class QuartResponseAdapter(ResponseAdapter): | ||
def get_status_code(self, response): | ||
return response.status_code | ||
|
||
def get_response_size(self, response): | ||
return response.content_length | ||
|
||
def get_content_type(self, response): | ||
return response.content_type |