]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/EdkLogger.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / Common / EdkLogger.py
index af7707482ccb7d897bb8a7d3b18094196fb45aa3..06da4a9d0a1d0be96994d1041be6003da66fab41 100644 (file)
 # This file implements the log mechanism for Python tools.\r
 #\r
 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution.  The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved.\r
 #\r
+# Permission to use, copy, modify, and distribute this software and its\r
+# documentation for any purpose and without fee is hereby granted,\r
+# provided that the above copyright notice appear in all copies and that\r
+# both that copyright notice and this permission notice appear in\r
+# supporting documentation, and that the name of Vinay Sajip\r
+# not be used in advertising or publicity pertaining to distribution\r
+# of the software without specific, written prior permission.\r
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL\r
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER\r
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\r
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+# This copyright is for QueueHandler.\r
 \r
 ## Import modules\r
 from __future__ import absolute_import\r
 import Common.LongFilePathOs as os, sys, logging\r
 import traceback\r
 from  .BuildToolError import *\r
-\r
+try:\r
+    from logging.handlers import QueueHandler\r
+except:\r
+    class QueueHandler(logging.Handler):\r
+        """\r
+        This handler sends events to a queue. Typically, it would be used together\r
+        with a multiprocessing Queue to centralise logging to file in one process\r
+        (in a multi-process application), so as to avoid file write contention\r
+        between processes.\r
+\r
+        This code is new in Python 3.2, but this class can be copy pasted into\r
+        user code for use with earlier Python versions.\r
+        """\r
+\r
+        def __init__(self, queue):\r
+            """\r
+            Initialise an instance, using the passed queue.\r
+            """\r
+            logging.Handler.__init__(self)\r
+            self.queue = queue\r
+\r
+        def enqueue(self, record):\r
+            """\r
+            Enqueue a record.\r
+\r
+            The base implementation uses put_nowait. You may want to override\r
+            this method if you want to use blocking, timeouts or custom queue\r
+            implementations.\r
+            """\r
+            self.queue.put_nowait(record)\r
+\r
+        def prepare(self, record):\r
+            """\r
+            Prepares a record for queuing. The object returned by this method is\r
+            enqueued.\r
+\r
+            The base implementation formats the record to merge the message\r
+            and arguments, and removes unpickleable items from the record\r
+            in-place.\r
+\r
+            You might want to override this method if you want to convert\r
+            the record to a dict or JSON string, or send a modified copy\r
+            of the record while leaving the original intact.\r
+            """\r
+            # The format operation gets traceback text into record.exc_text\r
+            # (if there's exception data), and also returns the formatted\r
+            # message. We can then use this to replace the original\r
+            # msg + args, as these might be unpickleable. We also zap the\r
+            # exc_info and exc_text attributes, as they are no longer\r
+            # needed and, if not None, will typically not be pickleable.\r
+            msg = self.format(record)\r
+            record.message = msg\r
+            record.msg = msg\r
+            record.args = None\r
+            record.exc_info = None\r
+            record.exc_text = None\r
+            return record\r
+\r
+        def emit(self, record):\r
+            """\r
+            Emit a record.\r
+\r
+            Writes the LogRecord to the queue, preparing it for pickling first.\r
+            """\r
+            try:\r
+                self.enqueue(self.prepare(record))\r
+            except Exception:\r
+                self.handleError(record)\r
+class BlockQueueHandler(QueueHandler):\r
+    def enqueue(self, record):\r
+        self.queue.put(record,True)\r
 ## Log level constants\r
 DEBUG_0 = 1\r
 DEBUG_1 = 2\r
@@ -145,7 +226,7 @@ def warn(ToolName, Message, File=None, Line=None, ExtraData=None):
 \r
     _InfoLogger.log(WARN, LogText)\r
 \r
-    # Raise an execption if indicated\r
+    # Raise an exception if indicated\r
     if _WarningAsError == True:\r
         raise FatalError(WARNING_AS_ERROR)\r
 \r
@@ -155,7 +236,7 @@ info    = _InfoLogger.info
 ## Log ERROR message\r
 #\r
 #   Once an error messages is logged, the tool's execution will be broken by raising\r
-# an execption. If you don't want to break the execution later, you can give\r
+# an exception. If you don't want to break the execution later, you can give\r
 # "RaiseError" with "False" value.\r
 #\r
 #   @param  ToolName    The name of the tool. If not given, the name of caller\r
@@ -165,7 +246,7 @@ info    = _InfoLogger.info
 #   @param  File        The name of file which caused the error.\r
 #   @param  Line        The line number in the "File" which caused the warning.\r
 #   @param  ExtraData   More information associated with "Message"\r
-#   @param  RaiseError  Raise an exception to break the tool's executuion if\r
+#   @param  RaiseError  Raise an exception to break the tool's execution if\r
 #                       it's True. This is the default behavior.\r
 #\r
 def error(ToolName, ErrorCode, Message=None, File=None, Line=None, ExtraData=None, RaiseError=IsRaiseError):\r
@@ -206,26 +287,26 @@ def error(ToolName, ErrorCode, Message=None, File=None, Line=None, ExtraData=Non
 quiet   = _ErrorLogger.error\r
 \r
 ## Initialize log system\r
-def Initialize():\r
+def LogClientInitialize(log_q):\r
     #\r
     # Since we use different format to log different levels of message into different\r
     # place (stdout or stderr), we have to use different "Logger" objects to do this.\r
     #\r
     # For DEBUG level (All DEBUG_0~9 are applicable)\r
     _DebugLogger.setLevel(INFO)\r
-    _DebugChannel = logging.StreamHandler(sys.stdout)\r
+    _DebugChannel = BlockQueueHandler(log_q)\r
     _DebugChannel.setFormatter(_DebugFormatter)\r
     _DebugLogger.addHandler(_DebugChannel)\r
 \r
     # For VERBOSE, INFO, WARN level\r
     _InfoLogger.setLevel(INFO)\r
-    _InfoChannel = logging.StreamHandler(sys.stdout)\r
+    _InfoChannel = BlockQueueHandler(log_q)\r
     _InfoChannel.setFormatter(_InfoFormatter)\r
     _InfoLogger.addHandler(_InfoChannel)\r
 \r
     # For ERROR level\r
     _ErrorLogger.setLevel(INFO)\r
-    _ErrorCh = logging.StreamHandler(sys.stderr)\r
+    _ErrorCh = BlockQueueHandler(log_q)\r
     _ErrorCh.setFormatter(_ErrorFormatter)\r
     _ErrorLogger.addHandler(_ErrorCh)\r
 \r
@@ -240,6 +321,30 @@ def SetLevel(Level):
     _InfoLogger.setLevel(Level)\r
     _ErrorLogger.setLevel(Level)\r
 \r
+## Initialize log system\r
+def Initialize():\r
+    #\r
+    # Since we use different format to log different levels of message into different\r
+    # place (stdout or stderr), we have to use different "Logger" objects to do this.\r
+    #\r
+    # For DEBUG level (All DEBUG_0~9 are applicable)\r
+    _DebugLogger.setLevel(INFO)\r
+    _DebugChannel = logging.StreamHandler(sys.stdout)\r
+    _DebugChannel.setFormatter(_DebugFormatter)\r
+    _DebugLogger.addHandler(_DebugChannel)\r
+\r
+    # For VERBOSE, INFO, WARN level\r
+    _InfoLogger.setLevel(INFO)\r
+    _InfoChannel = logging.StreamHandler(sys.stdout)\r
+    _InfoChannel.setFormatter(_InfoFormatter)\r
+    _InfoLogger.addHandler(_InfoChannel)\r
+\r
+    # For ERROR level\r
+    _ErrorLogger.setLevel(INFO)\r
+    _ErrorCh = logging.StreamHandler(sys.stderr)\r
+    _ErrorCh.setFormatter(_ErrorFormatter)\r
+    _ErrorLogger.addHandler(_ErrorCh)\r
+\r
 def InitializeForUnitTest():\r
     Initialize()\r
     SetLevel(SILENT)\r