1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 __all__ = ['debug','log','warn','stack','halt']
37 """ Debug and warning system (just error display). """
38
39
40 import traceback
41 import sys
42 import time
43 import os
44
47 self.name = name
48 if outfile:
49 self.file = outfile
50 else:
51 self.file = file(name,'a+b',0)
52
54 self.file.write(string)
55
59
61 syslog.openlog(self.name)
62 syslog.syslog(syslog.LOG_ERR, string)
63 syslog.closelog()
64
65
66
67
68
69
70 output = {}
77
79 """ Creates a logger function (a closure)
80 With |logid| name (to the set the output filename) and a function that choose the
81 a tuple of log names to be used by call (|logsplitter|). The output files will be opened
82 using the function |openfun|(logid, logname) and must return a file like object
83 (only write method is needed)
84 if |openfun| is None every file is opened in append and binary mode and
85 output filenames are ${main-log-directory}/log.${logid}.${logname}
86 Where ${main-log-directory} can be set with the function set_main_log_directory
87 ${logid} It the logid gived to this function
88 ${logname} It's the returned value of the logsplitter function
89
90 ------------------------
91 For example:
92 logger = logger_create_by_function("by-date", lambda x,y: (time.strftime("%y-%m"),))
93 logger = logger_create_by_function("spyro-user", lambda x,y: (spyro.getrequest()['auth'][0],)) # Using the SPyRO's Module
94 logger = logger_create_by_function("spyro-obj", lambda x,y: (spyro.getrequest()['objname'],))# Using the SPyRO's Module
95 logger = logger_create_by_function("log-ip", lambda x,y: (shttp.http.getrequest()['HTTP_REMOTE_ADDR'],)) # Using the SPyRO's shttp Module
96 set_main_log_function(logger)
97
98 The exact prototype of |logsplitter|
99 iterableobject logsplitter(str logid, str logname)
100
101 Note: The opened files are never closed, if you need to close them, use the
102 dictionary warn.Warn.outputs
103
104 key: logname (not logid), value: output file
105
106 ------------------------------
107 If logsplitter raises an exception (like KeyError for unknown logs or a failed log name resolution)
108 the default log is used (logger_simple)
109 """
110 if openfun is None:
111 def xopenfun(_logid, _logname):
112 xfilename = os.path.join(_MAIN_LOG_DIRECTORY,"log.%s.%s"%(_logid,_logname))
113 return file(xfilename, "ab", 0)
114 openfun = xopenfun
115 def _thelogger(_logname, string):
116 try:
117 lognamelist = logsplitter(logid, _logname)
118 for logname in lognamelist:
119 try:
120 outfile = Warn.output[logname]
121 except KeyError:
122 outfile = Warn.output[logname] = openfun(logid, logname)
123 outfile.write(string)
124 except Exception:
125 logger_simple(_logname, string)
126 return _thelogger
127
128 _MAIN_LOG_FUNCTION = logger_simple
129 _MAIN_LOG_DIRECTORY = "."
130
132 """ The main log directory. For default loggers """
133 global _MAIN_LOG_DIRECTORY
134 _MAIN_LOG_DIRECTORY = dirname
135
137 """ Initialices the global logger, this is the core of the warn module
138 And it can be used to perform fancy splitted logs, like log by session,
139 user, module, spyro objects, by network address, by time, by day, etc.
140
141 |logger| The function logger. It can be any object that can be called.
142 The prototype must be:
143
144 void logger(logname, logdata)
145
146 Where logname is the name of the log
147 logdata is the data to be logged
148 """
149 global _MAIN_LOG_FUNCTION
150 _MAIN_LOG_FUNCTION = logger
151
153 LOG_SYSLOG = 1
154 LOG_FILE = 2
155 LOG_STDERR = 3
156 output = output
157 - def __init__(self, name, outfile=None, filename=None, logtype=None):
158 """ Creates a Warn object. Warn objects provide useful
159 tools to show errors and warnings.
160 |name| The name of the warn object
161 |outfile| An output object in case that you have a default output.
162 If None, a file will be created
163 |logtype| If it must use syslog. If none it uses output to file.
164 Possible values are: Warn.LOG_FILE, Warn.LOG_SYSLOG, Warn.LOG_STDERR
165 Default: LOG_STDERR
166 If LOG_FILE is specified the constructor needs any of the
167 following keyword arguments:
168 filename='filename-to-output' or outfile=fileobject
169
170 NOTE: If output already has a handler, this handler is used overriding
171 any of the opening instructions. In order to override, you need
172 to modify the handler (using warn.output) directly
173 """
174 self.name = name
175 if logtype is None: logtype = Warn.LOG_STDERR
176
177 if Warn.output.has_key(name): return
178 if logtype == Warn.LOG_STDERR:
179 Warn.output[name] = sys.stderr
180 elif logtype == Warn.LOG_SYSLOG:
181 Warn.output[name] = SyslogWriter(name)
182 elif logtype == Warn.LOG_FILE:
183 if not outfile:
184 if not filename:
185 raise "You must specify a filename if you want a LOG_FILE Warn object"
186 outfile = open(filename,'a+b',0)
187 Warn.output[name] = outfile
188 else:
189 raise Exception("Invalid type of Warn")
190
191 - def write(self, string):
192 """ Output for loggin, append the current time, the name of the log, and the pid """
193 self._write("%s %s: %s"%(time.ctime(time.time()), self.name, string))
194
196 """ Direct write to the output """
197 _MAIN_LOG_FUNCTION(self.name, string)
198
200 """ Shows the args on the stderr """
201 self.write("DEBUG: " + "".join(map(str,args)) + "\n")
202
203 - def log(self, *args):
204 """ Shows the args on a log """
205 self.write("LOG: " + "".join(map(str,args)) + "\n")
206
207 - def warn(self,*args):
208 """ Shows |args| as warning, and print the last exception catched """
209 exc=sys.exc_info()
210 self.write("".join(("WARNING: ", "".join(map(str,args)), "\n", str(exc[1]))))
211 traceback.print_tb(exc[2],file=self)
212
214 """ Shows |args| as warning, and print the stack of current caller """
215 self.write("STACK: " + "".join(map(str,args)) + "\n")
216 traceback.print_stack(file=self)
217
218 - def halt(self,*args):
219 """ Displays |args|, print the last_exception and exits with code 127"""
220 exc=sys.exc_info()
221 self.write("".join(("HALT: ", "".join(map(str,args)), "\n", str(exc[1]))))
222 traceback.print_tb(exc[2],file=self)
223
224 try:
225 _name = "PID " + str(os.getpid())
226 except AttributeError:
227 _name = sys.argv[0]
228 _w = Warn(_name,outfile=sys.stderr)
229 debug = _w.debug
230 log = _w.log
231 warn = _w.warn
232 stack = _w.stack
233 halt = _w.halt
234 write = _w.write
235 _write = _w._write
236