2016-12-11 6 views
1

Я хотел бы gunicorn.error использовать следующий формат журнал, основанный ключ-значения, а не по умолчанию, определенном в gunicorn/glogging.py:Как переопределить протоколирование конфигурации Gunicorn, чтобы использовать пользовательский форматтер

'format': 'timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s'` 

В моем конфигурационном файле gunicorn :

import logging.config 

workers = 2 
bind = "127.0.0.1:8000" 
loglevel = 'INFO' 

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': True, 
    'formatters': { 
     'key_value': { 
      'format': 'timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s' 
     }, 
    }, 
    'handlers': { 
     'console': { 
      'level': 'INFO', 
      'class': 'logging.StreamHandler', 
      'formatter': 'key_value', 
      'stream': 'ext://sys.stdout' 
     } 
    }, 
    'loggers': { 
     'gunicorn.error': { 
      'handlers': ['console'], 
      'level': 'INFO', 
      'propagate': False, 
     }, 
     'flask.app': { 
      'handlers': ['console'], 
      'level': 'INFO', 
      'propagate': False, 
     } 
    }, 
} 

logging.config.dictConfig(LOGGING) 

Gunicorn регистрирует дважды, в моем пользовательском формате и в формате по умолчанию:

timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Starting gunicorn 19.6.0 
[2016-12-11 15:20:49 +0000] [22110] [INFO] Starting gunicorn 19.6.0 
timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Listening at: http://127.0.0.1:8000 (22110) 
[2016-12-11 15:20:49 +0000] [22110] [INFO] Listening at: http://127.0.0.1:8000 (22110) 
timestamp=2016-12-11 15:20:49,559 pid=22110 loglevel=INFO msg=Using worker: sync 
[2016-12-11 15:20:49 +0000] [22110] [INFO] Using worker: sync 
timestamp=2016-12-11 15:20:49,560 pid=22115 loglevel=INFO msg=Booting worker with pid: 22115 
[2016-12-11 15:20:49 +0000] [22115] [INFO] Booting worker with pid: 22115 
timestamp=2016-12-11 15:20:49,595 pid=22115 loglevel=INFO msg=Starting Flask application 
timestamp=2016-12-11 15:20:49,659 pid=22120 loglevel=INFO msg=Booting worker with pid: 22120 
[2016-12-11 15:20:49 +0000] [22120] [INFO] Booting worker with pid: 22120 
timestamp=2016-12-11 15:20:49,693 pid=22120 loglevel=INFO msg=Starting Flask application 

Я использовал logging_tree библиотеку, чтобы посмотреть на сконфигурированных лесорубов и я вижу 2 gunicorn регистраторы, излучающие в консоли:

<--"" 
    Level WARNING 
    | 
    o<--"flask" 
    | Level NOTSET so inherits level WARNING 
    | | 
    | o "flask.app" 
    |  Level INFO 
    |  Propagate OFF 
    |  Handler Stream <open file '<stdout>', mode 'w' at 0x7f86676b1150> 
    |   Level INFO 
    |   Formatter fmt='timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s' datefmt=None 
    | 
    o<--"gunicorn" 
     Level NOTSET so inherits level WARNING 
     | 
     o "gunicorn.access" 
     | Level INFO 
     | Propagate OFF 
     | 
     o "gunicorn.error" 
     | Level INFO 
     | Propagate OFF 
     | Handler Stream <open file '<stdout>', mode 'w' at 0x7f86676b1150> 
     |  Level INFO 
     |  Formatter fmt='timestamp=%(asctime)s pid=%(process)d loglevel=%(levelname)s msg=%(message)s' datefmt=None 
     | Handler Stream <open file '<stderr>', mode 'w' at 0x7f86676b11e0> 
     |  Formatter fmt='%(asctime)s [%(process)d] [%(levelname)s] %(message)s' datefmt='[%Y-%m-%d %H:%M:%S %z]' 
     | 
     o<--"gunicorn.http" 
      Level NOTSET so inherits level WARNING 
      | 
      o<--"gunicorn.http.wsgi" 
       Level NOTSET so inherits level WARNING 

Gunicorn-х docs говорят, что можно указать класс регистратора использовать, но я не знаю, как это сделать.

ответ

0

Я думаю, вам нужно предоставить только конфигурационный файл (.ini или .conf) с вашей собственной конфигурацией. Убедитесь, что вы переопределили значение по умолчанию.

В каталоге examples есть examples/logging.conf.

+0

Да, этот метод работает, однако поддерживается только формат .ini (fileConfig), но вы не можете использовать пользовательские фильтры в .ini. –

+0

Единственное решение, которое я знаю, это реализовать свой собственный * handler *, который создает необходимую вам фильтрацию. –

0

Мне очень повезло, указав собственный собственный класс ведения журнала. Вы можете сделать это, создав класс, который наследует класс Gunicorn gunicorn.glogging.Logger, а затем переопределяет метод setup(self, cfg) этого класса.

Например:

import logging 
from gunicorn import glogging 


class CustomLogger(glogging.Logger): 
    """Custom logger for Gunicorn log messages.""" 

    def setup(self, cfg): 
     """Configure Gunicorn application logging configuration.""" 
     super().setup(cfg) 

     # Override Gunicorn's `error_log` configuration. 
     self._set_handler(
      self.error_log, cfg.errorlog, logging.Formatter(
       fmt=('timestamp=%(asctime)s pid=%(process)d ' 
        'loglevel=%(levelname)s msg=%(message)s')) 

Теперь, в зависимости от того, как вы запустите Gunicorn, вы можете предоставить полный путь к этому классу; IE: program.app.CustomLogger с помощью опции --logger-class, или вы можете напрямую передать его в через собственный клиент Gunicorn класса приложений, как так:

from gunicorn.app import base 
from program.app import app, CustomLogger 


class WebServer(base.BaseApplication): 
    """Gunicorn WSGI Web Server.""" 

    def __init__(self, app, options): 
     """Initialize server object.""" 
     self.options = options or {} 
     self.application = app 
     super().__init__() 

    def load(): 
     """Return WSGI application.""" 
     return self.application 

    def load_config(): 
     """Load configuration into Gunicorn.""" 
     self.cfg.set('logger_class', CustomLogger) 


if __name__ == '__main__': 
    WebServer(app, {}).run() 

Это должно достичь желаемой цели без каких-либо противного INI файлов, с которыми требуются, и это полностью поддерживаемый стиль конфигурации.