1 #@ MODIF N_info Noyau DATE 17/08/2011 AUTEUR COURTOIS M.COURTOIS
2 # -*- coding: iso-8859-1 -*-
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2011 EDF R&D WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
9 # (AT YOUR OPTION) ANY LATER VERSION.
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
18 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
20 # RESPONSABLE COURTOIS M.COURTOIS
22 """Module to manage information printing : debug, info, error.
23 Should replace 'print' and 'UTMESS' calls at least in the supervisor
25 Only used for debug right now.
32 from functools import partial
33 from subprocess import Popen, PIPE
35 from N_utils import Enum
37 def default_print(text):
38 """Basic print function."""
48 class Category(object):
49 """Define a category of message for different parts of the code.
50 This allows to store different parameters for each category of message."""
52 self._level = LEVEL.INFO
55 LEVEL.DEBUG : "DEBUG",
57 LEVEL.WARN : "WARNING",
58 LEVEL.ERROR : "ERROR",
61 def set_level(self, level):
62 """Set the current level."""
66 """Return the current level."""
69 def set_header(self, level, header):
70 """Set the header of ``level`` messages."""
71 self._header[level] = header
73 def get_header(self, level):
74 """Return the header at this ``level``."""
75 header = self._header.get(level, "")
77 header = self._fmt % header
80 def active(self, level):
81 """Tell if a message should be print at this ``level``."""
82 return self._level <= level
87 SUPERV.set_header(LEVEL.ERROR, None)
90 REGEXP_ORIG = re.compile('File [\'\"]*(.*?)[\'\"]*, *line ([0-9]+), *in (.*)')
92 # slighty different and very simplier than logger objects
93 # from the logging module.
94 class InfoLevel(object):
95 """Store informations level."""
96 def __init__(self, level):
99 for part in self._parts:
101 self.reset_print_function()
102 self._msg_callback = []
103 #self.extend_message(ALL, stack_header_callback)
104 self.extend_message(ALL, insert_header)
106 def add(self, category):
107 """Add a category of message."""
108 self._parts.append(category)
110 def set_level(self, category, level):
111 """Set the current level for ``category``."""
112 assert category in self._parts, "unknown category : %s" % category
113 assert LEVEL.exists(level), "unknown level : %s" % level
114 category.set_level(level)
116 for part in self._parts:
117 part.set_level(level)
120 """Set debug level for all categories."""
121 self.set_level(ALL, LEVEL.DEBUG)
123 def set_header(self, category, level, header):
124 """Set the header of ``level`` messages."""
125 category.set_header(level, header)
127 def register_print_function(self, print_function):
128 """Define the `print_function` to use."""
129 self._print = print_function
131 def reset_print_function(self):
132 """Register the default 'print function'."""
133 self._print = default_print
135 def extend_message(self, category, callback):
136 """Allow to extend the message calling an external function."""
137 self._msg_callback.append((category, callback))
139 def _message(self, category, level, msg, args, kwargs):
140 """Print the message if the level is reached."""
141 if category.active(level):
142 if kwargs.get('utmess'):
143 func = self._message_utmess
145 func = self._message_print
146 func = self._message_print
147 apply(func, (category, level, msg, args, kwargs))
149 def _message_print(self, category, level, msg, args, kwargs):
150 """Print the message if the level is reached."""
151 for cat, cbk in self._msg_callback:
152 if cat in (ALL, category):
153 msg, args = cbk(category, level, msg, args, kwargs)
157 except Exception, err:
158 msg = repr((msg, args, err))
161 def _message_utmess(self, category, level, msg, args, kwargs):
162 """Print the message if the level is reached."""
163 # how to use callbacks ? valk ?
164 from Utilitai.Utmess import MessageLog
171 valk = kwargs.get('valk', ())
172 vali = kwargs.get('vali', ())
173 valr = kwargs.get('valr', ())
174 msg = MessageLog.GetText(code[level], msg, valk, vali, valr)
175 for cat, cbk in self._msg_callback:
176 if cat in (ALL, category):
177 msg, args = cbk(category, level, msg, args, kwargs)
180 def debug(self, category, msg, *args, **kwargs):
181 """Print a debug message."""
182 self._message(category or ALL, LEVEL.DEBUG, msg, args, kwargs)
184 def info(self, category, msg, *args, **kwargs):
185 """Print an information message."""
186 self._message(category or ALL, LEVEL.INFO, msg, args, kwargs)
188 def warn(self, category, msg, *args, **kwargs):
189 """Print a warning message."""
190 self._message(category or ALL, LEVEL.WARN, msg, args, kwargs)
192 def error(self, category, msg, *args, **kwargs):
193 """Print an error message."""
194 self._message(category or ALL, LEVEL.ERROR, msg, args, kwargs)
198 def add_memory_info(self, category):
199 """Shortcut to add memory informations."""
200 self.extend_message(category, mem_msg_callback)
202 def use_aster_print(self):
203 """Shortcut to use aster.affiche function to print the messages."""
205 self.register_print_function(partial(aster.affiche, 'MESSAGE'))
209 def insert_header(category, level, msg, args, kwargs):
210 """Insert the header."""
211 header = category.get_header(level)
216 def stack_header_callback(category, level, msg, args, kwargs):
217 """To insert the origin."""
218 if level <= LEVEL.DEBUG:
219 stack_id = -5 + kwargs.get('stack_id', 0)
220 stack = traceback.format_stack(limit=10)[stack_id]
221 mat = REGEXP_ORIG.search(stack)
222 origin = '[%s:%s in %s] ' % (osp.basename(mat.group(1)), mat.group(2), mat.group(3))
228 message = InfoLevel(LEVEL.INFO)
233 # callback to add memory information
236 RE_VMPEAK = re.compile('VmPeak:\s*([0-9]+)\s*([kMGBo]+)', re.M | re.I)
238 def memory_used(pid):
239 """Return the current VmPeak value."""
240 p = Popen(['cat', '/proc/%s/status' % pid], stdout=PIPE)
241 output = p.communicate()[0]
242 mat = RE_VMPEAK.search(output)
243 return int(mat.group(1)) / 1024.
245 current_memory_used = partial(memory_used, _pid)
247 def mem_msg_callback(category, level, msg, args, kwargs):
248 """Callback to add memory infos to message."""
249 if level <= LEVEL.DEBUG:
250 msg = msg + " - VmPeak : %.2f Mo"
251 args = tuple(list(args) + [current_memory_used(), ])
255 if __name__ == "__main__":
256 message.set_level(SUPERV, LEVEL.WARN)
257 message.set_level(MISS, LEVEL.DEBUG)
258 message.debug(None, "debug message")
259 message.info(ALL, "information message")
260 message.warn(None, "warning message")
261 message.error(ALL, "error message")
262 message.add_memory_info()
263 message.debug(MISS, "debug supervisor message")
264 message.info(SUPERV, "information supervisor message")
265 message.warn(SUPERV, "warning supervisor message")
266 message.error(SUPERV, "error supervisor message")
267 message.critical(MISS, "test the critical alias")