X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FUPT%2FLogger%2FLog.py;h=407a1b32b6eeb8f653d90623e6c834831d83d081;hp=0915bb72639c1e77f0ce706285798d5741161c1c;hb=f51461c829c124288a930829a78e2a5a799f4039;hpb=7771be9fd0b9b3c7f5c0659c416535171de31191 diff --git a/BaseTools/Source/Python/UPT/Logger/Log.py b/BaseTools/Source/Python/UPT/Logger/Log.py index 0915bb7263..407a1b32b6 100644 --- a/BaseTools/Source/Python/UPT/Logger/Log.py +++ b/BaseTools/Source/Python/UPT/Logger/Log.py @@ -1,325 +1,325 @@ -## @file -# This file implements the log mechanism for Python tools. -# -# Copyright (c) 2011, Intel Corporation. All rights reserved.
-# -# This program and the accompanying materials are licensed and made available -# under the terms and conditions of the BSD License which accompanies this -# distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# - -''' -Logger -''' - -## Import modules -from sys import argv -from sys import stdout -from sys import stderr -import os.path -from os import remove -from logging import getLogger -from logging import Formatter -from logging import StreamHandler -from logging import FileHandler -from traceback import extract_stack - -from Logger.ToolError import FatalError -from Logger.ToolError import WARNING_AS_ERROR -from Logger.ToolError import gERROR_MESSAGE -from Logger.ToolError import UNKNOWN_ERROR -from Library import GlobalData - -# -# Log level constants -# -DEBUG_0 = 1 -DEBUG_1 = 2 -DEBUG_2 = 3 -DEBUG_3 = 4 -DEBUG_4 = 5 -DEBUG_5 = 6 -DEBUG_6 = 7 -DEBUG_7 = 8 -DEBUG_8 = 9 -DEBUG_9 = 10 -VERBOSE = 15 -INFO = 20 -WARN = 30 -QUIET = 40 -QUIET_1 = 41 -ERROR = 50 -SILENT = 60 - -IS_RAISE_ERROR = True -SUPRESS_ERROR = False - -# -# Tool name -# -_TOOL_NAME = os.path.basename(argv[0]) -# -# For validation purpose -# -_LOG_LEVELS = [DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, \ - DEBUG_7, DEBUG_8, DEBUG_9, VERBOSE, WARN, INFO, ERROR, QUIET, \ - QUIET_1, SILENT] -# -# For DEBUG level (All DEBUG_0~9 are applicable) -# -_DEBUG_LOGGER = getLogger("tool_debug") -_DEBUG_FORMATTER = Formatter("[%(asctime)s.%(msecs)d]: %(message)s", \ - datefmt="%H:%M:%S") -# -# For VERBOSE, INFO, WARN level -# -_INFO_LOGGER = getLogger("tool_info") -_INFO_FORMATTER = Formatter("%(message)s") -# -# For ERROR level -# -_ERROR_LOGGER = getLogger("tool_error") -_ERROR_FORMATTER = Formatter("%(message)s") - -# -# String templates for ERROR/WARN/DEBUG log message -# -_ERROR_MESSAGE_TEMPLATE = \ -('\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s') - -__ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE = \ -'\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s' - -_WARNING_MESSAGE_TEMPLATE = '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s' -_WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE = '%(tool)s: : warning: %(msg)s' -_DEBUG_MESSAGE_TEMPLATE = '%(file)s(%(line)s): debug: \n %(msg)s' - - -# -# Log INFO message -# -#Info = _INFO_LOGGER.info - -def Info(msg, *args, **kwargs): - _INFO_LOGGER.info(msg, *args, **kwargs) - -# -# Log information which should be always put out -# -def Quiet(msg, *args, **kwargs): - _ERROR_LOGGER.error(msg, *args, **kwargs) - -## Log debug message -# -# @param Level DEBUG level (DEBUG0~9) -# @param Message Debug information -# @param ExtraData More information associated with "Message" -# -def Debug(Level, Message, ExtraData=None): - if _DEBUG_LOGGER.level > Level: - return - if Level > DEBUG_9: - return - # - # Find out the caller method information - # - CallerStack = extract_stack()[-2] - TemplateDict = { - "file" : CallerStack[0], - "line" : CallerStack[1], - "msg" : Message, - } - - if ExtraData != None: - LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + "\n %s" % ExtraData - else: - LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict - - _DEBUG_LOGGER.log(Level, LogText) - -## Log verbose message -# -# @param Message Verbose information -# -def Verbose(Message): - return _INFO_LOGGER.log(VERBOSE, Message) - -## Log warning message -# -# Warning messages are those which might be wrong but won't fail the tool. -# -# @param ToolName The name of the tool. If not given, the name of caller -# method will be used. -# @param Message Warning information -# @param File The name of file which caused the warning. -# @param Line The line number in the "File" which caused the warning. -# @param ExtraData More information associated with "Message" -# -def Warn(ToolName, Message, File=None, Line=None, ExtraData=None): - if _INFO_LOGGER.level > WARN: - return - # - # if no tool name given, use caller's source file name as tool name - # - if ToolName == None or ToolName == "": - ToolName = os.path.basename(extract_stack()[-2][0]) - - if Line == None: - Line = "..." - else: - Line = "%d" % Line - - TemplateDict = { - "tool" : ToolName, - "file" : File, - "line" : Line, - "msg" : Message, - } - - if File != None: - LogText = _WARNING_MESSAGE_TEMPLATE % TemplateDict - else: - LogText = _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict - - if ExtraData != None: - LogText += "\n %s" % ExtraData - - _INFO_LOGGER.log(WARN, LogText) - # - # Raise an execption if indicated - # - if GlobalData.gWARNING_AS_ERROR == True: - raise FatalError(WARNING_AS_ERROR) - -## Log ERROR message -# -# Once an error messages is logged, the tool's execution will be broken by -# raising an execption. If you don't want to break the execution later, you -# can give "RaiseError" with "False" value. -# -# @param ToolName The name of the tool. If not given, the name of caller -# method will be used. -# @param ErrorCode The error code -# @param Message Warning information -# @param File The name of file which caused the error. -# @param Line The line number in the "File" which caused the warning. -# @param ExtraData More information associated with "Message" -# @param RaiseError Raise an exception to break the tool's executuion if -# it's True. This is the default behavior. -# -def Error(ToolName, ErrorCode, Message=None, File=None, Line=None, \ - ExtraData=None, RaiseError=IS_RAISE_ERROR): - if ToolName: - pass - if Line == None: - Line = "..." - else: - Line = "%d" % Line - - if Message == None: - if ErrorCode in gERROR_MESSAGE: - Message = gERROR_MESSAGE[ErrorCode] - else: - Message = gERROR_MESSAGE[UNKNOWN_ERROR] - - if ExtraData == None: - ExtraData = "" - - TemplateDict = { - "tool" : _TOOL_NAME, - "file" : File, - "line" : Line, - "errorcode" : ErrorCode, - "msg" : Message, - "extra" : ExtraData - } - - if File != None: - LogText = _ERROR_MESSAGE_TEMPLATE % TemplateDict - else: - LogText = __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict - - if not SUPRESS_ERROR: - _ERROR_LOGGER.log(ERROR, LogText) - if RaiseError: - raise FatalError(ErrorCode) - - -## Initialize log system -# -def Initialize(): - # - # Since we use different format to log different levels of message into - # different place (stdout or stderr), we have to use different "Logger" - # objects to do this. - # - # For DEBUG level (All DEBUG_0~9 are applicable) - _DEBUG_LOGGER.setLevel(INFO) - _DebugChannel = StreamHandler(stdout) - _DebugChannel.setFormatter(_DEBUG_FORMATTER) - _DEBUG_LOGGER.addHandler(_DebugChannel) - # - # For VERBOSE, INFO, WARN level - # - _INFO_LOGGER.setLevel(INFO) - _InfoChannel = StreamHandler(stdout) - _InfoChannel.setFormatter(_INFO_FORMATTER) - _INFO_LOGGER.addHandler(_InfoChannel) - # - # For ERROR level - # - _ERROR_LOGGER.setLevel(INFO) - _ErrorCh = StreamHandler(stderr) - _ErrorCh.setFormatter(_ERROR_FORMATTER) - _ERROR_LOGGER.addHandler(_ErrorCh) - - -## Set log level -# -# @param Level One of log level in _LogLevel -# -def SetLevel(Level): - if Level not in _LOG_LEVELS: - Info("Not supported log level (%d). Use default level instead." % \ - Level) - Level = INFO - _DEBUG_LOGGER.setLevel(Level) - _INFO_LOGGER.setLevel(Level) - _ERROR_LOGGER.setLevel(Level) - -## Get current log level -# -def GetLevel(): - return _INFO_LOGGER.getEffectiveLevel() - -## Raise up warning as error -# -def SetWarningAsError(): - GlobalData.gWARNING_AS_ERROR = True - -## Specify a file to store the log message as well as put on console -# -# @param LogFile The file path used to store the log message -# -def SetLogFile(LogFile): - if os.path.exists(LogFile): - remove(LogFile) - - _Ch = FileHandler(LogFile) - _Ch.setFormatter(_DEBUG_FORMATTER) - _DEBUG_LOGGER.addHandler(_Ch) - - _Ch = FileHandler(LogFile) - _Ch.setFormatter(_INFO_FORMATTER) - _INFO_LOGGER.addHandler(_Ch) - - _Ch = FileHandler(LogFile) - _Ch.setFormatter(_ERROR_FORMATTER) - _ERROR_LOGGER.addHandler(_Ch) - - - +## @file +# This file implements the log mechanism for Python tools. +# +# Copyright (c) 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +''' +Logger +''' + +## Import modules +from sys import argv +from sys import stdout +from sys import stderr +import os.path +from os import remove +from logging import getLogger +from logging import Formatter +from logging import StreamHandler +from logging import FileHandler +from traceback import extract_stack + +from Logger.ToolError import FatalError +from Logger.ToolError import WARNING_AS_ERROR +from Logger.ToolError import gERROR_MESSAGE +from Logger.ToolError import UNKNOWN_ERROR +from Library import GlobalData + +# +# Log level constants +# +DEBUG_0 = 1 +DEBUG_1 = 2 +DEBUG_2 = 3 +DEBUG_3 = 4 +DEBUG_4 = 5 +DEBUG_5 = 6 +DEBUG_6 = 7 +DEBUG_7 = 8 +DEBUG_8 = 9 +DEBUG_9 = 10 +VERBOSE = 15 +INFO = 20 +WARN = 30 +QUIET = 40 +QUIET_1 = 41 +ERROR = 50 +SILENT = 60 + +IS_RAISE_ERROR = True +SUPRESS_ERROR = False + +# +# Tool name +# +_TOOL_NAME = os.path.basename(argv[0]) +# +# For validation purpose +# +_LOG_LEVELS = [DEBUG_0, DEBUG_1, DEBUG_2, DEBUG_3, DEBUG_4, DEBUG_5, DEBUG_6, \ + DEBUG_7, DEBUG_8, DEBUG_9, VERBOSE, WARN, INFO, ERROR, QUIET, \ + QUIET_1, SILENT] +# +# For DEBUG level (All DEBUG_0~9 are applicable) +# +_DEBUG_LOGGER = getLogger("tool_debug") +_DEBUG_FORMATTER = Formatter("[%(asctime)s.%(msecs)d]: %(message)s", \ + datefmt="%H:%M:%S") +# +# For VERBOSE, INFO, WARN level +# +_INFO_LOGGER = getLogger("tool_info") +_INFO_FORMATTER = Formatter("%(message)s") +# +# For ERROR level +# +_ERROR_LOGGER = getLogger("tool_error") +_ERROR_FORMATTER = Formatter("%(message)s") + +# +# String templates for ERROR/WARN/DEBUG log message +# +_ERROR_MESSAGE_TEMPLATE = \ +('\n\n%(tool)s...\n%(file)s(%(line)s): error %(errorcode)04X: %(msg)s\n\t%(extra)s') + +__ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE = \ +'\n\n%(tool)s...\n : error %(errorcode)04X: %(msg)s\n\t%(extra)s' + +_WARNING_MESSAGE_TEMPLATE = '%(tool)s...\n%(file)s(%(line)s): warning: %(msg)s' +_WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE = '%(tool)s: : warning: %(msg)s' +_DEBUG_MESSAGE_TEMPLATE = '%(file)s(%(line)s): debug: \n %(msg)s' + + +# +# Log INFO message +# +#Info = _INFO_LOGGER.info + +def Info(msg, *args, **kwargs): + _INFO_LOGGER.info(msg, *args, **kwargs) + +# +# Log information which should be always put out +# +def Quiet(msg, *args, **kwargs): + _ERROR_LOGGER.error(msg, *args, **kwargs) + +## Log debug message +# +# @param Level DEBUG level (DEBUG0~9) +# @param Message Debug information +# @param ExtraData More information associated with "Message" +# +def Debug(Level, Message, ExtraData=None): + if _DEBUG_LOGGER.level > Level: + return + if Level > DEBUG_9: + return + # + # Find out the caller method information + # + CallerStack = extract_stack()[-2] + TemplateDict = { + "file" : CallerStack[0], + "line" : CallerStack[1], + "msg" : Message, + } + + if ExtraData != None: + LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + "\n %s" % ExtraData + else: + LogText = _DEBUG_MESSAGE_TEMPLATE % TemplateDict + + _DEBUG_LOGGER.log(Level, LogText) + +## Log verbose message +# +# @param Message Verbose information +# +def Verbose(Message): + return _INFO_LOGGER.log(VERBOSE, Message) + +## Log warning message +# +# Warning messages are those which might be wrong but won't fail the tool. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param Message Warning information +# @param File The name of file which caused the warning. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# +def Warn(ToolName, Message, File=None, Line=None, ExtraData=None): + if _INFO_LOGGER.level > WARN: + return + # + # if no tool name given, use caller's source file name as tool name + # + if ToolName == None or ToolName == "": + ToolName = os.path.basename(extract_stack()[-2][0]) + + if Line == None: + Line = "..." + else: + Line = "%d" % Line + + TemplateDict = { + "tool" : ToolName, + "file" : File, + "line" : Line, + "msg" : Message, + } + + if File != None: + LogText = _WARNING_MESSAGE_TEMPLATE % TemplateDict + else: + LogText = _WARNING_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict + + if ExtraData != None: + LogText += "\n %s" % ExtraData + + _INFO_LOGGER.log(WARN, LogText) + # + # Raise an execption if indicated + # + if GlobalData.gWARNING_AS_ERROR == True: + raise FatalError(WARNING_AS_ERROR) + +## Log ERROR message +# +# Once an error messages is logged, the tool's execution will be broken by +# raising an execption. If you don't want to break the execution later, you +# can give "RaiseError" with "False" value. +# +# @param ToolName The name of the tool. If not given, the name of caller +# method will be used. +# @param ErrorCode The error code +# @param Message Warning information +# @param File The name of file which caused the error. +# @param Line The line number in the "File" which caused the warning. +# @param ExtraData More information associated with "Message" +# @param RaiseError Raise an exception to break the tool's executuion if +# it's True. This is the default behavior. +# +def Error(ToolName, ErrorCode, Message=None, File=None, Line=None, \ + ExtraData=None, RaiseError=IS_RAISE_ERROR): + if ToolName: + pass + if Line == None: + Line = "..." + else: + Line = "%d" % Line + + if Message == None: + if ErrorCode in gERROR_MESSAGE: + Message = gERROR_MESSAGE[ErrorCode] + else: + Message = gERROR_MESSAGE[UNKNOWN_ERROR] + + if ExtraData == None: + ExtraData = "" + + TemplateDict = { + "tool" : _TOOL_NAME, + "file" : File, + "line" : Line, + "errorcode" : ErrorCode, + "msg" : Message, + "extra" : ExtraData + } + + if File != None: + LogText = _ERROR_MESSAGE_TEMPLATE % TemplateDict + else: + LogText = __ERROR_MESSAGE_TEMPLATE_WITHOUT_FILE % TemplateDict + + if not SUPRESS_ERROR: + _ERROR_LOGGER.log(ERROR, LogText) + if RaiseError: + raise FatalError(ErrorCode) + + +## Initialize log system +# +def Initialize(): + # + # Since we use different format to log different levels of message into + # different place (stdout or stderr), we have to use different "Logger" + # objects to do this. + # + # For DEBUG level (All DEBUG_0~9 are applicable) + _DEBUG_LOGGER.setLevel(INFO) + _DebugChannel = StreamHandler(stdout) + _DebugChannel.setFormatter(_DEBUG_FORMATTER) + _DEBUG_LOGGER.addHandler(_DebugChannel) + # + # For VERBOSE, INFO, WARN level + # + _INFO_LOGGER.setLevel(INFO) + _InfoChannel = StreamHandler(stdout) + _InfoChannel.setFormatter(_INFO_FORMATTER) + _INFO_LOGGER.addHandler(_InfoChannel) + # + # For ERROR level + # + _ERROR_LOGGER.setLevel(INFO) + _ErrorCh = StreamHandler(stderr) + _ErrorCh.setFormatter(_ERROR_FORMATTER) + _ERROR_LOGGER.addHandler(_ErrorCh) + + +## Set log level +# +# @param Level One of log level in _LogLevel +# +def SetLevel(Level): + if Level not in _LOG_LEVELS: + Info("Not supported log level (%d). Use default level instead." % \ + Level) + Level = INFO + _DEBUG_LOGGER.setLevel(Level) + _INFO_LOGGER.setLevel(Level) + _ERROR_LOGGER.setLevel(Level) + +## Get current log level +# +def GetLevel(): + return _INFO_LOGGER.getEffectiveLevel() + +## Raise up warning as error +# +def SetWarningAsError(): + GlobalData.gWARNING_AS_ERROR = True + +## Specify a file to store the log message as well as put on console +# +# @param LogFile The file path used to store the log message +# +def SetLogFile(LogFile): + if os.path.exists(LogFile): + remove(LogFile) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_DEBUG_FORMATTER) + _DEBUG_LOGGER.addHandler(_Ch) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_INFO_FORMATTER) + _INFO_LOGGER.addHandler(_Ch) + + _Ch = FileHandler(LogFile) + _Ch.setFormatter(_ERROR_FORMATTER) + _ERROR_LOGGER.addHandler(_Ch) + + +