Salome HOME
Write log even if command fails (bug in code). Right print of command to launch to...
[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 that 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         if 'APPLICATION' in config:
43             logFilePath = os.path.join(config.APPLICATION.out_dir, 'LOGS', logFileName)
44         else:
45             logFilePath = os.path.join(config.VARS.personalDir, 'LOGS', logFileName)
46         src.ensure_path_exists(os.path.dirname(logFilePath))
47         
48         self.logFileName = logFileName
49         self.logFilePath = logFilePath   
50         self.xmlFile = xmlManager.xmlLogFile(logFilePath, "SATcommand", attrib = {"command" : config.VARS.command})
51         self.putInitialXMLFields()
52         
53     def putInitialXMLFields(self):
54         self.xmlFile.add_simple_node("field", text=self.config.VARS.command , attrib={"name" : "command"})
55         self.xmlFile.add_simple_node("field", text=self.config.INTERNAL.sat_version , attrib={"name" : "satversion"})
56         self.xmlFile.add_simple_node("field", text=self.config.VARS.hostname , attrib={"name" : "hostname"})
57         self.xmlFile.add_simple_node("field", text=self.config.VARS.dist , attrib={"name" : "OS"})
58         self.xmlFile.add_simple_node("field", text=self.config.VARS.user , attrib={"name" : "user"})
59         self.xmlFile.add_simple_node("field", text=self.config.VARS.datehour , attrib={"name" : "beginTime"})
60         self.xmlFile.add_simple_node("traces",text="")
61
62     def write(self, message, level=None, screenOnly=False):
63         '''the function used in the commands that will print in the terminal and the log file.
64         
65         :param message str: The message to print.
66         :param level int: The output level corresponding to the message 0 < level < 6.
67         :param screenOnly boolean: if True, do not write in log file.
68         '''
69         # do not write message starting with \r to log file
70         if not message.startswith("\r") and not screenOnly:
71             self.xmlFile.append_node("traces", printcolors.cleancolor(message))
72
73         # get user or option output level
74         current_output_level = self.config.USER.output_level
75         if not ('isatty' in dir(sys.stdout) and sys.stdout.isatty()):
76             # clean the message color if the terminal is redirected by user
77             # ex: sat compile appli > log.txt
78             message = printcolors.cleancolor(message)
79         
80         # Print message regarding the output level value
81         if level:
82             if level <= current_output_level and not self.silentSysStd:
83                 sys.stdout.write(message)
84         else:
85             if self.default_level <= current_output_level and not self.silentSysStd:
86                 sys.stdout.write(message)
87
88     def error(self, message):
89         '''Print an error.
90         
91         :param message str: The message to print.
92         '''
93         # Print in the log file
94         self.xmlFile.append_node("traces", _('ERROR:') + message)
95
96         # Print in the terminal and clean colors if the terminal is redirected by user
97         if not ('isatty' in dir(sys.stderr) and sys.stderr.isatty()):
98             sys.stderr.write(printcolors.printcError(_('ERROR:') + message))
99         else:
100             sys.stderr.write(_('ERROR:') + message)
101
102     def flush(self):
103         '''Flush terminal
104         '''
105         sys.stdout.flush()
106         
107     def endWrite(self):
108         
109         self.write(_('\nTap the following command to get the log :\n'), screenOnly=True)
110         if 'APPLICATION' in self.config:
111             self.write('%s/sat log %s\n' % (self.config.VARS.salometoolsway, self.config.VARS.application), screenOnly=True)
112         else:
113             self.write('%s/sat log\n' % self.config.VARS.salometoolsway, screenOnly=True)
114         
115         dt = datetime.datetime.now()
116         endtime = dt.strftime('%Y%m%d_%H%M%S')
117         t0 = date_to_datetime(self.config.VARS.datehour)
118         tf = dt
119         delta = tf - t0
120         total_time = delta.total_seconds()
121         hours = int(total_time / 3600)
122         minutes = int((total_time - hours*3600) / 60)
123         seconds = total_time - hours*3600 - minutes*60
124         self.xmlFile.add_simple_node("field", text=endtime , attrib={"name" : "endTime"})
125         self.xmlFile.add_simple_node("field", text="%ih%im%is" % (hours, minutes, seconds) , attrib={"name" : "Total Time"})
126         self.xmlFile.write_tree(stylesheet = "command.xsl")
127         if 'APPLICATION' in self.config:
128             src.xmlManager.update_hat_xml(self.config.VARS.logDir, self.config.VARS.application)
129         else:
130             src.xmlManager.update_hat_xml(self.config.VARS.logDir)
131
132 def date_to_datetime(date):
133     Y = int(date[:4])
134     m = int(date[4:6])
135     dd = int(date[6:8])
136     H = int(date[9:11])
137     M = int(date[11:13])
138     S = int(date[13:15])
139     return datetime.datetime(Y, m, dd, H, M, S)