Merge branch 'logging'
This commit is contained in:
commit
bf46bcf376
|
@ -16,4 +16,5 @@ dependencies:
|
|||
- ujson>=1.35
|
||||
- aiofiles>=0.3.0
|
||||
- websockets>=3.2
|
||||
- pyyaml>=3.12
|
||||
- https://github.com/channelcat/docutils-fork/zipball/master
|
|
@ -8,3 +8,4 @@ pytest
|
|||
tox
|
||||
ujson
|
||||
uvloop
|
||||
pyyaml
|
||||
|
|
|
@ -3,3 +3,4 @@ httptools
|
|||
ujson
|
||||
uvloop
|
||||
websockets
|
||||
pyyaml
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import os
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from importlib import import_module
|
||||
|
||||
from sanic import __path__ as lib_path
|
||||
from sanic.log import log
|
||||
from sanic.app import Sanic
|
||||
|
||||
|
@ -14,6 +17,8 @@ if __name__ == "__main__":
|
|||
help='location of keyfile for SSL.')
|
||||
parser.add_argument('--workers', dest='workers', type=int, default=1, )
|
||||
parser.add_argument('--debug', dest='debug', action="store_true")
|
||||
parser.add_argument('--log', dest='log_config_path', type=str,
|
||||
default=os.path.join(lib_path[0], 'default.conf'))
|
||||
parser.add_argument('module')
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -34,7 +39,8 @@ if __name__ == "__main__":
|
|||
ssl = None
|
||||
|
||||
app.run(host=args.host, port=args.port,
|
||||
workers=args.workers, debug=args.debug, ssl=ssl)
|
||||
workers=args.workers, debug=args.debug, ssl=ssl,
|
||||
log_config_path=args.log_config_path)
|
||||
except ImportError:
|
||||
log.error("No module named {} found.\n"
|
||||
" Example File: project/sanic_server.py -> app\n"
|
||||
|
|
43
sanic/app.py
43
sanic/app.py
|
@ -1,6 +1,9 @@
|
|||
import logging
|
||||
import logging.config
|
||||
import re
|
||||
import warnings
|
||||
import os
|
||||
import yaml
|
||||
from asyncio import get_event_loop, ensure_future, CancelledError
|
||||
from collections import deque, defaultdict
|
||||
from functools import partial
|
||||
|
@ -9,11 +12,12 @@ from traceback import format_exc
|
|||
from urllib.parse import urlencode, urlunparse
|
||||
from ssl import create_default_context, Purpose
|
||||
|
||||
from sanic import __path__ as lib_path
|
||||
from sanic.config import Config
|
||||
from sanic.constants import HTTP_METHODS
|
||||
from sanic.exceptions import ServerError, URLBuildError, SanicException
|
||||
from sanic.handlers import ErrorHandler
|
||||
from sanic.log import log
|
||||
from sanic.log import log, netlog
|
||||
from sanic.response import HTTPResponse, StreamingHTTPResponse
|
||||
from sanic.router import Router
|
||||
from sanic.server import serve, serve_multiple, HttpProtocol
|
||||
|
@ -26,10 +30,17 @@ from sanic.websocket import WebSocketProtocol, ConnectionClosed
|
|||
class Sanic:
|
||||
|
||||
def __init__(self, name=None, router=None, error_handler=None,
|
||||
load_env=True):
|
||||
load_env=True,
|
||||
log_config_path=os.path.join(lib_path[0], "default.conf")):
|
||||
conf = None
|
||||
if log_config_path and os.path.exists(log_config_path):
|
||||
with open(log_config_path) as f:
|
||||
conf = yaml.load(f)
|
||||
conf.setdefault('version', 1)
|
||||
logging.config.dictConfig(conf)
|
||||
# Only set up a default log handler if the
|
||||
# end-user application didn't set anything up.
|
||||
if not logging.root.handlers and log.level == logging.NOTSET:
|
||||
if not conf and log.level == logging.NOTSET:
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s: %(levelname)s: %(message)s")
|
||||
handler = logging.StreamHandler()
|
||||
|
@ -46,6 +57,7 @@ class Sanic:
|
|||
self.router = router or Router()
|
||||
self.error_handler = error_handler or ErrorHandler()
|
||||
self.config = Config(load_env=load_env)
|
||||
self.log_config_path = log_config_path
|
||||
self.request_middleware = deque()
|
||||
self.response_middleware = deque()
|
||||
self.blueprints = {}
|
||||
|
@ -442,7 +454,6 @@ class Sanic:
|
|||
# -------------------------------------------- #
|
||||
# Request Middleware
|
||||
# -------------------------------------------- #
|
||||
|
||||
request.app = self
|
||||
response = await self._run_request_middleware(request)
|
||||
# No middleware results
|
||||
|
@ -490,6 +501,13 @@ class Sanic:
|
|||
log.exception(
|
||||
'Exception occured in one of response middleware handlers'
|
||||
)
|
||||
if self.log_config_path:
|
||||
netlog.info('', extra={
|
||||
"host": "%s:%d" % request.ip,
|
||||
"request": "%s %s" % (request.method, request.query_string),
|
||||
"status": response.status,
|
||||
"byte": len(response.body)
|
||||
})
|
||||
|
||||
# pass the response to the correct callback
|
||||
if isinstance(response, StreamingHTTPResponse):
|
||||
|
@ -512,7 +530,8 @@ class Sanic:
|
|||
def run(self, host="127.0.0.1", port=8000, debug=False, before_start=None,
|
||||
after_start=None, before_stop=None, after_stop=None, ssl=None,
|
||||
sock=None, workers=1, loop=None, protocol=None,
|
||||
backlog=100, stop_event=None, register_sys_signals=True):
|
||||
backlog=100, stop_event=None, register_sys_signals=True,
|
||||
log_config_path=os.path.join(lib_path[0], "default.yml")):
|
||||
"""Run the HTTP Server and listen until keyboard interrupt or term
|
||||
signal. On termination, drain connections before closing.
|
||||
|
||||
|
@ -539,6 +558,11 @@ class Sanic:
|
|||
:param protocol: Subclass of asyncio protocol class
|
||||
:return: Nothing
|
||||
"""
|
||||
if log_config_path and os.path.exists(log_config_path):
|
||||
with open(log_config_path) as f:
|
||||
conf = yaml.load(f)
|
||||
conf.setdefault('version', 1)
|
||||
logging.config.dictConfig(conf)
|
||||
if protocol is None:
|
||||
protocol = (WebSocketProtocol if self.websocket_enabled
|
||||
else HttpProtocol)
|
||||
|
@ -579,12 +603,19 @@ class Sanic:
|
|||
before_start=None, after_start=None,
|
||||
before_stop=None, after_stop=None, ssl=None,
|
||||
sock=None, loop=None, protocol=None,
|
||||
backlog=100, stop_event=None):
|
||||
backlog=100, stop_event=None,
|
||||
log_config_path=os.path.join(lib_path[0],
|
||||
"default.yml")):
|
||||
"""Asynchronous version of `run`.
|
||||
|
||||
NOTE: This does not support multiprocessing and is not the preferred
|
||||
way to run a Sanic application.
|
||||
"""
|
||||
if log_config_path and os.path.exists(log_config_path):
|
||||
with open(log_config_path) as f:
|
||||
conf = yaml.load(f)
|
||||
conf.setdefault('version', 1)
|
||||
logging.config.dictConfig(conf)
|
||||
if protocol is None:
|
||||
protocol = (WebSocketProtocol if self.websocket_enabled
|
||||
else HttpProtocol)
|
||||
|
|
52
sanic/default.yml
Normal file
52
sanic/default.yml
Normal file
|
@ -0,0 +1,52 @@
|
|||
version: 1
|
||||
filters:
|
||||
access_filter:
|
||||
(): sanic.defaultFilter.DefaultFilter
|
||||
param: [0, 10, 20]
|
||||
error_filter:
|
||||
(): sanic.defaultFilter.DefaultFilter
|
||||
param: [30, 40, 50]
|
||||
|
||||
formatters:
|
||||
simple:
|
||||
format: '%(asctime)s - (%(name)s)[%(levelname)s]: %(message)s'
|
||||
datefmt: '%Y-%m-%d %H:%M:%S'
|
||||
access:
|
||||
format: '%(asctime)s - [%(levelname)s][%(host)s]: %(request)s %(message)s %(status)s %(byte)d'
|
||||
datefmt: '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
handlers:
|
||||
internal:
|
||||
class: logging.handlers.TimedRotatingFileHandler
|
||||
filters: [access_filter]
|
||||
formatter: simple
|
||||
when: 'D'
|
||||
interval: 1
|
||||
backupCount: 7
|
||||
filename: 'access.log'
|
||||
|
||||
access:
|
||||
class: logging.handlers.TimedRotatingFileHandler
|
||||
filters: [access_filter]
|
||||
formatter: access
|
||||
when: 'D'
|
||||
interval: 1
|
||||
backupCount: 7
|
||||
filename: 'access.log'
|
||||
|
||||
error:
|
||||
class: logging.handlers.TimedRotatingFileHandler
|
||||
filters: [error_filter]
|
||||
filename: 'error.log'
|
||||
when: 'D'
|
||||
interval: 1
|
||||
backupCount: 7
|
||||
formatter: simple
|
||||
|
||||
loggers:
|
||||
sanic:
|
||||
level: DEBUG
|
||||
handlers: [internal, error]
|
||||
network:
|
||||
level: DEBUG
|
||||
handlers: [access, error]
|
13
sanic/defaultFilter.py
Normal file
13
sanic/defaultFilter.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import logging
|
||||
|
||||
|
||||
class DefaultFilter(logging.Filter):
|
||||
def __init__(self, param=None):
|
||||
self.param = param
|
||||
|
||||
def filter(self, record):
|
||||
if self.param is None:
|
||||
return True
|
||||
if record.levelno in self.param:
|
||||
return True
|
||||
return False
|
|
@ -1,3 +1,4 @@
|
|||
import logging
|
||||
|
||||
log = logging.getLogger('sanic')
|
||||
netlog = logging.getLogger('network')
|
||||
|
|
2
setup.py
2
setup.py
|
@ -27,6 +27,7 @@ setup_kwargs = {
|
|||
'description': (
|
||||
'A microframework based on uvloop, httptools, and learnings of flask'),
|
||||
'packages': ['sanic'],
|
||||
'package_data': {'':['default.yml']},
|
||||
'platforms': 'any',
|
||||
'classifiers': [
|
||||
'Development Status :: 2 - Pre-Alpha',
|
||||
|
@ -46,6 +47,7 @@ requirements = [
|
|||
ujson,
|
||||
'aiofiles>=0.3.0',
|
||||
'websockets>=3.2',
|
||||
'pyyaml>=3.12'
|
||||
]
|
||||
if strtobool(os.environ.get("SANIC_NO_UJSON", "no")):
|
||||
print("Installing without uJSON")
|
||||
|
|
Loading…
Reference in New Issue
Block a user