Salome HOME
Minor print update
[modules/adao.git] / src / daComposant / daCore / ExtendedLogging.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2019 EDF R&D
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 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 """
24     Ce module permet de mettre en place un logging utilisable partout dans
25     l'application, par défaut à la console, et si nécessaire dans un fichier.
26
27     Il doit être appelé en premier dans AssimilationStudy (mais pas directement
28     dans les applications utilisateurs), en l'important et en instanciant un
29     objet :
30         import ExtendedLogging ; ExtendedLogging.ExtendedLogging()
31
32     Par défaut, seuls les messages du niveau WARNING ou au-delà sont disponibles
33     (donc les simples messages d'info ne sont pas disponibles), ce que l'on peut
34     changer à l'instanciation avec le mot-clé "level" :
35         import ExtendedLogging ; ExtendedLogging.ExtendedLogging(level=20)
36
37     On peut éventuellement demander à l'objet de sortir aussi les messages dans
38     un fichier (noms par défaut : AssimilationStudy.log, niveau NOTSET) :
39         import ExtendedLogging ; ExtendedLogging.ExtendedLogging().setLogfile()
40
41     Si on veut changer le nom du fichier ou le niveau global de message, il faut
42     récupérer l'instance et appliquer les méthodes :
43         import ExtendedLogging
44         log = ExtendedLogging.ExtendedLogging()
45         import logging
46         log.setLevel(logging.DEBUG)
47         log.setLogfile(filename="toto.log", filemode="a", level=logging.WARNING)
48     et on change éventuellement le niveau avec :
49         log.setLogfileLevel(logging.INFO)
50
51     Ensuite, n'importe où dans les applications, il suffit d'utiliser le module
52     "logging" (avec un petit "l") :
53         import logging
54         log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
55         log.critical("...")
56         log.error("...")
57         log.warning("...")
58         log.info("...")
59         log.debug("...")
60     ou encore plus simplement :
61         import logging
62         logging.info("...")
63
64     Dans une application, à n'importe quel endroit et autant de fois qu'on veut,
65     on peut changer le niveau global de message en utilisant par exemple :
66         import logging
67         log = logging.getLogger(NAME) # Avec rien (recommandé) ou un nom NAME
68         log.setLevel(logging.DEBUG)
69
70     On rappelle les niveaux (attributs de "logging") et leur ordre :
71         NOTSET=0 < DEBUG=10 < INFO=20 < WARNING=30 < ERROR=40 < CRITICAL=50
72 """
73 __author__ = "Jean-Philippe ARGAUD"
74 __all__ = []
75
76 import os
77 import sys
78 import logging
79 import functools
80 import time
81 from daCore import PlatformInfo
82
83 LOGFILE = os.path.join(os.path.abspath(os.curdir),"AssimilationStudy.log")
84
85 # ==============================================================================
86 class ExtendedLogging(object):
87     """
88     Logger général pour disposer conjointement de la sortie standard et de la
89     sortie sur fichier
90     """
91     def __init__(self, level=logging.WARNING):
92         """
93         Initialise un logging à la console pour TOUS les niveaux de messages.
94         """
95         logging.basicConfig(
96             format = '%(levelname)-8s %(message)s',
97             level  = level,
98             stream = sys.stdout,
99             )
100         self.__logfile = None
101         #
102         # Initialise l'affichage de logging
103         # ---------------------------------
104         p = PlatformInfo.PlatformInfo()
105         #
106         logging.info( "--------------------------------------------------" )
107         logging.info( p.getName()+" version "+p.getVersion() )
108         logging.info( "--------------------------------------------------" )
109         logging.info( "Library availability:" )
110         logging.info( "- Python.......: True" )
111         logging.info( "- Numpy........: True" )
112         logging.info( "- Scipy........: "+str(PlatformInfo.has_scipy) )
113         logging.info( "- Matplotlib...: "+str(PlatformInfo.has_matplotlib) )
114         logging.info( "- Gnuplot......: "+str(PlatformInfo.has_scipy) )
115         logging.info( "- Sphinx.......: "+str(PlatformInfo.has_sphinx) )
116         logging.info( "- Nlopt........: "+str(PlatformInfo.has_nlopt) )
117         logging.info( "Library versions:" )
118         logging.info( "- Python.......: "+p.getPythonVersion() )
119         logging.info( "- Numpy........: "+p.getNumpyVersion() )
120         logging.info( "- Scipy........: "+p.getScipyVersion() )
121         logging.info( "" )
122
123     def setLogfile(self, filename=LOGFILE, filemode="w", level=logging.NOTSET):
124         """
125         Permet de disposer des messages dans un fichier EN PLUS de la console.
126         """
127         if self.__logfile is not None:
128             # Supprime le précédent mode de stockage fichier s'il exsitait
129             logging.getLogger().removeHandler(self.__logfile)
130         self.__logfile = logging.FileHandler(filename, filemode)
131         self.__logfile.setLevel(level)
132         self.__logfile.setFormatter(
133             logging.Formatter('%(asctime)s %(levelname)-8s %(message)s',
134                               '%d %b %Y %H:%M:%S'))
135         logging.getLogger().addHandler(self.__logfile)
136
137     def setLogfileLevel(self, level=logging.NOTSET ):
138         """
139         Permet de changer le niveau des messages stockés en fichier. Il ne sera
140         pris en compte que s'il est supérieur au niveau global.
141         """
142         self.__logfile.setLevel(level)
143
144     def getLevel(self):
145         """
146         Renvoie le niveau de logging sous forme texte
147         """
148         return logging.getLevelName( logging.getLogger().getEffectiveLevel() )
149
150 # ==============================================================================
151 def logtimer(f):
152     @functools.wraps(f)
153     def wrapper(*args, **kwargs):
154         start  = time.clock() # time.time()
155         result = f(*args, **kwargs)
156         end    = time.clock() # time.time()
157         msg    = 'TIMER Durée elapsed de la fonction utilisateur "{}": {:.3f}s'
158         logging.debug(msg.format(f.__name__, end-start))
159         return result
160     return wrapper
161
162 # ==============================================================================
163 if __name__ == "__main__":
164     print('\n AUTODIAGNOSTIC\n')