2 # This file implements the log mechanism for Python tools.
4 # Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 from __future__
import absolute_import
16 import Common
.LongFilePathOs
as os
, sys
, logging
18 from .BuildToolError
import *
20 ## Log level constants
41 _ToolName
= os
.path
.basename(sys
.argv
[0])
43 # For validation purpose
44 _LogLevels
= [DEBUG_0
, DEBUG_1
, DEBUG_2
, DEBUG_3
, DEBUG_4
, DEBUG_5
,
45 DEBUG_6
, DEBUG_7
, DEBUG_8
, DEBUG_9
, VERBOSE
, WARN
, INFO
,
48 # For DEBUG level (All DEBUG_0~9 are applicable)
49 _DebugLogger
= logging
.getLogger("tool_debug")
50 _DebugFormatter
= logging
.Formatter("[%(asctime)s.%(msecs)d]: %(message)s", datefmt
="%H:%M:%S")
52 # For VERBOSE, INFO, WARN level
53 _InfoLogger
= logging
.getLogger("tool_info")
54 _InfoFormatter
= logging
.Formatter("%(message)s")
57 _ErrorLogger
= logging
.getLogger("tool_error")
58 _ErrorFormatter
= logging
.Formatter("%(message)s")
60 # String templates for ERROR/WARN/DEBUG log message
61 _ErrorMessageTemplate
= '\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s'
62 _ErrorMessageTemplateWithoutFile
= '\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s'
63 _WarningMessageTemplate
= '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s'
64 _WarningMessageTemplateWithoutFile
= '%(tool)s: : warning: %(msg)s'
65 _DebugMessageTemplate
= '%(file)s(%(line)s): debug: \n %(msg)s'
68 # Flag used to take WARN as ERROR.
69 # By default, only ERROR message will break the tools execution.
71 _WarningAsError
= False
75 # @param Level DEBUG level (DEBUG0~9)
76 # @param Message Debug information
77 # @param ExtraData More information associated with "Message"
79 def debug(Level
, Message
, ExtraData
=None):
80 if _DebugLogger
.level
> Level
:
85 # Find out the caller method information
86 CallerStack
= traceback
.extract_stack()[-2]
88 "file" : CallerStack
[0],
89 "line" : CallerStack
[1],
93 if ExtraData
is not None:
94 LogText
= _DebugMessageTemplate
% TemplateDict
+ "\n %s" % ExtraData
96 LogText
= _DebugMessageTemplate
% TemplateDict
98 _DebugLogger
.log(Level
, LogText
)
100 ## Log verbose message
102 # @param Message Verbose information
104 def verbose(Message
):
105 return _InfoLogger
.log(VERBOSE
, Message
)
107 ## Log warning message
109 # Warning messages are those which might be wrong but won't fail the tool.
111 # @param ToolName The name of the tool. If not given, the name of caller
112 # method will be used.
113 # @param Message Warning information
114 # @param File The name of file which caused the warning.
115 # @param Line The line number in the "File" which caused the warning.
116 # @param ExtraData More information associated with "Message"
118 def warn(ToolName
, Message
, File
=None, Line
=None, ExtraData
=None):
119 if _InfoLogger
.level
> WARN
:
122 # if no tool name given, use caller's source file name as tool name
123 if ToolName
is None or ToolName
== "":
124 ToolName
= os
.path
.basename(traceback
.extract_stack()[-2][0])
139 LogText
= _WarningMessageTemplate
% TemplateDict
141 LogText
= _WarningMessageTemplateWithoutFile
% TemplateDict
143 if ExtraData
is not None:
144 LogText
+= "\n %s" % ExtraData
146 _InfoLogger
.log(WARN
, LogText
)
148 # Raise an execption if indicated
149 if _WarningAsError
== True:
150 raise FatalError(WARNING_AS_ERROR
)
153 info
= _InfoLogger
.info
157 # Once an error messages is logged, the tool's execution will be broken by raising
158 # an execption. If you don't want to break the execution later, you can give
159 # "RaiseError" with "False" value.
161 # @param ToolName The name of the tool. If not given, the name of caller
162 # method will be used.
163 # @param ErrorCode The error code
164 # @param Message Warning information
165 # @param File The name of file which caused the error.
166 # @param Line The line number in the "File" which caused the warning.
167 # @param ExtraData More information associated with "Message"
168 # @param RaiseError Raise an exception to break the tool's executuion if
169 # it's True. This is the default behavior.
171 def error(ToolName
, ErrorCode
, Message
=None, File
=None, Line
=None, ExtraData
=None, RaiseError
=IsRaiseError
):
178 if ErrorCode
in gErrorMessage
:
179 Message
= gErrorMessage
[ErrorCode
]
181 Message
= gErrorMessage
[UNKNOWN_ERROR
]
183 if ExtraData
is None:
190 "errorcode" : ErrorCode
,
196 LogText
= _ErrorMessageTemplate
% TemplateDict
198 LogText
= _ErrorMessageTemplateWithoutFile
% TemplateDict
200 _ErrorLogger
.log(ERROR
, LogText
)
202 raise FatalError(ErrorCode
)
204 # Log information which should be always put out
205 quiet
= _ErrorLogger
.error
207 ## Initialize log system
210 # Since we use different format to log different levels of message into different
211 # place (stdout or stderr), we have to use different "Logger" objects to do this.
213 # For DEBUG level (All DEBUG_0~9 are applicable)
214 _DebugLogger
.setLevel(INFO
)
215 _DebugChannel
= logging
.StreamHandler(sys
.stdout
)
216 _DebugChannel
.setFormatter(_DebugFormatter
)
217 _DebugLogger
.addHandler(_DebugChannel
)
219 # For VERBOSE, INFO, WARN level
220 _InfoLogger
.setLevel(INFO
)
221 _InfoChannel
= logging
.StreamHandler(sys
.stdout
)
222 _InfoChannel
.setFormatter(_InfoFormatter
)
223 _InfoLogger
.addHandler(_InfoChannel
)
226 _ErrorLogger
.setLevel(INFO
)
227 _ErrorCh
= logging
.StreamHandler(sys
.stderr
)
228 _ErrorCh
.setFormatter(_ErrorFormatter
)
229 _ErrorLogger
.addHandler(_ErrorCh
)
233 # @param Level One of log level in _LogLevel
235 if Level
not in _LogLevels
:
236 info("Not supported log level (%d). Use default level instead." % Level
)
238 _DebugLogger
.setLevel(Level
)
239 _InfoLogger
.setLevel(Level
)
240 _ErrorLogger
.setLevel(Level
)
242 def InitializeForUnitTest():
246 ## Get current log level
248 return _InfoLogger
.getEffectiveLevel()
250 ## Raise up warning as error
251 def SetWarningAsError():
252 global _WarningAsError
253 _WarningAsError
= True
255 ## Specify a file to store the log message as well as put on console
257 # @param LogFile The file path used to store the log message
259 def SetLogFile(LogFile
):
260 if os
.path
.exists(LogFile
):
263 _Ch
= logging
.FileHandler(LogFile
)
264 _Ch
.setFormatter(_DebugFormatter
)
265 _DebugLogger
.addHandler(_Ch
)
267 _Ch
= logging
.FileHandler(LogFile
)
268 _Ch
.setFormatter(_InfoFormatter
)
269 _InfoLogger
.addHandler(_Ch
)
271 _Ch
= logging
.FileHandler(LogFile
)
272 _Ch
.setFormatter(_ErrorFormatter
)
273 _ErrorLogger
.addHandler(_Ch
)
275 if __name__
== '__main__':