1#!/usr/bin/env python3 2# 3# Copyright 2016 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import datetime 18import inspect 19import logging 20import os 21import xml.etree.cElementTree as et 22 23 24class TraceLogger(object): 25 def __init__(self, logger): 26 self._logger = logger 27 28 @staticmethod 29 def _get_trace_info(level=1, offset=2): 30 # We want the stack frame above this and above the error/warning/info 31 inspect_stack = inspect.stack() 32 trace_info = '' 33 for i in range(level): 34 try: 35 stack_frames = inspect_stack[offset + i] 36 info = inspect.getframeinfo(stack_frames[0]) 37 trace_info = '%s[%s:%s:%s]' % (trace_info, 38 os.path.basename(info.filename), 39 info.function, info.lineno) 40 except IndexError: 41 break 42 return trace_info 43 44 def _log_with(self, logging_lambda, trace_level, msg, *args, **kwargs): 45 trace_info = TraceLogger._get_trace_info(level=trace_level, offset=3) 46 logging_lambda('%s %s' % (msg, trace_info), *args, **kwargs) 47 48 def exception(self, msg, *args, **kwargs): 49 self._log_with(self._logger.exception, 5, msg, *args, **kwargs) 50 51 def debug(self, msg, *args, **kwargs): 52 self._log_with(self._logger.debug, 3, msg, *args, **kwargs) 53 54 def error(self, msg, *args, **kwargs): 55 self._log_with(self._logger.error, 3, msg, *args, **kwargs) 56 57 def warn(self, msg, *args, **kwargs): 58 self._log_with(self._logger.warn, 3, msg, *args, **kwargs) 59 60 def warning(self, msg, *args, **kwargs): 61 self._log_with(self._logger.warning, 3, msg, *args, **kwargs) 62 63 def info(self, msg, *args, **kwargs): 64 self._log_with(self._logger.info, 1, msg, *args, **kwargs) 65 66 def __getattr__(self, name): 67 return getattr(self._logger, name) 68 69 70class TakoTraceLogger(TraceLogger): 71 def __init__(self, *args, **kwargs): 72 super().__init__(*args, **kwargs) 73 self.d = self.debug 74 self.e = self.error 75 self.i = self.info 76 self.t = self.step 77 self.w = self.warning 78 79 def _logger_level(self, level_name): 80 level = logging.getLevelName(level_name) 81 return lambda *args, **kwargs: self._logger.log(level, *args, **kwargs) 82 83 def step(self, msg, *args, **kwargs): 84 """Delegate a step call to the underlying logger.""" 85 self._log_with(self._logger_level('STEP'), 1, msg, *args, **kwargs) 86 87 def device(self, msg, *args, **kwargs): 88 """Delegate a device call to the underlying logger.""" 89 self._log_with(self._logger_level('DEVICE'), 1, msg, *args, **kwargs) 90 91 def suite(self, msg, *args, **kwargs): 92 """Delegate a device call to the underlying logger.""" 93 self._log_with(self._logger_level('SUITE'), 1, msg, *args, **kwargs) 94 95 def case(self, msg, *args, **kwargs): 96 """Delegate a case call to the underlying logger.""" 97 self._log_with(self._logger_level('CASE'), 1, msg, *args, **kwargs) 98 99 def flush_log(self): 100 """This function exists for compatibility with Tako's logserial module. 101 102 Note that flushing the log is handled automatically by python's logging 103 module. 104 """ 105 pass 106