diff --git a/docs/sanic/logging.md b/docs/sanic/logging.md
index eb807388..49805d0e 100644
--- a/docs/sanic/logging.md
+++ b/docs/sanic/logging.md
@@ -9,12 +9,6 @@ A simple example using default settings would be like this:
```python
from sanic import Sanic
-from sanic.config import LOGGING
-
-# The default logging handlers are ['accessStream', 'errorStream']
-# but we change it to use other handlers here for demo purpose
-LOGGING['loggers']['network']['handlers'] = [
- 'accessSysLog', 'errorSysLog']
app = Sanic('test')
@@ -23,14 +17,21 @@ async def test(request):
return response.text('Hello World!')
if __name__ == "__main__":
- app.run(log_config=LOGGING)
+ app.run(debug=True, access_log=True)
```
-And to close logging, simply assign log_config=None:
+To use your own logging config, simply use `logging.config.dictConfig`, or
+pass `log_config` when you initialize `Sanic` app:
+
+```python
+app = Sanic('test', log_config=LOGGING_CONFIG)
+```
+
+And to close logging, simply assign access_log=False:
```python
if __name__ == "__main__":
- app.run(log_config=None)
+ app.run(access_log=False)
```
This would skip calling logging functions when handling requests.
@@ -38,64 +39,29 @@ And you could even do further in production to gain extra speed:
```python
if __name__ == "__main__":
- # disable internal messages
- app.run(debug=False, log_config=None)
+ # disable debug messages
+ app.run(debug=False, access_log=False)
```
### Configuration
-By default, log_config parameter is set to use sanic.config.LOGGING dictionary for configuration. The default configuration provides several predefined `handlers`:
+By default, log_config parameter is set to use sanic.log.LOGGING_CONFIG_DEFAULTS dictionary for configuration.
-- internal (using [logging.StreamHandler](https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler))
- For internal information console outputs.
+There are three `loggers` used in sanic, and **must be defined if you want to create your own logging configuration**:
-
-- accessStream (using [logging.StreamHandler](https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler))
- For requests information logging in console
-
-
-- errorStream (using [logging.StreamHandler](https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler))
- For error message and traceback logging in console.
-
-
-- accessSysLog (using [logging.handlers.SysLogHandler](https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SysLogHandler))
- For requests information logging to syslog.
- Currently supports Windows (via localhost:514), Darwin (/var/run/syslog),
- Linux (/dev/log) and FreeBSD (/dev/log).
- You would not be able to access this property if the directory doesn't exist.
- (Notice that in Docker you have to enable everything by yourself)
-
-
-- errorSysLog (using [logging.handlers.SysLogHandler](https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SysLogHandler))
- For error message and traceback logging to syslog.
- Currently supports Windows (via localhost:514), Darwin (/var/run/syslog),
- Linux (/dev/log) and FreeBSD (/dev/log).
- You would not be able to access this property if the directory doesn't exist.
- (Notice that in Docker you have to enable everything by yourself)
-
-
-And `filters`:
-
-- accessFilter (using sanic.log.DefaultFilter)
- The filter that allows only levels in `DEBUG`, `INFO`, and `NONE(0)`
-
-
-- errorFilter (using sanic.log.DefaultFilter)
- The filter that allows only levels in `WARNING`, `ERROR`, and `CRITICAL`
-
-There are two `loggers` used in sanic, and **must be defined if you want to create your own logging configuration**:
-
-- sanic:
+- root:
Used to log internal messages.
+- sanic.error:
+ Used to log error logs.
-- network:
- Used to log requests from network, and any information from those requests.
+- sanic.access:
+ Used to log access logs.
#### Log format:
In addition to default parameters provided by python (asctime, levelname, message),
-Sanic provides additional parameters for network logger with accessFilter:
+Sanic provides additional parameters for access logger with:
- host (str)
request.ip
diff --git a/sanic/__main__.py b/sanic/__main__.py
index cc580566..594256f8 100644
--- a/sanic/__main__.py
+++ b/sanic/__main__.py
@@ -1,7 +1,7 @@
from argparse import ArgumentParser
from importlib import import_module
-from sanic.log import log
+from sanic.log import logger
from sanic.app import Sanic
if __name__ == "__main__":
@@ -36,9 +36,9 @@ if __name__ == "__main__":
app.run(host=args.host, port=args.port,
workers=args.workers, debug=args.debug, ssl=ssl)
except ImportError as e:
- log.error("No module named {} found.\n"
- " Example File: project/sanic_server.py -> app\n"
- " Example Module: project.sanic_server.app"
- .format(e.name))
+ logger.error("No module named {} found.\n"
+ " Example File: project/sanic_server.py -> app\n"
+ " Example Module: project.sanic_server.app"
+ .format(e.name))
except ValueError as e:
- log.error("{}".format(e))
+ logger.error("{}".format(e))
diff --git a/sanic/app.py b/sanic/app.py
index d6e74b16..8f1e0b90 100644
--- a/sanic/app.py
+++ b/sanic/app.py
@@ -10,11 +10,11 @@ from traceback import format_exc
from urllib.parse import urlencode, urlunparse
from ssl import create_default_context, Purpose
-from sanic.config import Config, LOGGING
+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 logger, error_logger, LOGGING_CONFIG_DEFAULTS
from sanic.response import HTTPResponse, StreamingHTTPResponse
from sanic.router import Router
from sanic.server import serve, serve_multiple, HttpProtocol, Signal
@@ -28,30 +28,21 @@ class Sanic:
def __init__(self, name=None, router=None, error_handler=None,
load_env=True, request_class=None,
- log_config=LOGGING, strict_slashes=False):
- if log_config:
- logging.config.dictConfig(log_config)
- # 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:
- formatter = logging.Formatter(
- "%(asctime)s: %(levelname)s: %(message)s")
- handler = logging.StreamHandler()
- handler.setFormatter(formatter)
- log.addHandler(handler)
- log.setLevel(logging.INFO)
+ strict_slashes=False, log_config=None):
# Get name from previous stack frame
if name is None:
frame_records = stack()[1]
name = getmodulename(frame_records[1])
+ # logging
+ logging.config.dictConfig(log_config or LOGGING_CONFIG_DEFAULTS)
+
self.name = name
self.router = router or Router()
self.request_class = request_class
self.error_handler = error_handler or ErrorHandler()
self.config = Config(load_env=load_env)
- self.log_config = log_config
self.request_middleware = deque()
self.response_middleware = deque()
self.blueprints = {}
@@ -584,7 +575,7 @@ class Sanic:
response = await self._run_response_middleware(request,
response)
except:
- log.exception(
+ error_logger.exception(
'Exception occured in one of response middleware handlers'
)
@@ -609,7 +600,7 @@ class Sanic:
def run(self, host=None, port=None, debug=False, ssl=None,
sock=None, workers=1, protocol=None,
backlog=100, stop_event=None, register_sys_signals=True,
- log_config=None):
+ access_log=True):
"""Run the HTTP Server and listen until keyboard interrupt or term
signal. On termination, drain connections before closing.
@@ -627,12 +618,10 @@ class Sanic:
:param protocol: Subclass of asyncio protocol class
:return: Nothing
"""
+
if sock is None:
host, port = host or "127.0.0.1", port or 8000
- if log_config:
- self.log_config = log_config
- logging.config.dictConfig(log_config)
if protocol is None:
protocol = (WebSocketProtocol if self.websocket_enabled
else HttpProtocol)
@@ -645,7 +634,7 @@ class Sanic:
host=host, port=port, debug=debug, ssl=ssl, sock=sock,
workers=workers, protocol=protocol, backlog=backlog,
register_sys_signals=register_sys_signals,
- has_log=self.log_config is not None)
+ access_log=access_log)
try:
self.is_running = True
@@ -654,12 +643,12 @@ class Sanic:
else:
serve_multiple(server_settings, workers)
except:
- log.exception(
+ error_logger.exception(
'Experienced exception while trying to serve')
raise
finally:
self.is_running = False
- log.info("Server Stopped")
+ logger.info("Server Stopped")
def stop(self):
"""This kills the Sanic"""
@@ -672,17 +661,16 @@ class Sanic:
async def create_server(self, host=None, port=None, debug=False,
ssl=None, sock=None, protocol=None,
backlog=100, stop_event=None,
- log_config=LOGGING):
+ access_log=True):
"""Asynchronous version of `run`.
NOTE: This does not support multiprocessing and is not the preferred
way to run a Sanic application.
"""
+
if sock is None:
host, port = host or "127.0.0.1", port or 8000
- if log_config:
- logging.config.dictConfig(log_config)
if protocol is None:
protocol = (WebSocketProtocol if self.websocket_enabled
else HttpProtocol)
@@ -696,7 +684,7 @@ class Sanic:
host=host, port=port, debug=debug, ssl=ssl, sock=sock,
loop=get_event_loop(), protocol=protocol,
backlog=backlog, run_async=True,
- has_log=log_config is not None)
+ access_log=access_log)
# Trigger before_start events
await self.trigger_events(
@@ -741,7 +729,7 @@ class Sanic:
def _helper(self, host=None, port=None, debug=False,
ssl=None, sock=None, workers=1, loop=None,
protocol=HttpProtocol, backlog=100, stop_event=None,
- register_sys_signals=True, run_async=False, has_log=True):
+ register_sys_signals=True, run_async=False, access_log=True):
"""Helper function used by `run` and `create_server`."""
if isinstance(ssl, dict):
# try common aliaseses
@@ -782,7 +770,7 @@ class Sanic:
'loop': loop,
'register_sys_signals': register_sys_signals,
'backlog': backlog,
- 'has_log': has_log,
+ 'access_log': access_log,
'websocket_max_size': self.config.WEBSOCKET_MAX_SIZE,
'websocket_max_queue': self.config.WEBSOCKET_MAX_QUEUE,
'graceful_shutdown_timeout': self.config.GRACEFUL_SHUTDOWN_TIMEOUT
@@ -806,9 +794,9 @@ class Sanic:
server_settings[settings_name] = listeners
if debug:
- log.setLevel(logging.DEBUG)
+ logger.setLevel(logging.DEBUG)
if self.config.LOGO is not None:
- log.debug(self.config.LOGO)
+ logger.debug(self.config.LOGO)
if run_async:
server_settings['run_async'] = True
@@ -818,6 +806,6 @@ class Sanic:
proto = "http"
if ssl is not None:
proto = "https"
- log.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port))
+ logger.info('Goin\' Fast @ {}://{}:{}'.format(proto, host, port))
return server_settings
diff --git a/sanic/config.py b/sanic/config.py
index 1067bd0c..741da019 100644
--- a/sanic/config.py
+++ b/sanic/config.py
@@ -1,107 +1,9 @@
import os
-import sys
-import platform
import types
-from sanic.log import DefaultFilter
SANIC_PREFIX = 'SANIC_'
-try:
- from syslog import LOG_DAEMON
-except ImportError:
- LOG_DAEMON = 24
-
-_address_dict = {
- 'Windows': ('localhost', 514),
- 'Darwin': '/var/run/syslog',
- 'Linux': '/dev/log',
- 'FreeBSD': '/var/run/log'
-}
-
-LOGGING = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'filters': {
- 'accessFilter': {
- '()': DefaultFilter,
- 'param': [0, 10, 20]
- },
- 'errorFilter': {
- '()': 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 - (%(name)s)[%(levelname)s][%(host)s]: ' +
- '%(request)s %(message)s %(status)d %(byte)d',
- 'datefmt': '%Y-%m-%d %H:%M:%S'
- }
- },
- 'handlers': {
- 'internal': {
- 'class': 'logging.StreamHandler',
- 'filters': ['accessFilter'],
- 'formatter': 'simple',
- 'stream': sys.stderr
- },
- 'accessStream': {
- 'class': 'logging.StreamHandler',
- 'filters': ['accessFilter'],
- 'formatter': 'access',
- 'stream': sys.stderr
- },
- 'errorStream': {
- 'class': 'logging.StreamHandler',
- 'filters': ['errorFilter'],
- 'formatter': 'simple',
- 'stream': sys.stderr
- },
- # before you use accessSysLog, be sure that log levels
- # 0, 10, 20 have been enabled in you syslog configuration
- # otherwise you won't be able to see the output in syslog
- # logging file.
- 'accessSysLog': {
- 'class': 'logging.handlers.SysLogHandler',
- 'address': _address_dict.get(platform.system(),
- ('localhost', 514)),
- 'facility': LOG_DAEMON,
- 'filters': ['accessFilter'],
- 'formatter': 'access'
- },
- 'errorSysLog': {
- 'class': 'logging.handlers.SysLogHandler',
- 'address': _address_dict.get(platform.system(),
- ('localhost', 514)),
- 'facility': LOG_DAEMON,
- 'filters': ['errorFilter'],
- 'formatter': 'simple'
- },
- },
- 'loggers': {
- 'sanic': {
- 'level': 'INFO',
- 'handlers': ['internal', 'errorStream']
- },
- 'network': {
- 'level': 'INFO',
- 'handlers': ['accessStream', 'errorStream']
- }
- }
-}
-
-# this happens when using container or systems without syslog
-# keep things in config would cause file not exists error
-_addr = LOGGING['handlers']['accessSysLog']['address']
-if type(_addr) is str and not os.path.exists(_addr):
- LOGGING['handlers'].pop('accessSysLog')
- LOGGING['handlers'].pop('errorSysLog')
-
class Config(dict):
def __init__(self, defaults=None, load_env=True, keep_alive=True):
diff --git a/sanic/handlers.py b/sanic/handlers.py
index 6a87fd5d..2e335b09 100644
--- a/sanic/handlers.py
+++ b/sanic/handlers.py
@@ -12,7 +12,7 @@ from sanic.exceptions import (
TRACEBACK_WRAPPER_HTML,
TRACEBACK_WRAPPER_INNER_HTML,
TRACEBACK_BORDER)
-from sanic.log import log
+from sanic.log import logger
from sanic.response import text, html
@@ -90,7 +90,7 @@ class ErrorHandler:
'Exception raised in exception handler "{}" '
'for uri: "{}"\n{}').format(
handler.__name__, url, format_exc())
- log.error(response_message)
+ logger.error(response_message)
return text(response_message, 500)
else:
return text('An error occurred while handling an error', 500)
@@ -101,7 +101,7 @@ class ErrorHandler:
Override this method in an ErrorHandler subclass to prevent
logging exceptions.
"""
- getattr(log, level)(message)
+ getattr(logger, level)(message)
def default(self, request, exception):
self.log(format_exc())
@@ -117,7 +117,7 @@ class ErrorHandler:
response_message = (
'Exception occurred while handling uri: "{}"\n{}'.format(
request.url, format_exc()))
- log.error(response_message)
+ logger.error(response_message)
return html(html_output, status=500)
else:
return html(INTERNAL_SERVER_ERROR_HTML, status=500)
diff --git a/sanic/log.py b/sanic/log.py
index 760ad1c6..9c6d868d 100644
--- a/sanic/log.py
+++ b/sanic/log.py
@@ -1,18 +1,63 @@
import logging
+import sys
-class DefaultFilter(logging.Filter):
+LOGGING_CONFIG_DEFAULTS = dict(
+ version=1,
+ disable_existing_loggers=False,
- def __init__(self, param=None):
- self.param = param
+ loggers={
+ "root": {
+ "level": "INFO",
+ "handlers": ["console"]
+ },
+ "sanic.error": {
+ "level": "INFO",
+ "handlers": ["error_console"],
+ "propagate": True,
+ "qualname": "sanic.error"
+ },
- def filter(self, record):
- if self.param is None:
- return True
- if record.levelno in self.param:
- return True
- return False
+ "sanic.access": {
+ "level": "INFO",
+ "handlers": ["access_console"],
+ "propagate": True,
+ "qualname": "sanic.access"
+ }
+ },
+ handlers={
+ "console": {
+ "class": "logging.StreamHandler",
+ "formatter": "generic",
+ "stream": sys.stdout
+ },
+ "error_console": {
+ "class": "logging.StreamHandler",
+ "formatter": "generic",
+ "stream": sys.stderr
+ },
+ "access_console": {
+ "class": "logging.StreamHandler",
+ "formatter": "access",
+ "stream": sys.stdout
+ },
+ },
+ formatters={
+ "generic": {
+ "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
+ "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
+ "class": "logging.Formatter"
+ },
+ "access": {
+ "format": "%(asctime)s - (%(name)s)[%(levelname)s][%(host)s]: " +
+ "%(request)s %(message)s %(status)d %(byte)d",
+ "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
+ "class": "logging.Formatter"
+ },
+ }
+)
-log = logging.getLogger('sanic')
-netlog = logging.getLogger('network')
+logger = logging.getLogger('root')
+error_logger = logging.getLogger('sanic.error')
+access_logger = logging.getLogger('sanic.access')
diff --git a/sanic/request.py b/sanic/request.py
index ae6a340e..26f19baf 100644
--- a/sanic/request.py
+++ b/sanic/request.py
@@ -17,7 +17,7 @@ except ImportError:
json_loads = json.loads
from sanic.exceptions import InvalidUsage
-from sanic.log import log
+from sanic.log import error_logger
DEFAULT_HTTP_CONTENT_TYPE = "application/octet-stream"
@@ -127,7 +127,7 @@ class Request(dict):
self.parsed_form, self.parsed_files = (
parse_multipart_form(self.body, boundary))
except Exception:
- log.exception("Failed when parsing form")
+ error_logger.exception("Failed when parsing form")
return self.parsed_form
diff --git a/sanic/server.py b/sanic/server.py
index e66afcf8..a17e479b 100644
--- a/sanic/server.py
+++ b/sanic/server.py
@@ -24,7 +24,7 @@ try:
except ImportError:
async_loop = asyncio
-from sanic.log import log, netlog
+from sanic.log import logger, access_logger
from sanic.response import HTTPResponse
from sanic.request import Request
from sanic.exceptions import (
@@ -67,8 +67,8 @@ class HttpProtocol(asyncio.Protocol):
'request_handler', 'request_timeout', 'response_timeout',
'keep_alive_timeout', 'request_max_size', 'request_class',
'is_request_stream', 'router',
- # enable or disable access log / error log purpose
- 'has_log',
+ # enable or disable access log purpose
+ 'access_log',
# connection management
'_total_request_size', '_request_timeout_handler',
'_response_timeout_handler', '_keep_alive_timeout_handler',
@@ -77,7 +77,7 @@ class HttpProtocol(asyncio.Protocol):
def __init__(self, *, loop, request_handler, error_handler,
signal=Signal(), connections=set(), request_timeout=60,
response_timeout=60, keep_alive_timeout=15,
- request_max_size=None, request_class=None, has_log=True,
+ request_max_size=None, request_class=None, access_log=True,
keep_alive=True, is_request_stream=False, router=None,
state=None, debug=False, **kwargs):
self.loop = loop
@@ -88,7 +88,7 @@ class HttpProtocol(asyncio.Protocol):
self.headers = None
self.router = router
self.signal = signal
- self.has_log = has_log
+ self.access_log = access_log
self.connections = connections
self.request_handler = request_handler
self.error_handler = error_handler
@@ -190,7 +190,7 @@ class HttpProtocol(asyncio.Protocol):
self.keep_alive_timeout_callback)
)
else:
- log.info('KeepAlive Timeout. Closing connection.')
+ logger.info('KeepAlive Timeout. Closing connection.')
self.transport.close()
# -------------------------------------------- #
@@ -337,13 +337,13 @@ class HttpProtocol(asyncio.Protocol):
self.keep_alive_timeout))
self.log_response(response)
except AttributeError:
- log.error(
+ logger.error(
('Invalid response object for url {}, '
'Expected Type: HTTPResponse, Actual Type: {}').format(
self.url, type(response)))
self.write_error(ServerError('Invalid response type'))
except RuntimeError:
- log.error(
+ logger.error(
'Connection lost before response written @ {}'.format(
self.request.ip))
except Exception as e:
@@ -376,13 +376,13 @@ class HttpProtocol(asyncio.Protocol):
self.request.version, keep_alive, self.keep_alive_timeout)
self.log_response(response)
except AttributeError:
- log.error(
+ logger.error(
('Invalid response object for url {}, '
'Expected Type: HTTPResponse, Actual Type: {}').format(
self.url, type(response)))
self.write_error(ServerError('Invalid response type'))
except RuntimeError:
- log.error(
+ logger.error(
'Connection lost before response written @ {}'.format(
self.request.ip))
except Exception as e:
@@ -411,7 +411,7 @@ class HttpProtocol(asyncio.Protocol):
version = self.request.version if self.request else '1.1'
self.transport.write(response.output(version))
except RuntimeError:
- log.error(
+ logger.error(
'Connection lost before error written @ {}'.format(
self.request.ip if self.request else 'Unknown'))
except Exception as e:
@@ -427,16 +427,16 @@ class HttpProtocol(asyncio.Protocol):
def bail_out(self, message, from_error=False):
if from_error or self.transport.is_closing():
- log.error(
+ logger.error(
("Transport closed @ {} and exception "
"experienced during error handling").format(
self.transport.get_extra_info('peername')))
- log.debug(
+ logger.debug(
'Exception:\n{}'.format(traceback.format_exc()))
else:
exception = ServerError(message)
self.write_error(exception)
- log.error(message)
+ logger.error(message)
def cleanup(self):
"""This is called when KeepAlive feature is used,
@@ -500,7 +500,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
ssl=None, sock=None, request_max_size=None, reuse_port=False,
loop=None, protocol=HttpProtocol, backlog=100,
register_sys_signals=True, run_async=False, connections=None,
- signal=Signal(), request_class=None, has_log=True,
+ signal=Signal(), request_class=None, access_log=True,
keep_alive=True, is_request_stream=False, router=None,
websocket_max_size=None, websocket_max_queue=None, state=None,
graceful_shutdown_timeout=15.0):
@@ -529,7 +529,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
:param loop: asyncio compatible event loop
:param protocol: subclass of asyncio protocol class
:param request_class: Request class to use
- :param has_log: disable/enable access log and error log
+ :param access_log: disable/enable access log
:param is_request_stream: disable/enable Request.stream
:param router: Router object
:return: Nothing
@@ -554,7 +554,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
keep_alive_timeout=keep_alive_timeout,
request_max_size=request_max_size,
request_class=request_class,
- has_log=has_log,
+ access_log=access_log,
keep_alive=keep_alive,
is_request_stream=is_request_stream,
router=router,
@@ -586,7 +586,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
try:
http_server = loop.run_until_complete(server_coroutine)
except:
- log.exception("Unable to start server")
+ logger.exception("Unable to start server")
return
trigger_events(after_start, loop)
@@ -597,14 +597,15 @@ def serve(host, port, request_handler, error_handler, before_start=None,
try:
loop.add_signal_handler(_signal, loop.stop)
except NotImplementedError:
- log.warn('Sanic tried to use loop.add_signal_handler but it is'
- ' not implemented on this platform.')
+ logger.warn(
+ 'Sanic tried to use loop.add_signal_handler but it is'
+ ' not implemented on this platform.')
pid = os.getpid()
try:
- log.info('Starting worker [{}]'.format(pid))
+ logger.info('Starting worker [{}]'.format(pid))
loop.run_forever()
finally:
- log.info("Stopping worker [{}]".format(pid))
+ logger.info("Stopping worker [{}]".format(pid))
# Run the on_stop function if provided
trigger_events(before_stop, loop)
@@ -666,7 +667,7 @@ def serve_multiple(server_settings, workers):
server_settings['port'] = None
def sig_handler(signal, frame):
- log.info("Received signal {}. Shutting down.".format(
+ logger.info("Received signal {}. Shutting down.".format(
Signals(signal).name))
for process in processes:
os.kill(process.pid, SIGINT)
diff --git a/sanic/testing.py b/sanic/testing.py
index de26d025..5d233d7b 100644
--- a/sanic/testing.py
+++ b/sanic/testing.py
@@ -1,7 +1,7 @@
import traceback
from json import JSONDecodeError
-from sanic.log import log
+from sanic.log import logger
HOST = '127.0.0.1'
PORT = 42101
@@ -19,7 +19,7 @@ class SanicTestClient:
url = 'http://{host}:{port}{uri}'.format(
host=HOST, port=PORT, uri=uri)
- log.info(url)
+ logger.info(url)
conn = aiohttp.TCPConnector(verify_ssl=False)
async with aiohttp.ClientSession(
cookies=cookies, connector=conn) as session:
@@ -61,7 +61,7 @@ class SanicTestClient:
**request_kwargs)
results[-1] = response
except Exception as e:
- log.error(
+ logger.error(
'Exception:\n{}'.format(traceback.format_exc()))
exceptions.append(e)
self.app.stop()
diff --git a/tests/test_logging.py b/tests/test_logging.py
index d6911d86..112c94a0 100644
--- a/tests/test_logging.py
+++ b/tests/test_logging.py
@@ -1,8 +1,8 @@
import uuid
from importlib import reload
-from sanic.config import LOGGING
from sanic.response import text
+from sanic.log import LOGGING_CONFIG_DEFAULTS
from sanic import Sanic
from io import StringIO
import logging
@@ -40,18 +40,34 @@ def test_log():
assert rand_string in log_text
-def test_default_log_fmt():
-
+def test_logging_defaults():
reset_logging()
- Sanic()
- for fmt in [h.formatter for h in logging.getLogger('sanic').handlers]:
- assert fmt._fmt == LOGGING['formatters']['simple']['format']
+ app = Sanic("test_logging")
+ for fmt in [h.formatter for h in logging.getLogger('root').handlers]:
+ assert fmt._fmt == LOGGING_CONFIG_DEFAULTS['formatters']['generic']['format']
+
+ for fmt in [h.formatter for h in logging.getLogger('sanic.error').handlers]:
+ assert fmt._fmt == LOGGING_CONFIG_DEFAULTS['formatters']['generic']['format']
+
+ for fmt in [h.formatter for h in logging.getLogger('sanic.access').handlers]:
+ assert fmt._fmt == LOGGING_CONFIG_DEFAULTS['formatters']['access']['format']
+
+
+def test_logging_pass_customer_logconfig():
reset_logging()
- Sanic(log_config=None)
- for fmt in [h.formatter for h in logging.getLogger('sanic').handlers]:
- assert fmt._fmt == "%(asctime)s: %(levelname)s: %(message)s"
+ modified_config = LOGGING_CONFIG_DEFAULTS
+ modified_config['formatters']['generic']['format'] = '%(asctime)s - (%(name)s)[%(levelname)s]: %(message)s'
+ modified_config['formatters']['access']['format'] = '%(asctime)s - (%(name)s)[%(levelname)s]: %(message)s'
-if __name__ == "__main__":
- test_log()
+ app = Sanic("test_logging", log_config=modified_config)
+
+ for fmt in [h.formatter for h in logging.getLogger('root').handlers]:
+ assert fmt._fmt == modified_config['formatters']['generic']['format']
+
+ for fmt in [h.formatter for h in logging.getLogger('sanic.error').handlers]:
+ assert fmt._fmt == modified_config['formatters']['generic']['format']
+
+ for fmt in [h.formatter for h in logging.getLogger('sanic.access').handlers]:
+ assert fmt._fmt == modified_config['formatters']['access']['format']