* tried to put some sense in the way things get logged, at least on server-side for now
[sfa.git] / sfa / util / sfalogging.py
1 #!/usr/bin/python
2
3 import os
4 import traceback
5 import logging, logging.handlers
6
7 class SfaLogging:
8     def __init__ (self,logfile,name=None,level=logging.INFO):
9         # default is to locate logger name from the logfile
10         if not name:
11             name=os.path.basename(logfile)
12         self.logger=logging.getLogger(name)
13         self.logger.setLevel(level)
14         try:
15             handler=logging.handlers.RotatingFileHandler(logfile,maxBytes=1000000, backupCount=5) 
16         except IOError:
17             # This is usually a permissions error becaue the file is
18             # owned by root, but httpd is trying to access it.
19             tmplogfile=os.getenv("TMPDIR", "/tmp") + os.path.sep + os.path.basename(logfile)
20             handler=logging.handlers.RotatingFileHandler(tmplogfile,maxBytes=1000000, backupCount=5) 
21         handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
22         self.logger.addHandler(handler)
23
24     def wrap(fun):
25         def wrapped(self,msg,*args,**kwds):
26             native=getattr(self.logger,fun.__name__)
27             return native(msg,*args,**kwds)
28         #wrapped.__doc__=native.__doc__
29         return wrapped
30
31     def setLevel(self,level):
32         self.logger.setLevel(level)
33
34     @wrap
35     def critical(): pass
36     @wrap
37     def error(): pass
38     @wrap
39     def warning(): pass
40     @wrap
41     def info(): pass
42     @wrap
43     def debug(): pass
44     
45     # logs an exception - use in an except statement
46     def log_exc(self,message):
47         self.error("%s BEG TRACEBACK"%message+"\n"+traceback.format_exc().strip("\n"))
48         self.error("%s END TRACEBACK"%message)
49     
50     def log_exc_critical(self,message):
51         self.critical("%s BEG TRACEBACK"%message+"\n"+traceback.format_exc().strip("\n"))
52         self.critical("%s END TRACEBACK"%message)
53     
54     # for investigation purposes, can be placed anywhere
55     def log_stack(self,message):
56         to_log="".join(traceback.format_stack())
57         self.debug("%s BEG STACK"%message+"\n"+to_log)
58         self.debug("%s END STACK"%message)
59
60 sfa_logger=SfaLogging(logfile='/var/log/sfa.log')
61 sfa_import_logger=SfaLogging(logfile='/var/log/sfa_import.log')
62
63
64 ########################################
65 import time
66
67 def profile(callable):
68     """
69     Prints the runtime of the specified callable. Use as a decorator, e.g.,
70
71         @profile
72         def foo(...):
73             ...
74
75     Or, equivalently,
76
77         def foo(...):
78             ...
79         foo = profile(foo)
80
81     Or inline:
82
83         result = profile(foo)(...)
84     """
85
86     def wrapper(*args, **kwds):
87         start = time.time()
88         result = callable(*args, **kwds)
89         end = time.time()
90         args = map(str, args)
91         args += ["%s = %s" % (name, str(value)) for (name, value) in kwds.items()]
92         sfa_logger.debug("%s (%s): %.02f s" % (callable.__name__, ", ".join(args), end - start))
93         return result
94
95     return wrapper
96
97 if __name__ == '__main__': 
98     print 'testing sfalogging into logger.log'
99     global sfa_logger
100     sfa_logger=SfaLogging('logger.log')
101     sfa_logger.critical("logger.critical")
102     sfa_logger.error("logger.error")
103     sfa_logger.warning("logger.warning")
104     sfa_logger.info("logger.info")
105     sfa_logger.debug("logger.debug")
106     sfa_logger.setLevel(logging.DEBUG)
107     sfa_logger.debug("logger.debug again")
108
109     @profile
110     def sleep(seconds = 1):
111         time.sleep(seconds)
112
113     sleep(1)