15bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Copyright (C) 2016 The Android Open Source Project 25bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# 35bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Licensed under the Apache License, Version 2.0 (the "License"); 45bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# you may not use this file except in compliance with the License. 55bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# You may obtain a copy of the License at 65bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# 75bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# http://www.apache.org/licenses/LICENSE-2.0 85bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# 95bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# Unless required by applicable law or agreed to in writing, software 105bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# distributed under the License is distributed on an "AS IS" BASIS, 115bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 125bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# See the License for the specific language governing permissions and 135bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond# limitations under the License. 145bbcc3861c44435f89481f80946ef5c9c49968f2Luke Drummond 15dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo'''Initialise the Python logging facility for the test suite. 16dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 17a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummondfrom __future__ import absolute_import 18a3c6f62775506c95afd556e617f14d7a28839f01Luke Drummond 19dcecc0c8d22e894525e25a122ce25129b51338f2Dean De LeoIt provides the function to initialise the logging facility and retrieve an 20dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoinstance of the logger class. It also contains the definition of the internal 21dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leologger class. 22dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo''' 23dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leofrom __future__ import print_function 24dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 25dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport io 26dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport sys 27dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoimport logging 28dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 29dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 30dcecc0c8d22e894525e25a122ce25129b51338f2Dean De LeoINITIALISED = False 31dcecc0c8d22e894525e25a122ce25129b51338f2Dean De LeoNAMESPACE = 'RS_LLDB_TESTSUITE' 32dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 33dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef initialise(identifier, level=logging.INFO, print_to_stdout=False, 34dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo file_path=None, file_mode='a'): 35dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '''Initialise the logging facility for the test suite. 36dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 37dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo This function should be invoked only once, at the start of the program, and 38dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo before emitting any log. 39dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 40dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Args: 41dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo identifier: String, a label that will be part of each record. It is 42dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo usually the test case name. 43dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo level: Integer, all messages above this log level will be discarded. 44dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Valid values are those recognised by the python logging module: 45dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo https://docs.python.org/2/library/logging.html#levels . 46dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo print_to_stdout: Boolean, whether the logs should be redirected to 47dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo sys.stdout (true) or stored into a text file (false). 48dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo file_path: String, path to the text file in which to store the logs. 49dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo This option is only meaningful when print_to_stdout = False. 50dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo file_mode: String, the mode to open the text file. Valid modes are 51dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo those recognised by the standard Python `open' function. 52dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo This option is only meaningful when print_to_stdout = False. 53dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 54dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Raises: 55dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo RuntimeError: If the logging has already been initialised 56dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo ValueError: If the argument "file_path" has not been provided when 57dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo print_to_stdout=False 58dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo ''' 59dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # pylint: disable=global-statement 60dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo global INITIALISED 61dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo if INITIALISED: 62dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo raise RuntimeError('Already initialised') 63dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 64dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # set the logging class 65dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo old_logger_class = logging.getLoggerClass() 66dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo logging.setLoggerClass(RsLogger) 67dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 68dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # initialise the Logger 69dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo log = logging.getLogger(NAMESPACE) 70dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo log.setLevel(level) # reject all logs below 71dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 72dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # don't propagate the log records to the logging root 73dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo log.propagate = False 74dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 75dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # restore the previous class 76dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo logging.setLoggerClass(old_logger_class) 77dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 78dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # handler 79dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo if print_to_stdout: 80dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo handler_default = logging.StreamHandler(sys.stdout) 81dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo else: 82dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo if file_path is None: 83dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo raise ValueError('Missing mandatory argument "file_path"') 84dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 85dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo handler_default = logging.FileHandler(file_path, file_mode) 86dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 87dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # Do not filter records in the handler because of the level 88dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo handler_default.setLevel(logging.NOTSET) 89dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 90dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # format the message 91dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo handler_default.setFormatter( 92dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo logging.Formatter( 93dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '%(asctime)s [{0}] [%(levelname)s] %(message)s' 94dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo .format(identifier) 95dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo )) 96dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 97dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo log.addHandler(handler_default) 98dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 99dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo INITIALISED = True 100dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 101dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 102dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leoclass RsLogger(logging.getLoggerClass()): 103dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '''Internal logging class. 104dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 105dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo This is an internal class to enhance the logging facility with the methods 106dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo "log_and_print" and "seek_to_end". 107dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo ''' 108dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo # pylint: disable=too-many-public-methods 109dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 110dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo def log_and_print(self, msg, level=logging.INFO): 111dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '''Print "msg" to stdout and emit a log record. 112dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 113dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Args: 114dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo msg: The message to emit. 115dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo level: The level to use. By default it is logging.INFO. 116dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo ''' 117dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo print(msg) 118dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo self.log(level, msg) 119dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 120dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo def seek_to_end(self): 121dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '''Reset the cursor position to the end for all handlers that are 122dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Text File managers.''' 123dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo for hndlr in self.handlers: 124dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo if isinstance(hndlr, logging.FileHandler): 125dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo hndlr.stream.seek(0, io.SEEK_END) 126dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 127dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 128dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leodef get_logger(): 129dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo '''Retrieves the Logger instance related to the testsuite. 130dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 131dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Throws: 132dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo RuntimeError: If the logging facility has not been initialised with 133dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo "initialise" beforehand. 134dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 135dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo Returns: 136dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo An instance of logging.Logger to write the logs. 137dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo ''' 138dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo if not INITIALISED: 139dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo raise RuntimeError('Logging facility not initialised') 140dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo 141dcecc0c8d22e894525e25a122ce25129b51338f2Dean De Leo return logging.getLogger(NAMESPACE) 142