~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/python/logging/logging-0.4.9.2/test/logrecv.py

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
#
 
3
# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
 
4
#
 
5
# Permission to use, copy, modify, and distribute this software and its
 
6
# documentation for any purpose and without fee is hereby granted,
 
7
# provided that the above copyright notice appear in all copies and that
 
8
# both that copyright notice and this permission notice appear in
 
9
# supporting documentation, and that the name of Vinay Sajip
 
10
# not be used in advertising or publicity pertaining to distribution
 
11
# of the software without specific, written prior permission.
 
12
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
13
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 
14
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
15
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 
16
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 
17
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
18
#
 
19
 
 
20
"""
 
21
Simple socket-based logging event receiver for use with "logging.py" logging
 
22
module.
 
23
 
 
24
Should work under Python versions >= 1.5.2, except that source line information
 
25
is not available unless 'inspect' is.
 
26
 
 
27
Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
 
28
"""
 
29
 
 
30
from select import select
 
31
import sys, string, struct, types, cPickle, socket
 
32
import logging, logging.handlers, logging.config
 
33
 
 
34
TIMEOUT         = 10
 
35
if sys.platform == "win32":
 
36
    RESET_ERROR = 10054
 
37
else:
 
38
    RESET_ERROR = 0 #FIXME get correct value for Unix...
 
39
 
 
40
logging.raiseExceptions = 1
 
41
 
 
42
#
 
43
# TCP receiver
 
44
#
 
45
 
 
46
from SocketServer import ThreadingTCPServer, StreamRequestHandler
 
47
 
 
48
class LogRecordStreamHandler(StreamRequestHandler):
 
49
    """
 
50
    Handler for a streaming logging request. It basically logs the record
 
51
    using whatever logging policy is configured locally.
 
52
    """
 
53
 
 
54
    def handle(self):
 
55
        """
 
56
        Handle multiple requests - each expected to be a 4-byte length,
 
57
        followed by the LogRecord in pickle format. Logs the record
 
58
        according to whatever policy is configured locally.
 
59
        """
 
60
        while 1:
 
61
            try:
 
62
                chunk = self.connection.recv(4)
 
63
                if len(chunk) < 4:
 
64
                    break
 
65
                slen = struct.unpack(">L", chunk)[0]
 
66
                chunk = self.connection.recv(slen)
 
67
                while len(chunk) < slen:
 
68
                    chunk = chunk + self.connection.recv(slen - len(chunk))
 
69
                obj = self.unPickle(chunk)
 
70
                record = logging.makeLogRecord(obj)
 
71
                self.handleLogRecord(record)
 
72
            except socket.error, e:
 
73
                if type(e.args) != types.TupleType:
 
74
                    raise
 
75
                else:
 
76
                    errcode = e.args[0]
 
77
                    if errcode != RESET_ERROR:
 
78
                        raise
 
79
                    break
 
80
 
 
81
    def unPickle(self, data):
 
82
        return cPickle.loads(data)
 
83
 
 
84
    def handleLogRecord(self, record):
 
85
        #if a name is specified, we use the named logger rather than the one
 
86
        #implied by the record. This is so test harnesses don't get into
 
87
        #endless loops (particularly log_test.py, which has this code and the
 
88
        #client code in the same Python instance)
 
89
        if self.server.logname is not None:
 
90
            name = self.server.logname
 
91
        else:
 
92
            name = record.name
 
93
        logger = logging.getLogger(name)
 
94
        logger.handle(record)
 
95
 
 
96
class LogRecordSocketReceiver(ThreadingTCPServer):
 
97
    """
 
98
    A simple-minded TCP socket-based logging receiver suitable for test
 
99
    purposes.
 
100
    """
 
101
 
 
102
    allow_reuse_address = 1
 
103
 
 
104
    def __init__(self, host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
 
105
            handler=LogRecordStreamHandler):
 
106
        ThreadingTCPServer.__init__(self, (host, port), handler)
 
107
        self.abort = 0
 
108
        self.timeout = 1
 
109
        self.logname = None
 
110
 
 
111
    def serve_until_stopped(self):
 
112
        import select
 
113
        abort = 0
 
114
        while not abort:
 
115
            rd, wr, ex = select.select([self.socket.fileno()],
 
116
                                       [], [],
 
117
                                       self.timeout)
 
118
            if rd:
 
119
                self.handle_request()
 
120
            abort = self.abort
 
121
 
 
122
#
 
123
# UDP receiver
 
124
#
 
125
 
 
126
from SocketServer import ThreadingUDPServer, DatagramRequestHandler
 
127
 
 
128
class LogRecordDatagramHandler(DatagramRequestHandler):
 
129
    """
 
130
    Handler for a datagram logging request. It basically logs the record using
 
131
    whatever logging policy is configured locally.
 
132
    """
 
133
    def handle(self):
 
134
        chunk = self.packet
 
135
        slen = struct.unpack(">L", chunk[:4])[0]
 
136
        chunk = chunk[4:]
 
137
        assert len(chunk) == slen
 
138
        obj = self.unPickle(chunk)
 
139
        record = logging.LogRecord(None, None, "", 0, "", (), None)
 
140
        record.__dict__.update(obj)
 
141
        self.handleLogRecord(record)
 
142
 
 
143
    def unPickle(self, data):
 
144
        return cPickle.loads(data)
 
145
 
 
146
    def handleLogRecord(self, record):
 
147
        #if a name is specified, we use the named logger rather than the one
 
148
        #implied by the record. This is so test harnesses don't get into
 
149
        #endless loops (particularly log_test.py, which has this code and the
 
150
        #client code in the same Python instance)
 
151
        if self.server.logname is not None:
 
152
            name = self.server.logname
 
153
        else:
 
154
            name = record.name
 
155
        logger = logging.getLogger(name)
 
156
        logger.handle(record)
 
157
 
 
158
    def finish(self):
 
159
        pass
 
160
 
 
161
class LogRecordDatagramReceiver(ThreadingUDPServer):
 
162
    """
 
163
    A simple-minded UDP datagram-based logging receiver suitable for test
 
164
    purposes.
 
165
    """
 
166
 
 
167
    allow_reuse_address = 1
 
168
 
 
169
    def __init__(self, host='localhost', port=logging.handlers.DEFAULT_UDP_LOGGING_PORT,
 
170
            handler=LogRecordDatagramHandler):
 
171
        ThreadingUDPServer.__init__(self, (host, port), handler)
 
172
        self.abort = 0
 
173
        self.timeout = 1
 
174
        self.logname = None
 
175
 
 
176
    def serve_until_stopped(self):
 
177
        import select
 
178
        abort = 0
 
179
        while not abort:
 
180
            rd, wr, ex = select.select([self.socket.fileno()],
 
181
                                       [], [],
 
182
                                       self.timeout)
 
183
            if rd:
 
184
                self.handle_request()
 
185
            abort = self.abort
 
186
 
 
187
#
 
188
# HTTP receiver
 
189
#
 
190
 
 
191
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
 
192
 
 
193
import cgi
 
194
 
 
195
class LogRecordHTTPHandler(BaseHTTPRequestHandler):
 
196
    def makeDict(self, fs):
 
197
        dict = {}
 
198
        for mfs in fs.list:
 
199
            dict[mfs.name] = mfs.value
 
200
        for key in ["args", "exc_info", "exc_text", "lineno", "msecs", "created",
 
201
                    "thread", "levelno", "relativeCreated"]:
 
202
            if dict.has_key(key):
 
203
                dict[key] = eval(dict[key])
 
204
        return dict
 
205
 
 
206
    def do_GET(self):
 
207
        """Serve a GET request."""
 
208
        sts = "OK"
 
209
        env = { 'REQUEST_METHOD' : 'GET'}
 
210
        try:
 
211
            i = string.find(self.path, '?')
 
212
            if i >= 0:
 
213
                env['QUERY_STRING'] = self.path[i + 1:]
 
214
            fs = cgi.FieldStorage(environ=env)
 
215
            dict = self.makeDict(fs)
 
216
            record = logging.LogRecord(None, None, "", 0, "", (), None)
 
217
            record.__dict__.update(dict)
 
218
            self.handleLogRecord(record)
 
219
        except Exception, e:
 
220
            sts = "ERROR"
 
221
            raise
 
222
        self.send_head()
 
223
        self.wfile.write("GET %s" % sts)
 
224
 
 
225
    def handleLogRecord(self, record):
 
226
        #if a name is specified, we use the named logger rather than the one
 
227
        #implied by the record. This is so test harnesses don't get into
 
228
        #endless loops (particularly log_test.py, which has this code and the
 
229
        #client code in the same Python instance)
 
230
        if self.server.logname is not None:
 
231
            name = self.server.logname
 
232
        else:
 
233
            name = record.name
 
234
        logger = logging.getLogger(name)
 
235
        logger.handle(record)
 
236
 
 
237
    def do_HEAD(self):
 
238
        """Serve a HEAD request."""
 
239
        self.send_head()
 
240
 
 
241
    def do_POST(self):
 
242
        """Serve a POST request."""
 
243
        sts = "OK"
 
244
        env = { 'REQUEST_METHOD' : 'POST'}
 
245
        try:
 
246
            length = self.headers.getheader('content-length')
 
247
            if length:
 
248
                env['CONTENT_LENGTH'] = length
 
249
            #print self.headers
 
250
            i = string.find(self.path, '?')
 
251
            if i >= 0:
 
252
                env['QUERY_STRING'] = self.path[i + 1:]
 
253
            fs = cgi.FieldStorage(fp=self.rfile, environ=env)
 
254
            dict = self.makeDict(fs)
 
255
            record = logging.LogRecord(None, None, "", 0, "", (), None)
 
256
            record.__dict__.update(dict)
 
257
            self.handleLogRecord(record)
 
258
        except Exception, e:
 
259
            print e
 
260
            sys.stdout.flush()
 
261
            sts = "ERROR"
 
262
            raise
 
263
        self.send_head()
 
264
        self.wfile.write("POST %s" % sts)
 
265
 
 
266
    def send_head(self):
 
267
        """Common code for GET and HEAD commands.
 
268
 
 
269
        This sends the response code and MIME headers.
 
270
 
 
271
        Return value is either a file object (which has to be copied
 
272
        to the outputfile by the caller unless the command was HEAD,
 
273
        and must be closed by the caller under all circumstances), or
 
274
        None, in which case the caller has nothing further to do.
 
275
 
 
276
        """
 
277
        self.send_response(200)
 
278
        self.send_header("Content-type", "text/plain")
 
279
        self.end_headers()
 
280
 
 
281
    def log_message(self, *args):
 
282
        #comment out the following line if you don't want to show requests
 
283
        #apply(BaseHTTPRequestHandler.log_message, (self,) + args)
 
284
        pass
 
285
 
 
286
class LogRecordHTTPReceiver(HTTPServer):
 
287
    def __init__(self, host='localhost', port=logging.handlers.DEFAULT_HTTP_LOGGING_PORT,
 
288
            handler=LogRecordHTTPHandler):
 
289
        HTTPServer.__init__(self, (host, port), handler)
 
290
        self.abort = 0
 
291
        self.timeout = 1
 
292
        self.logname = None
 
293
 
 
294
    def serve_until_stopped(self):
 
295
        import select
 
296
        abort = 0
 
297
        while not abort:
 
298
            rd, wr, ex = select.select([self.socket.fileno()],
 
299
                                       [], [],
 
300
                                       self.timeout)
 
301
            if rd:
 
302
                self.handle_request()
 
303
            abort = self.abort
 
304
 
 
305
 
 
306
#
 
307
# SOAP receiver
 
308
#
 
309
 
 
310
try:
 
311
    from ZSI import dispatch
 
312
 
 
313
    logname = None
 
314
 
 
315
    def log(args, created, exc_info, exc_text, filename, levelname, levelno, lineno, module, msecs, msg, name, pathname, process, relativeCreated, thread):
 
316
        record = logging.LogRecord(None, None, "", 0, "", (), None)
 
317
        record.args = eval(args)
 
318
        record.exc_info = eval(exc_info)
 
319
        record.exc_text = eval(exc_text)
 
320
        record.created = created
 
321
        record.filename = filename
 
322
        record.module = module
 
323
        record.levelname = levelname
 
324
        record.lineno = lineno
 
325
        record.levelno = levelno
 
326
        record.msecs = msecs
 
327
        record.msg = msg
 
328
        record.name = name
 
329
        record.pathname = pathname
 
330
        record.process = process
 
331
        record.relativeCreated = relativeCreated
 
332
        record.thread = thread
 
333
        #if a name is specified, we use the named logger rather than the one
 
334
        #implied by the record. This is so test harnesses don't get into
 
335
        #endless loops (particularly log_test.py, which has this code and the
 
336
        #client code in the same Python instance)
 
337
        if logname is not None:
 
338
            lname = logname
 
339
        else:
 
340
            lname = name
 
341
        logger = logging.getLogger(lname)
 
342
        logger.handle(record)
 
343
 
 
344
    class MySOAPRequestHandler(dispatch.SOAPRequestHandler):
 
345
        def log_message(self, *args):
 
346
            #comment out the following line if you don't want to show requests
 
347
            #apply(BaseHTTPRequestHandler.log_message, (self,) + args)
 
348
            pass
 
349
 
 
350
    class SOAPServer(HTTPServer):
 
351
        def __init__(self, port=logging.handlers.DEFAULT_SOAP_LOGGING_PORT):
 
352
            address = ('', port)
 
353
            HTTPServer.__init__(self, address, MySOAPRequestHandler)
 
354
            self.abort = 0
 
355
            self.timeout = 1
 
356
            self.logname = None
 
357
            self.docstyle = 0
 
358
            self.nsdict = {}
 
359
            self.typesmodule = None
 
360
            self.rpc = 1
 
361
            self.modules = (sys.modules["__main__"],)
 
362
 
 
363
        def serve_until_stopped(self):
 
364
            import select
 
365
            abort = 0
 
366
            while not abort:
 
367
                rd, wr, ex = select.select([self.socket.fileno()],
 
368
                                           [], [],
 
369
                                           self.timeout)
 
370
                if rd:
 
371
                    global logname
 
372
                    logname = self.logname
 
373
                    self.handle_request()
 
374
                abort = self.abort
 
375
 
 
376
except ImportError:
 
377
    "Import failed"
 
378
    SOAPServer = None
 
379
 
 
380
def runTCP(tcpserver=None):
 
381
    if not tcpserver:
 
382
        tcpserver = LogRecordSocketReceiver()
 
383
    print "About to start TCP server..."
 
384
    tcpserver.serve_until_stopped()
 
385
 
 
386
def runUDP(udpserver=None):
 
387
    if not udpserver:
 
388
        udpserver = LogRecordDatagramReceiver()
 
389
    print "About to start UDP server..."
 
390
    udpserver.serve_until_stopped()
 
391
 
 
392
def runHTTP(httpserver=None):
 
393
    if not httpserver:
 
394
        httpserver = LogRecordHTTPReceiver()
 
395
    print "About to start HTTP server..."
 
396
    httpserver.serve_until_stopped()
 
397
 
 
398
def runSOAP(soapserver=None):
 
399
    if not SOAPServer:
 
400
        print "Sorry, ZSI is not available. Install PyXML-0.6.6 and ZSI first."
 
401
        print "See README.txt and python_logging.html for more information."
 
402
    else:
 
403
        if not soapserver:
 
404
            soapserver = SOAPServer()
 
405
        print "About to start SOAP server..."
 
406
        soapserver.serve_until_stopped()
 
407
 
 
408
FORMAT_STR = "%(asctime)s %(name)-19s %(levelname)-5s - %(message)s"
 
409
 
 
410
if __name__ == "__main__":
 
411
    if (len(sys.argv) < 2) or not (string.lower(sys.argv[1]) in \
 
412
                                    ["udp", "tcp", "http", "soap"]):
 
413
        print "usage: logrecv.py [UDP|TCP|HTTP|SOAP]"
 
414
    else:
 
415
        #logging.basicConfig()
 
416
        logging.config.fileConfig("logrecv.ini")
 
417
#        both = string.lower(sys.argv[1]) == "both"
 
418
#        hdlr = logging.FileHandler("test.log")
 
419
#        hdlr.setFormatter(logging.Formatter(FORMAT_STR))
 
420
#        logging.getLogger("").addHandler(hdlr)
 
421
#        if both:
 
422
#            import threading
 
423
#            tcpthread = threading.Thread(target=runTCP)
 
424
#            udpthread = threading.Thread(target=runUDP)
 
425
#            tcpthread.start()
 
426
#            udpthread.start()
 
427
#            tcpthread.join()
 
428
#            udpthread.join()
 
429
#        else:
 
430
#            tcp = string.lower(sys.argv[1]) == "tcp"
 
431
#            if tcp:
 
432
#                runTCP()
 
433
#            else:
 
434
#                runUDP()
 
435
        arg = string.lower(sys.argv[1])
 
436
        if arg == "tcp":
 
437
            runTCP()
 
438
        elif arg == "udp":
 
439
            runUDP()
 
440
        elif arg == "http":
 
441
            runHTTP()
 
442
        elif arg == "soap":
 
443
            runSOAP()