]> SALOME platform Git repositories - tools/sat.git/blob - src/logger.py
Salome HOME
Change log directory. It is now set in site.pyconf
[tools/sat.git] / src / logger.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2012  CEA/DEN
4 #
5 #  This library is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU Lesser General Public
7 #  License as published by the Free Software Foundation; either
8 #  version 2.1 of the License.
9 #
10 #  This library is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  Lesser General Public License for more details.
14 #
15 #  You should have received a copy of the GNU Lesser General Public
16 #  License along with this library; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18
19 import sys
20 import os
21 import datetime
22
23 import src
24 from . import printcolors
25 from . import xmlManager
26
27 class Logger(object):
28     '''Class to handle log mechanism
29     '''
30     def __init__(self, config, silent_sysstd=False):
31         '''Initialization
32         
33         :param config pyconf.Config: The global configuration.
34         :param silent_sysstd boolean: if True, do not write anything in terminal.
35         '''
36         self.config = config
37         self.default_level = 3
38         self.silentSysStd = silent_sysstd
39         
40         # Construct log file location. There are two cases. With an application an without any application.
41         logFileName = config.VARS.datehour + "_" + config.VARS.command + ".xml"
42         logFilePath = os.path.join(config.SITE.log.logDir, logFileName)
43
44         src.ensure_path_exists(os.path.dirname(logFilePath))
45         
46         self.logFileName = logFileName
47         self.logFilePath = logFilePath   
48         self.xmlFile = xmlManager.xmlLogFile(logFilePath, "SATcommand", attrib = {"command" : config.VARS.command})
49         self.putInitialXMLFields()
50         
51     def putInitialXMLFields(self):
52         '''Method called at class initialization : Put all fields corresponding to the command context (user, time, ...)
53         '''
54         # command name
55         self.xmlFile.add_simple_node("Site", attrib={"command" : self.config.VARS.command})
56         # version of salomeTools
57         self.xmlFile.append_node_attrib("Site", attrib={"satversion" : self.config.INTERNAL.sat_version})
58         # machine name on which the command has been launched
59         self.xmlFile.append_node_attrib("Site", attrib={"hostname" : self.config.VARS.hostname})
60         # Distribution of the machine
61         self.xmlFile.append_node_attrib("Site", attrib={"OS" : self.config.VARS.dist})
62         # The user that have launched the command
63         self.xmlFile.append_node_attrib("Site", attrib={"user" : self.config.VARS.user})
64         # The time when command was launched
65         Y, m, dd, H, M, S = date_to_datetime(self.config.VARS.datehour)
66         date_hour = "%2s/%2s/%4s %2sh%2sm%2ss" % (dd, m, Y, H, M, S)
67         self.xmlFile.append_node_attrib("Site", attrib={"beginTime" : date_hour})
68         # The initialization of the trace node
69         self.xmlFile.add_simple_node("Log",text="")
70
71     def write(self, message, level=None, screenOnly=False):
72         '''the function used in the commands that will print in the terminal and the log file.
73         
74         :param message str: The message to print.
75         :param level int: The output level corresponding to the message 0 < level < 6.
76         :param screenOnly boolean: if True, do not write in log file.
77         '''
78         # do not write message starting with \r to log file
79         if not message.startswith("\r") and not screenOnly:
80             self.xmlFile.append_node_text("Log", printcolors.cleancolor(message))
81
82         # get user or option output level
83         current_output_level = self.config.USER.output_level
84         if not ('isatty' in dir(sys.stdout) and sys.stdout.isatty()):
85             # clean the message color if the terminal is redirected by user
86             # ex: sat compile appli > log.txt
87             message = printcolors.cleancolor(message)
88         
89         # Print message regarding the output level value
90         if level:
91             if level <= current_output_level and not self.silentSysStd:
92                 sys.stdout.write(message)
93         else:
94             if self.default_level <= current_output_level and not self.silentSysStd:
95                 sys.stdout.write(message)
96
97     def error(self, message):
98         '''Print an error.
99         
100         :param message str: The message to print.
101         '''
102         # Print in the log file
103         self.xmlFile.append_node_text("traces", _('ERROR:') + message)
104
105         # Print in the terminal and clean colors if the terminal is redirected by user
106         if not ('isatty' in dir(sys.stderr) and sys.stderr.isatty()):
107             sys.stderr.write(printcolors.printcError(_('ERROR:') + message))
108         else:
109             sys.stderr.write(_('ERROR:') + message)
110
111     def flush(self):
112         '''Flush terminal
113         '''
114         sys.stdout.flush()
115         
116     def endWrite(self, attribute):
117         '''Method called just after command end : Put all fields corresponding to the command end context (time).
118         Write the log xml file on the hard drive.
119         And display the command to launch to get the log
120         
121         :param attribute dict: the attribute to add to the node "Site".
122         '''       
123         # Get current time (end of command) and format it
124         dt = datetime.datetime.now()
125         Y, m, dd, H, M, S = date_to_datetime(self.config.VARS.datehour)
126         t0 = datetime.datetime(int(Y), int(m), int(dd), int(H), int(M), int(S))
127         tf = dt
128         delta = tf - t0
129         total_time = timedelta_total_seconds(delta)
130         hours = int(total_time / 3600)
131         minutes = int((total_time - hours*3600) / 60)
132         seconds = total_time - hours*3600 - minutes*60
133         # Add the fields corresponding to the end time and the total time of command
134         endtime = dt.strftime('%d/%Y/%m %Hh%Mm%Ss')
135         self.xmlFile.append_node_attrib("Site", attrib={"endTime" : endtime})
136         self.xmlFile.append_node_attrib("Site", attrib={"TotalTime" : "%ih%im%is" % (hours, minutes, seconds)})
137         
138         # Add the attribute passed to the method
139         self.xmlFile.append_node_attrib("Site", attrib=attribute)
140         
141         # Call the method to write the xml file on the hard drive
142         self.xmlFile.write_tree(stylesheet = "command.xsl")
143         
144         # Update the hat xml (that shows all logs) in order to make the new log visible on the main log page)
145         src.xmlManager.update_hat_xml(self.config.SITE.log.logDir)
146
147 def date_to_datetime(date):
148     '''Little method that gets year, mon, day, hour , minutes and seconds from a str in format YYYYMMDD_HHMMSS
149     
150     :param date str: The date in format YYYYMMDD_HHMMSS
151     :return: the same date and time in separate variables.
152     :rtype: (str,str,str,str,str,str)
153     '''
154     Y = date[:4]
155     m = date[4:6]
156     dd = date[6:8]
157     H = date[9:11]
158     M = date[11:13]
159     S = date[13:15]
160     return Y, m, dd, H, M, S
161
162 def timedelta_total_seconds(timedelta):
163     '''Little method to replace total_seconds from datetime module in order to be compatible with old python versions
164     
165     :param timedelta datetime.timedelta: The delta between two dates
166     :return: The number of seconds corresponding to timedelta.
167     :rtype: float
168     '''
169     return (
170         timedelta.microseconds + 0.0 +
171         (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6