2 # This file implements the log mechanism for Python tools.
4 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 from sys
import stdout
22 from sys
import stderr
25 from logging
import getLogger
26 from logging
import Formatter
27 from logging
import StreamHandler
28 from logging
import FileHandler
29 from traceback
import extract_stack
31 from Logger
.ToolError
import FatalError
32 from Logger
.ToolError
import WARNING_AS_ERROR
33 from Logger
.ToolError
import gERROR_MESSAGE
34 from Logger
.ToolError
import UNKNOWN_ERROR
35 from Library
import GlobalData
64 _TOOL_NAME
= os
.path
.basename(argv
[0])
66 # For validation purpose
68 _LOG_LEVELS
= [DEBUG_0
, DEBUG_1
, DEBUG_2
, DEBUG_3
, DEBUG_4
, DEBUG_5
, DEBUG_6
, \
69 DEBUG_7
, DEBUG_8
, DEBUG_9
, VERBOSE
, WARN
, INFO
, ERROR
, QUIET
, \
72 # For DEBUG level (All DEBUG_0~9 are applicable)
74 _DEBUG_LOGGER
= getLogger("tool_debug")
75 _DEBUG_FORMATTER
= Formatter("[%(asctime)s.%(msecs)d]: %(message)s", \
78 # For VERBOSE, INFO, WARN level
80 _INFO_LOGGER
= getLogger("tool_info")
81 _INFO_FORMATTER
= Formatter("%(message)s")
85 _ERROR_LOGGER
= getLogger("tool_error")
86 _ERROR_FORMATTER
= Formatter("%(message)s")
89 # String templates for ERROR/WARN/DEBUG log message
91 _ERROR_MESSAGE_TEMPLATE
= \
92 ('\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s')
94 __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE
= \
95 '\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s'
97 _WARNING_MESSAGE_TEMPLATE
= '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s'
98 _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE
= '%(tool)s: : warning: %(msg)s'
99 _DEBUG_MESSAGE_TEMPLATE
= '%(file)s(%(line)s): debug: \n %(msg)s'
105 #Info = _INFO_LOGGER.info
107 def Info(msg
, *args
, **kwargs
):
108 _INFO_LOGGER
.info(msg
, *args
, **kwargs
)
111 # Log information which should be always put out
113 def Quiet(msg
, *args
, **kwargs
):
114 _ERROR_LOGGER
.error(msg
, *args
, **kwargs
)
118 # @param Level DEBUG level (DEBUG0~9)
119 # @param Message Debug information
120 # @param ExtraData More information associated with "Message"
122 def Debug(Level
, Message
, ExtraData
=None):
123 if _DEBUG_LOGGER
.level
> Level
:
128 # Find out the caller method information
130 CallerStack
= extract_stack()[-2]
132 "file" : CallerStack
[0],
133 "line" : CallerStack
[1],
137 if ExtraData
is not None:
138 LogText
= _DEBUG_MESSAGE_TEMPLATE
% TemplateDict
+ "\n %s" % ExtraData
140 LogText
= _DEBUG_MESSAGE_TEMPLATE
% TemplateDict
142 _DEBUG_LOGGER
.log(Level
, LogText
)
144 ## Log verbose message
146 # @param Message Verbose information
148 def Verbose(Message
):
149 return _INFO_LOGGER
.log(VERBOSE
, Message
)
151 ## Log warning message
153 # Warning messages are those which might be wrong but won't fail the tool.
155 # @param ToolName The name of the tool. If not given, the name of caller
156 # method will be used.
157 # @param Message Warning information
158 # @param File The name of file which caused the warning.
159 # @param Line The line number in the "File" which caused the warning.
160 # @param ExtraData More information associated with "Message"
162 def Warn(ToolName
, Message
, File
=None, Line
=None, ExtraData
=None):
163 if _INFO_LOGGER
.level
> WARN
:
166 # if no tool name given, use caller's source file name as tool name
168 if ToolName
is None or ToolName
== "":
169 ToolName
= os
.path
.basename(extract_stack()[-2][0])
184 LogText
= _WARNING_MESSAGE_TEMPLATE
% TemplateDict
186 LogText
= _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE
% TemplateDict
188 if ExtraData
is not None:
189 LogText
+= "\n %s" % ExtraData
191 _INFO_LOGGER
.log(WARN
, LogText
)
193 # Raise an execption if indicated
195 if GlobalData
.gWARNING_AS_ERROR
== True:
196 raise FatalError(WARNING_AS_ERROR
)
200 # Once an error messages is logged, the tool's execution will be broken by
201 # raising an execption. If you don't want to break the execution later, you
202 # can give "RaiseError" with "False" value.
204 # @param ToolName The name of the tool. If not given, the name of caller
205 # method will be used.
206 # @param ErrorCode The error code
207 # @param Message Warning information
208 # @param File The name of file which caused the error.
209 # @param Line The line number in the "File" which caused the warning.
210 # @param ExtraData More information associated with "Message"
211 # @param RaiseError Raise an exception to break the tool's executuion if
212 # it's True. This is the default behavior.
214 def Error(ToolName
, ErrorCode
, Message
=None, File
=None, Line
=None, \
215 ExtraData
=None, RaiseError
=IS_RAISE_ERROR
):
224 if ErrorCode
in gERROR_MESSAGE
:
225 Message
= gERROR_MESSAGE
[ErrorCode
]
227 Message
= gERROR_MESSAGE
[UNKNOWN_ERROR
]
229 if ExtraData
is None:
236 "errorcode" : ErrorCode
,
242 LogText
= _ERROR_MESSAGE_TEMPLATE
% TemplateDict
244 LogText
= __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE
% TemplateDict
246 if not SUPRESS_ERROR
:
247 _ERROR_LOGGER
.log(ERROR
, LogText
)
249 raise FatalError(ErrorCode
)
252 ## Initialize log system
256 # Since we use different format to log different levels of message into
257 # different place (stdout or stderr), we have to use different "Logger"
258 # objects to do this.
260 # For DEBUG level (All DEBUG_0~9 are applicable)
261 _DEBUG_LOGGER
.setLevel(INFO
)
262 _DebugChannel
= StreamHandler(stdout
)
263 _DebugChannel
.setFormatter(_DEBUG_FORMATTER
)
264 _DEBUG_LOGGER
.addHandler(_DebugChannel
)
266 # For VERBOSE, INFO, WARN level
268 _INFO_LOGGER
.setLevel(INFO
)
269 _InfoChannel
= StreamHandler(stdout
)
270 _InfoChannel
.setFormatter(_INFO_FORMATTER
)
271 _INFO_LOGGER
.addHandler(_InfoChannel
)
275 _ERROR_LOGGER
.setLevel(INFO
)
276 _ErrorCh
= StreamHandler(stderr
)
277 _ErrorCh
.setFormatter(_ERROR_FORMATTER
)
278 _ERROR_LOGGER
.addHandler(_ErrorCh
)
283 # @param Level One of log level in _LogLevel
286 if Level
not in _LOG_LEVELS
:
287 Info("Not supported log level (%d). Use default level instead." % \
290 _DEBUG_LOGGER
.setLevel(Level
)
291 _INFO_LOGGER
.setLevel(Level
)
292 _ERROR_LOGGER
.setLevel(Level
)
294 ## Get current log level
297 return _INFO_LOGGER
.getEffectiveLevel()
299 ## Raise up warning as error
301 def SetWarningAsError():
302 GlobalData
.gWARNING_AS_ERROR
= True
304 ## Specify a file to store the log message as well as put on console
306 # @param LogFile The file path used to store the log message
308 def SetLogFile(LogFile
):
309 if os
.path
.exists(LogFile
):
312 _Ch
= FileHandler(LogFile
)
313 _Ch
.setFormatter(_DEBUG_FORMATTER
)
314 _DEBUG_LOGGER
.addHandler(_Ch
)
316 _Ch
= FileHandler(LogFile
)
317 _Ch
.setFormatter(_INFO_FORMATTER
)
318 _INFO_LOGGER
.addHandler(_Ch
)
320 _Ch
= FileHandler(LogFile
)
321 _Ch
.setFormatter(_ERROR_FORMATTER
)
322 _ERROR_LOGGER
.addHandler(_Ch
)