Integrate gunicorn logs with bigchaindb logs

Closes #1329
This commit is contained in:
Sylvain Bellemare 2017-03-23 15:28:01 +01:00 committed by Sylvain Bellemare
parent 6e3f25a143
commit cea78b3ae2
6 changed files with 64 additions and 2 deletions

View File

@ -36,6 +36,7 @@ config = {
'bind': os.environ.get('BIGCHAINDB_SERVER_BIND') or 'localhost:9984',
'workers': None, # if none, the value will be cpu_count * 2 + 1
'threads': None, # if none, the value will be cpu_count * 2 + 1
'logger_class': 'bigchaindb.log.loggers.HttpServerLogger',
},
'database': _database_map[
os.environ.get('BIGCHAINDB_DATABASE_BACKEND', 'rethinkdb')

View File

@ -1,7 +1,12 @@
import logging
from logging.handlers import DEFAULT_TCP_LOGGING_PORT
from os.path import expanduser, join
DEFAULT_SOCKET_LOGGING_HOST = 'localhost'
DEFAULT_SOCKET_LOGGING_PORT = DEFAULT_TCP_LOGGING_PORT
DEFAULT_SOCKET_LOGGING_ADDR = (DEFAULT_SOCKET_LOGGING_HOST,
DEFAULT_SOCKET_LOGGING_PORT)
DEFAULT_LOG_DIR = expanduser('~')
PUBLISHER_LOGGING_CONFIG = {

32
bigchaindb/log/loggers.py Normal file
View File

@ -0,0 +1,32 @@
import logging.handlers
from gunicorn.glogging import Logger
from .configs import DEFAULT_SOCKET_LOGGING_HOST, DEFAULT_SOCKET_LOGGING_PORT
class HttpServerLogger(Logger):
"""Custom logger class for ``gunicorn`` logs.
Meant for internal usage only, to set the ``logger_class``
configuration setting on gunicorn.
"""
def setup(self, cfg):
"""Setup the gunicorn access and error loggers. This overrides
the parent method. Its main goal is to simply pipe all the logs to
the TCP socket used througout BigchainDB.
Args:
cfg (:obj:`gunicorn.config.Config`): Gunicorn configuration
object. *Ignored*.
"""
self._set_socklog_handler(self.error_log)
self._set_socklog_handler(self.access_log)
def _set_socklog_handler(self, log):
socket_handler = logging.handlers.SocketHandler(
DEFAULT_SOCKET_LOGGING_HOST, DEFAULT_SOCKET_LOGGING_PORT)
socket_handler._gunicorn = True
log.addHandler(socket_handler)

View File

@ -9,7 +9,12 @@ import struct
import sys
from multiprocessing import Process
from .configs import PUBLISHER_LOGGING_CONFIG, SUBSCRIBER_LOGGING_CONFIG
from .configs import (
DEFAULT_SOCKET_LOGGING_HOST,
DEFAULT_SOCKET_LOGGING_PORT,
PUBLISHER_LOGGING_CONFIG,
SUBSCRIBER_LOGGING_CONFIG,
)
from bigchaindb.common.exceptions import ConfigurationError
@ -23,7 +28,7 @@ def _normalize_log_level(level):
def setup_pub_logger():
dictConfig(PUBLISHER_LOGGING_CONFIG)
socket_handler = logging.handlers.SocketHandler(
'localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
DEFAULT_SOCKET_LOGGING_HOST, DEFAULT_SOCKET_LOGGING_PORT)
socket_handler.setLevel(logging.DEBUG)
logger = logging.getLogger()
logger.addHandler(socket_handler)

18
tests/log/test_loggers.py Normal file
View File

@ -0,0 +1,18 @@
from logging.handlers import SocketHandler
class TestHttpServerLogger:
def test_init(self, mocker):
from bigchaindb.log.configs import (
DEFAULT_SOCKET_LOGGING_ADDR as expected_socket_address)
from bigchaindb.log.loggers import HttpServerLogger
mocked_config = mocker.patch(
'gunicorn.config.Config', autospec=True, spec_set=True)
logger = HttpServerLogger(mocked_config.return_value)
assert len(logger.access_log.handlers) == 1
assert len(logger.error_log.handlers) == 1
assert isinstance(logger.access_log.handlers[0], SocketHandler)
assert isinstance(logger.error_log.handlers[0], SocketHandler)
assert logger.access_log.handlers[0].address == expected_socket_address
assert logger.error_log.handlers[0].address == expected_socket_address

View File

@ -195,6 +195,7 @@ def test_autoconfigure_read_both_from_file_and_env(monkeypatch, request):
'bind': SERVER_BIND,
'workers': None,
'threads': None,
'logger_class': 'bigchaindb.log.loggers.HttpServerLogger',
},
'database': database,
'keypair': {