One problem with paste.translogger is it logs all the error documents,
which is nifty for ten minutes but then becomes clutter unless you're
debugging the error documents themselves.  This is a basic problem for
new Pylons users who need a transaction log that shows only
user-originated requests, and they don't want to spend hours
reimplementing it.

I tried to subclass TransLogger to ignore error URLs, but it's not
very subclassable.  i got this:

====
class TransLogger(_TransLogger):
    format = ('%(REMOTE_ADDR)s - %(REMOTE_USER)s [%(time)s] '
              '"%(REQUEST_METHOD)s %(REQUEST_URI)s %(HTTP_VERSION)s" '
              '%(status)s %(bytes)s "%(HTTP_REFERER)s"')

    def __init__(self, application, ignore_prefixes=None, **kw):
        self.ignore_prefixes = ignore_prefixes or []
        _TransLogger.__init__(self, application, **kw)

    def write_log(self, environ, req_uri, start, status, bytes):
        if self.ignore(req_uri):
            return
        _TransLogger.write_log(self, environ, req_uri, start, status, bytes)

    def ignore(self, req_uri):
        for prefix in self.ignore_prefixes:
            if req_uri.startswith(prefix):
                return True
        return False
====

The constructor takes a list of URL prefixes which should be ignored.
The middleware line is:

    app = TransLogger(app, ["/error"])

A more general one might take a regex, a list of regexes, or a boolean function.

So, I think Pylons needs to ship with a built-in or easily-configured
way to activate a transaction log without the error documents (or with
only external requests).  I'm not sure if this is doable with a
logging filter, but a logging filter would not have access to the WSGI
environment or request.  So i think either paste.Translogger should
take a list of prefixes or a boolean function to determine which
requests to log, or Pylons should ship with its own TransLogger, or
the Book should show how to write a complete TransLogger middleware.
The boolean function would clearly be the most flexible:
    def my_filter(wsgi_environ): => True to log this request.

It would be more Pylonsic to examine the routing variables or request
rather than parsing the raw URL, but if those are in the environment
it could do that.

I'm not sure whether to file a Pylons bug or a Paste bug so I thought
I'd bring it up here first.

Also, I find the Apache log format unreasonable to parse, so my
application actually logs to CSV files using this subclass.  This
might be an advanced middleware-writing example for the Pylons Book.

====
class CSVTransLogger(TransLogger):
    """Log to a file in the CSV format used by CAMEO Chemicals' access log."""

    def __init__(self, application, filename, ignore_prefixes=None, **kw):
        self.filename = filename
        if filename:
            f = open(filename, "ab")  # Make sure we have write permission.
            f.close()
        #    self.writer = csv.writer(f)
        #else:
        #    self.writer = None
        TransLogger.__init__(self, application, ignore_prefixes, **kw)

    def write_log(self, environ, req_uri, start, status, bytes):
        #if not self.writer:
        #    return
        if not self.filename:
            return
        if self.ignore(req_uri):
            return
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S", start)
        remote_addr = environ.get("HTTP_X_FORWARDED_FOR", "")
        if not remote_addr:
            remote_addr = environ.get("REMOTE_ADDR", "")
        status_num = status.split(None, 1)[0]
        referer = environ.get("HTTP_REFERER", "")
        seconds = "%2f" % (time.time() - time.mktime(start))
        user = ""
        try:
            session_id = str(environ["beaker.session"].id)
        except (KeyError, AttributeError, TypeError, ValueError):
            session_id = ""
        row = (
            timestamp,
            remote_addr,
            status_num,
            req_uri,
            referer,
            seconds,
            user,
            session_id,
            )
        # @@MO: Opening the logfile each transaction due to mysterious bug
        # on server: the entries weren't being written.
        f = open(self.filename, "ab")
        writer = csv.writer(f)
        writer.writerow(row)
        f.close()
====



-- 
Mike Orr <[EMAIL PROTECTED]>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-devel" group.
To post to this group, send email to pylons-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-devel?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to