91be2b477c1d2b6c04be589958da04ba383c9bd2
[feedingit] / psa_harmattan / feedingit / deb_dist / feedingit-0.1.0 / debian / feedingit / usr / share / feedingit / debugging.py
1 # Copyright (c) 2011 Neal H. Walfield
2 #
3 # This software is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This software is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 from __future__ import with_statement
17 import os
18 import logging
19 import itertools
20 import sys
21 import string
22 import traceback
23 import time
24 import errno
25 import glob
26
27 logger = None
28 original_excepthook = None
29
30 def my_excepthook(exctype, value, tb):
31     """Log uncaught exceptions."""
32     logger.error(
33         "Uncaught exception: %s"
34         % (''.join(traceback.format_exception(exctype, value, tb)),))
35     original_excepthook(exctype, value, tb)
36
37 def init(dot_directory, debug=False, max_logfiles=1, program_name=None):
38     debug = True
39     if not os.path.isabs(dot_directory):
40         dot_directory = os.path.join(os.path.expanduser("~"), dot_directory)
41
42     logging_directory = os.path.join(dot_directory, "logging")
43     try:
44         os.makedirs(logging_directory)
45     except OSError, e:
46         if e.errno != errno.EEXIST:
47             raise
48
49     if program_name is None:
50         program_name = os.path.basename(sys.argv[0])
51     string.translate(program_name, string.maketrans(' .', '__'))
52
53     timestamp = time.strftime("%Y%m%d")
54
55     logfiles = glob.glob(os.path.join(logging_directory,
56                                       program_name + '-*.log'))
57     if len(logfiles) >= max_logfiles:
58         logfiles.sort()
59         for f in logfiles[:-(max_logfiles+1)]:
60             print "Purging old log file %s" % (f,)
61             try:
62                 os.remove(f)
63             except OSError, e:
64                 print "Removing %s: %s" % (f, str(e))
65
66     logfile = os.path.join(logging_directory,
67                            program_name + '-' + timestamp + '.log')
68
69     print "Sending output to %s" % logfile
70
71     global logger
72     logger = logging.getLogger(__name__) 
73
74     if debug:
75         level = logging.DEBUG
76     else:
77         level = logging.INFO
78
79     logging.basicConfig(
80         level=level,
81         format=('%(asctime)s (pid: ' + str(os.getpid()) + ') '
82                 + '%(levelname)-8s %(message)s'),
83         filename=logfile,
84         filemode='a')
85
86     # Log uncaught exceptions.
87     global original_excepthook
88     original_excepthook = sys.excepthook
89     sys.excepthook = my_excepthook
90
91     def redirect(thing):
92         filename = os.path.join(logging_directory, program_name + '.' + thing)
93         try:
94             with open(filename, "r") as fhandle:
95                 contents = fhandle.read()
96         except IOError, e:
97             if e.errno in (errno.ENOENT,):
98                 fhandle = None
99                 contents = ""
100             else:
101                 logging.error("Reading %s: %s" % (filename, str(e)))
102                 raise
103
104         logging.error("std%s of last run: %s" % (thing, contents))
105
106         if fhandle is not None:
107             os.remove(filename)
108
109         print "Redirecting std%s to %s" % (thing, filename)
110         return open(filename, "w", 0)
111             
112     sys.stderr = redirect('err')
113     sys.stdout = redirect('out')
114