You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					479 lines
				
				15 KiB
			
		
		
			
		
	
	
					479 lines
				
				15 KiB
			| 
								 
											8 years ago
										 
									 | 
							
								# -*- coding: utf-8 -
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# This file is part of gunicorn released under the MIT license.
							 | 
						||
| 
								 | 
							
								# See the NOTICE for more information.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import base64
							 | 
						||
| 
								 | 
							
								import binascii
							 | 
						||
| 
								 | 
							
								import time
							 | 
						||
| 
								 | 
							
								import logging
							 | 
						||
| 
								 | 
							
								logging.Logger.manager.emittedNoHandlerWarning = 1
							 | 
						||
| 
								 | 
							
								from logging.config import fileConfig
							 | 
						||
| 
								 | 
							
								try:
							 | 
						||
| 
								 | 
							
								    from logging.config import dictConfig
							 | 
						||
| 
								 | 
							
								except ImportError:
							 | 
						||
| 
								 | 
							
								    # python 2.6
							 | 
						||
| 
								 | 
							
								    dictConfig = None
							 | 
						||
| 
								 | 
							
								import os
							 | 
						||
| 
								 | 
							
								import socket
							 | 
						||
| 
								 | 
							
								import sys
							 | 
						||
| 
								 | 
							
								import threading
							 | 
						||
| 
								 | 
							
								import traceback
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from gunicorn import util
							 | 
						||
| 
								 | 
							
								from gunicorn.six import PY3, string_types
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# syslog facility codes
							 | 
						||
| 
								 | 
							
								SYSLOG_FACILITIES = {
							 | 
						||
| 
								 | 
							
								        "auth":     4,
							 | 
						||
| 
								 | 
							
								        "authpriv": 10,
							 | 
						||
| 
								 | 
							
								        "cron":     9,
							 | 
						||
| 
								 | 
							
								        "daemon":   3,
							 | 
						||
| 
								 | 
							
								        "ftp":      11,
							 | 
						||
| 
								 | 
							
								        "kern":     0,
							 | 
						||
| 
								 | 
							
								        "lpr":      6,
							 | 
						||
| 
								 | 
							
								        "mail":     2,
							 | 
						||
| 
								 | 
							
								        "news":     7,
							 | 
						||
| 
								 | 
							
								        "security": 4,  #  DEPRECATED
							 | 
						||
| 
								 | 
							
								        "syslog":   5,
							 | 
						||
| 
								 | 
							
								        "user":     1,
							 | 
						||
| 
								 | 
							
								        "uucp":     8,
							 | 
						||
| 
								 | 
							
								        "local0":   16,
							 | 
						||
| 
								 | 
							
								        "local1":   17,
							 | 
						||
| 
								 | 
							
								        "local2":   18,
							 | 
						||
| 
								 | 
							
								        "local3":   19,
							 | 
						||
| 
								 | 
							
								        "local4":   20,
							 | 
						||
| 
								 | 
							
								        "local5":   21,
							 | 
						||
| 
								 | 
							
								        "local6":   22,
							 | 
						||
| 
								 | 
							
								        "local7":   23
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CONFIG_DEFAULTS = dict(
							 | 
						||
| 
								 | 
							
								        version=1,
							 | 
						||
| 
								 | 
							
								        disable_existing_loggers=False,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        loggers={
							 | 
						||
| 
								 | 
							
								            "root": {"level": "INFO", "handlers": ["console"]},
							 | 
						||
| 
								 | 
							
								            "gunicorn.error": {
							 | 
						||
| 
								 | 
							
								                "level": "INFO",
							 | 
						||
| 
								 | 
							
								                "handlers": ["error_console"],
							 | 
						||
| 
								 | 
							
								                "propagate": True,
							 | 
						||
| 
								 | 
							
								                "qualname": "gunicorn.error"
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            "gunicorn.access": {
							 | 
						||
| 
								 | 
							
								                "level": "INFO",
							 | 
						||
| 
								 | 
							
								                "handlers": ["console"],
							 | 
						||
| 
								 | 
							
								                "propagate": True,
							 | 
						||
| 
								 | 
							
								                "qualname": "gunicorn.access"
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        handlers={
							 | 
						||
| 
								 | 
							
								            "console": {
							 | 
						||
| 
								 | 
							
								                "class": "logging.StreamHandler",
							 | 
						||
| 
								 | 
							
								                "formatter": "generic",
							 | 
						||
| 
								 | 
							
								                "stream": "sys.stdout"
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            "error_console": {
							 | 
						||
| 
								 | 
							
								                "class": "logging.StreamHandler",
							 | 
						||
| 
								 | 
							
								                "formatter": "generic",
							 | 
						||
| 
								 | 
							
								                "stream": "sys.stderr"
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        formatters={
							 | 
						||
| 
								 | 
							
								            "generic": {
							 | 
						||
| 
								 | 
							
								                "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
							 | 
						||
| 
								 | 
							
								                "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
							 | 
						||
| 
								 | 
							
								                "class": "logging.Formatter"
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def loggers():
							 | 
						||
| 
								 | 
							
								    """ get list of all loggers """
							 | 
						||
| 
								 | 
							
								    root = logging.root
							 | 
						||
| 
								 | 
							
								    existing = root.manager.loggerDict.keys()
							 | 
						||
| 
								 | 
							
								    return [logging.getLogger(name) for name in existing]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SafeAtoms(dict):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, atoms):
							 | 
						||
| 
								 | 
							
								        dict.__init__(self)
							 | 
						||
| 
								 | 
							
								        for key, value in atoms.items():
							 | 
						||
| 
								 | 
							
								            if isinstance(value, string_types):
							 | 
						||
| 
								 | 
							
								                self[key] = value.replace('"', '\\"')
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                self[key] = value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __getitem__(self, k):
							 | 
						||
| 
								 | 
							
								        if k.startswith("{"):
							 | 
						||
| 
								 | 
							
								            kl = k.lower()
							 | 
						||
| 
								 | 
							
								            if kl in self:
							 | 
						||
| 
								 | 
							
								                return super(SafeAtoms, self).__getitem__(kl)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                return "-"
							 | 
						||
| 
								 | 
							
								        if k in self:
							 | 
						||
| 
								 | 
							
								            return super(SafeAtoms, self).__getitem__(k)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            return '-'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def parse_syslog_address(addr):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # unix domain socket type depends on backend
							 | 
						||
| 
								 | 
							
								    # SysLogHandler will try both when given None
							 | 
						||
| 
								 | 
							
								    if addr.startswith("unix://"):
							 | 
						||
| 
								 | 
							
								        sock_type = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # set socket type only if explicitly requested
							 | 
						||
| 
								 | 
							
								        parts = addr.split("#", 1)
							 | 
						||
| 
								 | 
							
								        if len(parts) == 2:
							 | 
						||
| 
								 | 
							
								            addr = parts[0]
							 | 
						||
| 
								 | 
							
								            if parts[1] == "dgram":
							 | 
						||
| 
								 | 
							
								                sock_type = socket.SOCK_DGRAM
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return (sock_type, addr.split("unix://")[1])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if addr.startswith("udp://"):
							 | 
						||
| 
								 | 
							
								        addr = addr.split("udp://")[1]
							 | 
						||
| 
								 | 
							
								        socktype = socket.SOCK_DGRAM
							 | 
						||
| 
								 | 
							
								    elif addr.startswith("tcp://"):
							 | 
						||
| 
								 | 
							
								        addr = addr.split("tcp://")[1]
							 | 
						||
| 
								 | 
							
								        socktype = socket.SOCK_STREAM
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        raise RuntimeError("invalid syslog address")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if '[' in addr and ']' in addr:
							 | 
						||
| 
								 | 
							
								        host = addr.split(']')[0][1:].lower()
							 | 
						||
| 
								 | 
							
								    elif ':' in addr:
							 | 
						||
| 
								 | 
							
								        host = addr.split(':')[0].lower()
							 | 
						||
| 
								 | 
							
								    elif addr == "":
							 | 
						||
| 
								 | 
							
								        host = "localhost"
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        host = addr.lower()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    addr = addr.split(']')[-1]
							 | 
						||
| 
								 | 
							
								    if ":" in addr:
							 | 
						||
| 
								 | 
							
								        port = addr.split(':', 1)[1]
							 | 
						||
| 
								 | 
							
								        if not port.isdigit():
							 | 
						||
| 
								 | 
							
								            raise RuntimeError("%r is not a valid port number." % port)
							 | 
						||
| 
								 | 
							
								        port = int(port)
							 | 
						||
| 
								 | 
							
								    else:
							 | 
						||
| 
								 | 
							
								        port = 514
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return (socktype, (host, port))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Logger(object):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    LOG_LEVELS = {
							 | 
						||
| 
								 | 
							
								        "critical": logging.CRITICAL,
							 | 
						||
| 
								 | 
							
								        "error": logging.ERROR,
							 | 
						||
| 
								 | 
							
								        "warning": logging.WARNING,
							 | 
						||
| 
								 | 
							
								        "info": logging.INFO,
							 | 
						||
| 
								 | 
							
								        "debug": logging.DEBUG
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    loglevel = logging.INFO
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    error_fmt = r"%(asctime)s [%(process)d] [%(levelname)s] %(message)s"
							 | 
						||
| 
								 | 
							
								    datefmt = r"[%Y-%m-%d %H:%M:%S %z]"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    access_fmt = "%(message)s"
							 | 
						||
| 
								 | 
							
								    syslog_fmt = "[%(process)d] %(message)s"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    atoms_wrapper_class = SafeAtoms
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, cfg):
							 | 
						||
| 
								 | 
							
								        self.error_log = logging.getLogger("gunicorn.error")
							 | 
						||
| 
								 | 
							
								        self.error_log.propagate = False
							 | 
						||
| 
								 | 
							
								        self.access_log = logging.getLogger("gunicorn.access")
							 | 
						||
| 
								 | 
							
								        self.access_log.propagate = False
							 | 
						||
| 
								 | 
							
								        self.error_handlers = []
							 | 
						||
| 
								 | 
							
								        self.access_handlers = []
							 | 
						||
| 
								 | 
							
								        self.logfile = None
							 | 
						||
| 
								 | 
							
								        self.lock = threading.Lock()
							 | 
						||
| 
								 | 
							
								        self.cfg = cfg
							 | 
						||
| 
								 | 
							
								        self.setup(cfg)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def setup(self, cfg):
							 | 
						||
| 
								 | 
							
								        self.loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO)
							 | 
						||
| 
								 | 
							
								        self.error_log.setLevel(self.loglevel)
							 | 
						||
| 
								 | 
							
								        self.access_log.setLevel(logging.INFO)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # set gunicorn.error handler
							 | 
						||
| 
								 | 
							
								        if self.cfg.capture_output and cfg.errorlog != "-":
							 | 
						||
| 
								 | 
							
								            for stream in sys.stdout, sys.stderr:
							 | 
						||
| 
								 | 
							
								                stream.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            self.logfile = open(cfg.errorlog, 'a+')
							 | 
						||
| 
								 | 
							
								            os.dup2(self.logfile.fileno(), sys.stdout.fileno())
							 | 
						||
| 
								 | 
							
								            os.dup2(self.logfile.fileno(), sys.stderr.fileno())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        self._set_handler(self.error_log, cfg.errorlog,
							 | 
						||
| 
								 | 
							
								                          logging.Formatter(self.error_fmt, self.datefmt))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # set gunicorn.access handler
							 | 
						||
| 
								 | 
							
								        if cfg.accesslog is not None:
							 | 
						||
| 
								 | 
							
								            self._set_handler(self.access_log, cfg.accesslog,
							 | 
						||
| 
								 | 
							
								                fmt=logging.Formatter(self.access_fmt), stream=sys.stdout)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # set syslog handler
							 | 
						||
| 
								 | 
							
								        if cfg.syslog:
							 | 
						||
| 
								 | 
							
								            self._set_syslog_handler(
							 | 
						||
| 
								 | 
							
								                self.error_log, cfg, self.syslog_fmt, "error"
							 | 
						||
| 
								 | 
							
								            )
							 | 
						||
| 
								 | 
							
								            if not cfg.disable_redirect_access_to_syslog:
							 | 
						||
| 
								 | 
							
								                self._set_syslog_handler(
							 | 
						||
| 
								 | 
							
								                    self.access_log, cfg, self.syslog_fmt, "access"
							 | 
						||
| 
								 | 
							
								                )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if dictConfig is None and cfg.logconfig_dict:
							 | 
						||
| 
								 | 
							
								            util.warn("Dictionary-based log configuration requires "
							 | 
						||
| 
								 | 
							
								                      "Python 2.7 or above.")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if dictConfig and cfg.logconfig_dict:
							 | 
						||
| 
								 | 
							
								            config = CONFIG_DEFAULTS.copy()
							 | 
						||
| 
								 | 
							
								            config.update(cfg.logconfig_dict)
							 | 
						||
| 
								 | 
							
								            try:
							 | 
						||
| 
								 | 
							
								                dictConfig(config)
							 | 
						||
| 
								 | 
							
								            except (
							 | 
						||
| 
								 | 
							
								                    AttributeError,
							 | 
						||
| 
								 | 
							
								                    ImportError,
							 | 
						||
| 
								 | 
							
								                    ValueError,
							 | 
						||
| 
								 | 
							
								                    TypeError
							 | 
						||
| 
								 | 
							
								            ) as exc:
							 | 
						||
| 
								 | 
							
								                raise RuntimeError(str(exc))
							 | 
						||
| 
								 | 
							
								        elif cfg.logconfig:
							 | 
						||
| 
								 | 
							
								            if os.path.exists(cfg.logconfig):
							 | 
						||
| 
								 | 
							
								                defaults = CONFIG_DEFAULTS.copy()
							 | 
						||
| 
								 | 
							
								                defaults['__file__'] = cfg.logconfig
							 | 
						||
| 
								 | 
							
								                defaults['here'] = os.path.dirname(cfg.logconfig)
							 | 
						||
| 
								 | 
							
								                fileConfig(cfg.logconfig, defaults=defaults,
							 | 
						||
| 
								 | 
							
								                           disable_existing_loggers=False)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                msg = "Error: log config '%s' not found"
							 | 
						||
| 
								 | 
							
								                raise RuntimeError(msg % cfg.logconfig)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def critical(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.critical(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def error(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.error(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def warning(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.warning(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def info(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.info(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def debug(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.debug(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def exception(self, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        self.error_log.exception(msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def log(self, lvl, msg, *args, **kwargs):
							 | 
						||
| 
								 | 
							
								        if isinstance(lvl, string_types):
							 | 
						||
| 
								 | 
							
								            lvl = self.LOG_LEVELS.get(lvl.lower(), logging.INFO)
							 | 
						||
| 
								 | 
							
								        self.error_log.log(lvl, msg, *args, **kwargs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def atoms(self, resp, req, environ, request_time):
							 | 
						||
| 
								 | 
							
								        """ Gets atoms for log formating.
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								        status = resp.status
							 | 
						||
| 
								 | 
							
								        if isinstance(status, str):
							 | 
						||
| 
								 | 
							
								            status = status.split(None, 1)[0]
							 | 
						||
| 
								 | 
							
								        atoms = {
							 | 
						||
| 
								 | 
							
								            'h': environ.get('REMOTE_ADDR', '-'),
							 | 
						||
| 
								 | 
							
								            'l': '-',
							 | 
						||
| 
								 | 
							
								            'u': self._get_user(environ) or '-',
							 | 
						||
| 
								 | 
							
								            't': self.now(),
							 | 
						||
| 
								 | 
							
								            'r': "%s %s %s" % (environ['REQUEST_METHOD'],
							 | 
						||
| 
								 | 
							
								                environ['RAW_URI'], environ["SERVER_PROTOCOL"]),
							 | 
						||
| 
								 | 
							
								            's': status,
							 | 
						||
| 
								 | 
							
								            'm': environ.get('REQUEST_METHOD'),
							 | 
						||
| 
								 | 
							
								            'U': environ.get('PATH_INFO'),
							 | 
						||
| 
								 | 
							
								            'q': environ.get('QUERY_STRING'),
							 | 
						||
| 
								 | 
							
								            'H': environ.get('SERVER_PROTOCOL'),
							 | 
						||
| 
								 | 
							
								            'b': getattr(resp, 'sent', None) and str(resp.sent) or '-',
							 | 
						||
| 
								 | 
							
								            'B': getattr(resp, 'sent', None),
							 | 
						||
| 
								 | 
							
								            'f': environ.get('HTTP_REFERER', '-'),
							 | 
						||
| 
								 | 
							
								            'a': environ.get('HTTP_USER_AGENT', '-'),
							 | 
						||
| 
								 | 
							
								            'T': request_time.seconds,
							 | 
						||
| 
								 | 
							
								            'D': (request_time.seconds*1000000) + request_time.microseconds,
							 | 
						||
| 
								 | 
							
								            'L': "%d.%06d" % (request_time.seconds, request_time.microseconds),
							 | 
						||
| 
								 | 
							
								            'p': "<%s>" % os.getpid()
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # add request headers
							 | 
						||
| 
								 | 
							
								        if hasattr(req, 'headers'):
							 | 
						||
| 
								 | 
							
								            req_headers = req.headers
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            req_headers = req
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if hasattr(req_headers, "items"):
							 | 
						||
| 
								 | 
							
								            req_headers = req_headers.items()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        atoms.update(dict([("{%s}i" % k.lower(), v) for k, v in req_headers]))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        resp_headers = resp.headers
							 | 
						||
| 
								 | 
							
								        if hasattr(resp_headers, "items"):
							 | 
						||
| 
								 | 
							
								            resp_headers = resp_headers.items()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # add response headers
							 | 
						||
| 
								 | 
							
								        atoms.update(dict([("{%s}o" % k.lower(), v) for k, v in resp_headers]))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # add environ variables
							 | 
						||
| 
								 | 
							
								        environ_variables = environ.items()
							 | 
						||
| 
								 | 
							
								        atoms.update(dict([("{%s}e" % k.lower(), v) for k, v in environ_variables]))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return atoms
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def access(self, resp, req, environ, request_time):
							 | 
						||
| 
								 | 
							
								        """ See http://httpd.apache.org/docs/2.0/logs.html#combined
							 | 
						||
| 
								 | 
							
								        for format details
							 | 
						||
| 
								 | 
							
								        """
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not (self.cfg.accesslog or self.cfg.logconfig or
							 | 
						||
| 
								 | 
							
								           self.cfg.logconfig_dict or
							 | 
						||
| 
								 | 
							
								           (self.cfg.syslog and not self.cfg.disable_access_log_redirection)):
							 | 
						||
| 
								 | 
							
								            return
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # wrap atoms:
							 | 
						||
| 
								 | 
							
								        # - make sure atoms will be test case insensitively
							 | 
						||
| 
								 | 
							
								        # - if atom doesn't exist replace it by '-'
							 | 
						||
| 
								 | 
							
								        safe_atoms = self.atoms_wrapper_class(self.atoms(resp, req, environ,
							 | 
						||
| 
								 | 
							
								            request_time))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            self.access_log.info(self.cfg.access_log_format, safe_atoms)
							 | 
						||
| 
								 | 
							
								        except:
							 | 
						||
| 
								 | 
							
								            self.error(traceback.format_exc())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def now(self):
							 | 
						||
| 
								 | 
							
								        """ return date in Apache Common Log Format """
							 | 
						||
| 
								 | 
							
								        return time.strftime('[%d/%b/%Y:%H:%M:%S %z]')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def reopen_files(self):
							 | 
						||
| 
								 | 
							
								        if self.cfg.capture_output and self.cfg.errorlog != "-":
							 | 
						||
| 
								 | 
							
								            for stream in sys.stdout, sys.stderr:
							 | 
						||
| 
								 | 
							
								                stream.flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            with self.lock:
							 | 
						||
| 
								 | 
							
								                if self.logfile is not None:
							 | 
						||
| 
								 | 
							
								                    self.logfile.close()
							 | 
						||
| 
								 | 
							
								                self.logfile = open(self.cfg.errorlog, 'a+')
							 | 
						||
| 
								 | 
							
								                os.dup2(self.logfile.fileno(), sys.stdout.fileno())
							 | 
						||
| 
								 | 
							
								                os.dup2(self.logfile.fileno(), sys.stderr.fileno())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        for log in loggers():
							 | 
						||
| 
								 | 
							
								            for handler in log.handlers:
							 | 
						||
| 
								 | 
							
								                if isinstance(handler, logging.FileHandler):
							 | 
						||
| 
								 | 
							
								                    handler.acquire()
							 | 
						||
| 
								 | 
							
								                    try:
							 | 
						||
| 
								 | 
							
								                        if handler.stream:
							 | 
						||
| 
								 | 
							
								                            handler.close()
							 | 
						||
| 
								 | 
							
								                            handler.stream = handler._open()
							 | 
						||
| 
								 | 
							
								                    finally:
							 | 
						||
| 
								 | 
							
								                        handler.release()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def close_on_exec(self):
							 | 
						||
| 
								 | 
							
								        for log in loggers():
							 | 
						||
| 
								 | 
							
								            for handler in log.handlers:
							 | 
						||
| 
								 | 
							
								                if isinstance(handler, logging.FileHandler):
							 | 
						||
| 
								 | 
							
								                    handler.acquire()
							 | 
						||
| 
								 | 
							
								                    try:
							 | 
						||
| 
								 | 
							
								                        if handler.stream:
							 | 
						||
| 
								 | 
							
								                            util.close_on_exec(handler.stream.fileno())
							 | 
						||
| 
								 | 
							
								                    finally:
							 | 
						||
| 
								 | 
							
								                        handler.release()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_gunicorn_handler(self, log):
							 | 
						||
| 
								 | 
							
								        for h in log.handlers:
							 | 
						||
| 
								 | 
							
								            if getattr(h, "_gunicorn", False):
							 | 
						||
| 
								 | 
							
								                return h
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _set_handler(self, log, output, fmt, stream=None):
							 | 
						||
| 
								 | 
							
								        # remove previous gunicorn log handler
							 | 
						||
| 
								 | 
							
								        h = self._get_gunicorn_handler(log)
							 | 
						||
| 
								 | 
							
								        if h:
							 | 
						||
| 
								 | 
							
								            log.handlers.remove(h)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if output is not None:
							 | 
						||
| 
								 | 
							
								            if output == "-":
							 | 
						||
| 
								 | 
							
								                h = logging.StreamHandler(stream)
							 | 
						||
| 
								 | 
							
								            else:
							 | 
						||
| 
								 | 
							
								                util.check_is_writeable(output)
							 | 
						||
| 
								 | 
							
								                h = logging.FileHandler(output)
							 | 
						||
| 
								 | 
							
								                # make sure the user can reopen the file
							 | 
						||
| 
								 | 
							
								                try:
							 | 
						||
| 
								 | 
							
								                    os.chown(h.baseFilename, self.cfg.user, self.cfg.group)
							 | 
						||
| 
								 | 
							
								                except OSError:
							 | 
						||
| 
								 | 
							
								                    # it's probably OK there, we assume the user has given
							 | 
						||
| 
								 | 
							
								                    # /dev/null as a parameter.
							 | 
						||
| 
								 | 
							
								                    pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            h.setFormatter(fmt)
							 | 
						||
| 
								 | 
							
								            h._gunicorn = True
							 | 
						||
| 
								 | 
							
								            log.addHandler(h)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _set_syslog_handler(self, log, cfg, fmt, name):
							 | 
						||
| 
								 | 
							
								        # setup format
							 | 
						||
| 
								 | 
							
								        if not cfg.syslog_prefix:
							 | 
						||
| 
								 | 
							
								            prefix = cfg.proc_name.replace(":", ".")
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            prefix = cfg.syslog_prefix
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        prefix = "gunicorn.%s.%s" % (prefix, name)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # set format
							 | 
						||
| 
								 | 
							
								        fmt = logging.Formatter(r"%s: %s" % (prefix, fmt))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # syslog facility
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            facility = SYSLOG_FACILITIES[cfg.syslog_facility.lower()]
							 | 
						||
| 
								 | 
							
								        except KeyError:
							 | 
						||
| 
								 | 
							
								            raise RuntimeError("unknown facility name")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # parse syslog address
							 | 
						||
| 
								 | 
							
								        socktype, addr = parse_syslog_address(cfg.syslog_addr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        # finally setup the syslog handler
							 | 
						||
| 
								 | 
							
								        if sys.version_info >= (2, 7):
							 | 
						||
| 
								 | 
							
								            h = logging.handlers.SysLogHandler(address=addr,
							 | 
						||
| 
								 | 
							
								                    facility=facility, socktype=socktype)
							 | 
						||
| 
								 | 
							
								        else:
							 | 
						||
| 
								 | 
							
								            # socktype is only supported in 2.7 and sup
							 | 
						||
| 
								 | 
							
								            # fix issue #541
							 | 
						||
| 
								 | 
							
								            h = logging.handlers.SysLogHandler(address=addr,
							 | 
						||
| 
								 | 
							
								                    facility=facility)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        h.setFormatter(fmt)
							 | 
						||
| 
								 | 
							
								        h._gunicorn = True
							 | 
						||
| 
								 | 
							
								        log.addHandler(h)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _get_user(self, environ):
							 | 
						||
| 
								 | 
							
								        user = None
							 | 
						||
| 
								 | 
							
								        http_auth = environ.get("HTTP_AUTHORIZATION")
							 | 
						||
| 
								 | 
							
								        if http_auth and http_auth.startswith('Basic'):
							 | 
						||
| 
								 | 
							
								            auth = http_auth.split(" ", 1)
							 | 
						||
| 
								 | 
							
								            if len(auth) == 2:
							 | 
						||
| 
								 | 
							
								                try:
							 | 
						||
| 
								 | 
							
								                    # b64decode doesn't accept unicode in Python < 3.3
							 | 
						||
| 
								 | 
							
								                    # so we need to convert it to a byte string
							 | 
						||
| 
								 | 
							
								                    auth = base64.b64decode(auth[1].strip().encode('utf-8'))
							 | 
						||
| 
								 | 
							
								                    if PY3:  # b64decode returns a byte string in Python 3
							 | 
						||
| 
								 | 
							
								                        auth = auth.decode('utf-8')
							 | 
						||
| 
								 | 
							
								                    auth = auth.split(":", 1)
							 | 
						||
| 
								 | 
							
								                except (TypeError, binascii.Error, UnicodeDecodeError) as exc:
							 | 
						||
| 
								 | 
							
								                    self.debug("Couldn't get username: %s", exc)
							 | 
						||
| 
								 | 
							
								                    return user
							 | 
						||
| 
								 | 
							
								                if len(auth) == 2:
							 | 
						||
| 
								 | 
							
								                    user = auth[0]
							 | 
						||
| 
								 | 
							
								        return user
							 |