root/livinglogic.python.aplora/aplora.py @ 16:e4865b39c0d0

Revision 16:e4865b39c0d0, 4.2 KB (checked in by Walter Doerwald <walter@…>, 11 years ago)

Stop using cx_Oracle.Timestamp. Use ReST for documentation.

Line 
1#!/usr/local/bin/python
2# -*- coding: utf-8 -*-
3
4## Copyright 2004-2008 by LivingLogic AG, Bayreuth/Germany.
5## Copyright 2004-2008 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## Permission to use, copy, modify, and distribute this software and its documentation
10## for any purpose and without fee is hereby granted, provided that the above copyright
11## notice appears in all copies and that both that copyright notice and this permission
12## notice appear in supporting documentation, and that the name of LivingLogic AG or
13## the author not be used in advertising or publicity pertaining to distribution of the
14## software without specific, written prior permission.
15##
16## LIVINGLOGIC AG AND THE AUTHOR DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17## INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18## LIVINGLOGIC AG OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
19## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20## IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21## IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23"""
24This script can be used with Apache's piped logging to log HTTP request
25to an Oracle database.
26"""
27
28__docformat__ = "plaintext"
29
30
31import os, datetime, cgi, Cookie, urlparse
32
33
34class Logger(object):
35    def __init__(self, oracle, connect, procname):
36        os.environ["ORACLE_HOME"] = oracle
37        import cx_Oracle
38        self.cx_Oracle = cx_Oracle
39        db = cx_Oracle.connect(connect)
40        self.c = db.cursor()
41        self.connect = connect
42        self.procname = procname
43
44    def findcoid(self, path, query):
45        # Find Content-Object-ID in URL
46        coid = None
47        pos1 = path.find("_id_")
48        if pos1 >= 0:
49            pos2 = path.find("_", pos1+4)
50            if pos2 >= 0:
51                coid = path[pos1+4:pos2]
52   
53        # Retry with a query parameter
54        if coid is None and query:
55            query = query[1:] # drop the ?
56            query = cgi.parse_qs(query)
57            if "id" in query:
58                coid = query["id"][0]
59        return coid
60   
61    def findsession(self, sessionin, sessionout, path):
62        if sessionout and sessionout != "-":
63            cookie = Cookie.SimpleCookie()
64            cookie.load(sessionout)
65            if "JSESSIONID" in cookie:
66                return cookie["JSESSIONID"].value
67        (scheme, server, path, params, query, frag) = urlparse.urlparse(path)
68        if params.startswith("jsessionid="):
69            return params[11:]
70        if sessionin and sessionin != "-":
71            return sessionin
72        return None
73
74    def run(self, stream):
75        while True:
76            line = stream.readline()
77            fields = [field.decode("string-escape").encode("latin-1") for field in line.rstrip("\n").split("\t")]
78
79            field = iter(fields)
80            instance = field.next()
81            try:
82                reqstart = int(field.next())
83            except ValueError:
84                reqstart = None
85            else:
86                reqstart = datetime.datetime.fromtimestamp(reqstart)
87            reqtime = 1e-6*float(field.next())
88            client = field.next()
89            useragent = field.next()
90            path = field.next()
91            query = field.next()
92            method = field.next()
93            status = int(field.next())
94            bytesin = int(field.next())
95            bytesout = int(field.next())
96            bytesbodyout = int(field.next())
97            referer = field.next()
98            contenttype = field.next()
99            sessionin = field.next()
100            sessionout = field.next()
101
102            (mimetype, options) = cgi.parse_header(contenttype)
103            charset = options.get("charset", None)
104
105            data = [
106                reqstart,
107                reqtime,
108                instance,
109                client,
110                useragent,
111                path+query,
112                method,
113                status,
114                bytesin,
115                bytesout,
116                bytesbodyout,
117                None, #req.content_encoding,
118                mimetype,
119                charset,
120                referer,
121                self.findsession(sessionin, sessionout, path),
122                self.findcoid(path, query),
123            ]
124            self.c.callproc(self.procname, data)
125
126
127if __name__ == "__main__":
128    import sys, optparse
129    p = optparse.OptionParser(usage="usage: %prog [options]", version="%%prog %s" % __version__)
130    p.add_option("-o", "--oracle", dest="oracle", help="Value for ORACLE_HOME", default="/oracle/Client")
131    p.add_option("-c", "--connect", dest="connect", help="Oracle connect string", default=None)
132    p.add_option("-p", "--procname", dest="procname", help="Name of insert procedure", default="log_insert")
133    (options, args) = p.parse_args()
134    logger = Logger(oracle=options.oracle, connect=options.connect, procname=options.procname)
135    logger.run(sys.stdin)
Note: See TracBrowser for help on using the browser.