summaryrefslogtreecommitdiff
path: root/vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py')
-rw-r--r--vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py398
1 files changed, 0 insertions, 398 deletions
diff --git a/vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py b/vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py
deleted file mode 100644
index aad9e8a..0000000
--- a/vendor/CherryPy-3.2.0/py3/cherrypy/_cplogging.py
+++ /dev/null
@@ -1,398 +0,0 @@
-"""
-Simple config
-=============
-
-Although CherryPy uses the :mod:`Python logging module <logging>`, it does so
-behind the scenes so that simple logging is simple, but complicated logging
-is still possible. "Simple" logging means that you can log to the screen
-(i.e. console/stdout) or to a file, and that you can easily have separate
-error and access log files.
-
-Here are the simplified logging settings. You use these by adding lines to
-your config file or dict. You should set these at either the global level or
-per application (see next), but generally not both.
-
- * ``log.screen``: Set this to True to have both "error" and "access" messages
- printed to stdout.
- * ``log.access_file``: Set this to an absolute filename where you want
- "access" messages written.
- * ``log.error_file``: Set this to an absolute filename where you want "error"
- messages written.
-
-Many events are automatically logged; to log your own application events, call
-:func:`cherrypy.log`.
-
-Architecture
-============
-
-Separate scopes
----------------
-
-CherryPy provides log managers at both the global and application layers.
-This means you can have one set of logging rules for your entire site,
-and another set of rules specific to each application. The global log
-manager is found at :func:`cherrypy.log`, and the log manager for each
-application is found at :attr:`app.log<cherrypy._cptree.Application.log>`.
-If you're inside a request, the latter is reachable from
-``cherrypy.request.app.log``; if you're outside a request, you'll have to obtain
-a reference to the ``app``: either the return value of
-:func:`tree.mount()<cherrypy._cptree.Tree.mount>` or, if you used
-:func:`quickstart()<cherrypy.quickstart>` instead, via ``cherrypy.tree.apps['/']``.
-
-By default, the global logs are named "cherrypy.error" and "cherrypy.access",
-and the application logs are named "cherrypy.error.2378745" and
-"cherrypy.access.2378745" (the number is the id of the Application object).
-This means that the application logs "bubble up" to the site logs, so if your
-application has no log handlers, the site-level handlers will still log the
-messages.
-
-Errors vs. Access
------------------
-
-Each log manager handles both "access" messages (one per HTTP request) and
-"error" messages (everything else). Note that the "error" log is not just for
-errors! The format of access messages is highly formalized, but the error log
-isn't--it receives messages from a variety of sources (including full error
-tracebacks, if enabled).
-
-
-Custom Handlers
-===============
-
-The simple settings above work by manipulating Python's standard :mod:`logging`
-module. So when you need something more complex, the full power of the standard
-module is yours to exploit. You can borrow or create custom handlers, formats,
-filters, and much more. Here's an example that skips the standard FileHandler
-and uses a RotatingFileHandler instead:
-
-::
-
- #python
- log = app.log
-
- # Remove the default FileHandlers if present.
- log.error_file = ""
- log.access_file = ""
-
- maxBytes = getattr(log, "rot_maxBytes", 10000000)
- backupCount = getattr(log, "rot_backupCount", 1000)
-
- # Make a new RotatingFileHandler for the error log.
- fname = getattr(log, "rot_error_file", "error.log")
- h = handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
- h.setLevel(DEBUG)
- h.setFormatter(_cplogging.logfmt)
- log.error_log.addHandler(h)
-
- # Make a new RotatingFileHandler for the access log.
- fname = getattr(log, "rot_access_file", "access.log")
- h = handlers.RotatingFileHandler(fname, 'a', maxBytes, backupCount)
- h.setLevel(DEBUG)
- h.setFormatter(_cplogging.logfmt)
- log.access_log.addHandler(h)
-
-
-The ``rot_*`` attributes are pulled straight from the application log object.
-Since "log.*" config entries simply set attributes on the log object, you can
-add custom attributes to your heart's content. Note that these handlers are
-used ''instead'' of the default, simple handlers outlined above (so don't set
-the "log.error_file" config entry, for example).
-"""
-
-import datetime
-import logging
-# Silence the no-handlers "warning" (stderr write!) in stdlib logging
-logging.Logger.manager.emittedNoHandlerWarning = 1
-logfmt = logging.Formatter("%(message)s")
-import os
-import sys
-
-import cherrypy
-from cherrypy import _cperror
-
-
-class LogManager(object):
- """An object to assist both simple and advanced logging.
-
- ``cherrypy.log`` is an instance of this class.
- """
-
- appid = None
- """The id() of the Application object which owns this log manager. If this
- is a global log manager, appid is None."""
-
- error_log = None
- """The actual :class:`logging.Logger` instance for error messages."""
-
- access_log = None
- """The actual :class:`logging.Logger` instance for access messages."""
-
- access_log_format = \
- '{h} {l} {u} {t} "{r}" {s} {b} "{f}" "{a}"'
-
- logger_root = None
- """The "top-level" logger name.
-
- This string will be used as the first segment in the Logger names.
- The default is "cherrypy", for example, in which case the Logger names
- will be of the form::
-
- cherrypy.error.<appid>
- cherrypy.access.<appid>
- """
-
- def __init__(self, appid=None, logger_root="cherrypy"):
- self.logger_root = logger_root
- self.appid = appid
- if appid is None:
- self.error_log = logging.getLogger("%s.error" % logger_root)
- self.access_log = logging.getLogger("%s.access" % logger_root)
- else:
- self.error_log = logging.getLogger("%s.error.%s" % (logger_root, appid))
- self.access_log = logging.getLogger("%s.access.%s" % (logger_root, appid))
- self.error_log.setLevel(logging.INFO)
- self.access_log.setLevel(logging.INFO)
- cherrypy.engine.subscribe('graceful', self.reopen_files)
-
- def reopen_files(self):
- """Close and reopen all file handlers."""
- for log in (self.error_log, self.access_log):
- for h in log.handlers:
- if isinstance(h, logging.FileHandler):
- h.acquire()
- h.stream.close()
- h.stream = open(h.baseFilename, h.mode)
- h.release()
-
- def error(self, msg='', context='', severity=logging.INFO, traceback=False):
- """Write the given ``msg`` to the error log.
-
- This is not just for errors! Applications may call this at any time
- to log application-specific information.
-
- If ``traceback`` is True, the traceback of the current exception
- (if any) will be appended to ``msg``.
- """
- if traceback:
- msg += _cperror.format_exc()
- self.error_log.log(severity, ' '.join((self.time(), context, msg)))
-
- def __call__(self, *args, **kwargs):
- """An alias for ``error``."""
- return self.error(*args, **kwargs)
-
- def access(self):
- """Write to the access log (in Apache/NCSA Combined Log format).
-
- See http://httpd.apache.org/docs/2.0/logs.html#combined for format
- details.
-
- CherryPy calls this automatically for you. Note there are no arguments;
- it collects the data itself from
- :class:`cherrypy.request<cherrypy._cprequest.Request>`.
-
- Like Apache started doing in 2.0.46, non-printable and other special
- characters in %r (and we expand that to all parts) are escaped using
- \\xhh sequences, where hh stands for the hexadecimal representation
- of the raw byte. Exceptions from this rule are " and \\, which are
- escaped by prepending a backslash, and all whitespace characters,
- which are written in their C-style notation (\\n, \\t, etc).
- """
- request = cherrypy.serving.request
- remote = request.remote
- response = cherrypy.serving.response
- outheaders = response.headers
- inheaders = request.headers
- if response.output_status is None:
- status = "-"
- else:
- status = str(response.output_status.split(b" ", 1)[0], 'ISO-8859-1')
-
- atoms = {'h': remote.name or remote.ip,
- 'l': '-',
- 'u': getattr(request, "login", None) or "-",
- 't': self.time(),
- 'r': request.request_line,
- 's': status,
- 'b': dict.get(outheaders, 'Content-Length', '') or "-",
- 'f': dict.get(inheaders, 'Referer', ''),
- 'a': dict.get(inheaders, 'User-Agent', ''),
- }
- for k, v in atoms.items():
- if not isinstance(v, str):
- v = str(v)
- v = v.replace('"', '\\"').encode('utf8')
- # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
- # and backslash for us. All we have to do is strip the quotes.
- v = repr(v)[2:-1]
-
- # in python 3.0 the repr of bytes (as returned by encode)
- # uses double \'s. But then the logger escapes them yet, again
- # resulting in quadruple slashes. Remove the extra one here.
- v = v.replace('\\\\', '\\')
-
- # Escape double-quote.
- atoms[k] = v
-
- try:
- self.access_log.log(logging.INFO, self.access_log_format.format(**atoms))
- except:
- self(traceback=True)
-
- def time(self):
- """Return now() in Apache Common Log Format (no timezone)."""
- now = datetime.datetime.now()
- monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
- 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
- month = monthnames[now.month - 1].capitalize()
- return ('[%02d/%s/%04d:%02d:%02d:%02d]' %
- (now.day, month, now.year, now.hour, now.minute, now.second))
-
- def _get_builtin_handler(self, log, key):
- for h in log.handlers:
- if getattr(h, "_cpbuiltin", None) == key:
- return h
-
-
- # ------------------------- Screen handlers ------------------------- #
-
- def _set_screen_handler(self, log, enable, stream=None):
- h = self._get_builtin_handler(log, "screen")
- if enable:
- if not h:
- if stream is None:
- stream=sys.stderr
- h = logging.StreamHandler(stream)
- h.setFormatter(logfmt)
- h._cpbuiltin = "screen"
- log.addHandler(h)
- elif h:
- log.handlers.remove(h)
-
- def _get_screen(self):
- h = self._get_builtin_handler
- has_h = h(self.error_log, "screen") or h(self.access_log, "screen")
- return bool(has_h)
-
- def _set_screen(self, newvalue):
- self._set_screen_handler(self.error_log, newvalue, stream=sys.stderr)
- self._set_screen_handler(self.access_log, newvalue, stream=sys.stdout)
- screen = property(_get_screen, _set_screen,
- doc="""Turn stderr/stdout logging on or off.
-
- If you set this to True, it'll add the appropriate StreamHandler for
- you. If you set it to False, it will remove the handler.
- """)
-
- # -------------------------- File handlers -------------------------- #
-
- def _add_builtin_file_handler(self, log, fname):
- h = logging.FileHandler(fname)
- h.setFormatter(logfmt)
- h._cpbuiltin = "file"
- log.addHandler(h)
-
- def _set_file_handler(self, log, filename):
- h = self._get_builtin_handler(log, "file")
- if filename:
- if h:
- if h.baseFilename != os.path.abspath(filename):
- h.close()
- log.handlers.remove(h)
- self._add_builtin_file_handler(log, filename)
- else:
- self._add_builtin_file_handler(log, filename)
- else:
- if h:
- h.close()
- log.handlers.remove(h)
-
- def _get_error_file(self):
- h = self._get_builtin_handler(self.error_log, "file")
- if h:
- return h.baseFilename
- return ''
- def _set_error_file(self, newvalue):
- self._set_file_handler(self.error_log, newvalue)
- error_file = property(_get_error_file, _set_error_file,
- doc="""The filename for self.error_log.
-
- If you set this to a string, it'll add the appropriate FileHandler for
- you. If you set it to ``None`` or ``''``, it will remove the handler.
- """)
-
- def _get_access_file(self):
- h = self._get_builtin_handler(self.access_log, "file")
- if h:
- return h.baseFilename
- return ''
- def _set_access_file(self, newvalue):
- self._set_file_handler(self.access_log, newvalue)
- access_file = property(_get_access_file, _set_access_file,
- doc="""The filename for self.access_log.
-
- If you set this to a string, it'll add the appropriate FileHandler for
- you. If you set it to ``None`` or ``''``, it will remove the handler.
- """)
-
- # ------------------------- WSGI handlers ------------------------- #
-
- def _set_wsgi_handler(self, log, enable):
- h = self._get_builtin_handler(log, "wsgi")
- if enable:
- if not h:
- h = WSGIErrorHandler()
- h.setFormatter(logfmt)
- h._cpbuiltin = "wsgi"
- log.addHandler(h)
- elif h:
- log.handlers.remove(h)
-
- def _get_wsgi(self):
- return bool(self._get_builtin_handler(self.error_log, "wsgi"))
-
- def _set_wsgi(self, newvalue):
- self._set_wsgi_handler(self.error_log, newvalue)
- wsgi = property(_get_wsgi, _set_wsgi,
- doc="""Write errors to wsgi.errors.
-
- If you set this to True, it'll add the appropriate
- :class:`WSGIErrorHandler<cherrypy._cplogging.WSGIErrorHandler>` for you
- (which writes errors to ``wsgi.errors``).
- If you set it to False, it will remove the handler.
- """)
-
-
-class WSGIErrorHandler(logging.Handler):
- "A handler class which writes logging records to environ['wsgi.errors']."
-
- def flush(self):
- """Flushes the stream."""
- try:
- stream = cherrypy.serving.request.wsgi_environ.get('wsgi.errors')
- except (AttributeError, KeyError):
- pass
- else:
- stream.flush()
-
- def emit(self, record):
- """Emit a record."""
- try:
- stream = cherrypy.serving.request.wsgi_environ.get('wsgi.errors')
- except (AttributeError, KeyError):
- pass
- else:
- try:
- msg = self.format(record)
- fs = "%s\n"
- import types
- if not hasattr(types, "UnicodeType"): #if no unicode support...
- stream.write(fs % msg)
- else:
- try:
- stream.write(fs % msg)
- except UnicodeError:
- stream.write(fs % msg.encode("UTF-8"))
- self.flush()
- except:
- self.handleError(record)