From patchwork Tue Nov 29 05:33:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 17903 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 946ADBE08B for ; Tue, 29 Nov 2022 05:33:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4F6B063340; Tue, 29 Nov 2022 06:33:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1669700022; bh=qPIrXBTslCt+3tRVlHHq45B+cuJZlab0foFAbM2+WG4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=WwGHlSBEWtE5R0/GrxjX6IHs/N9G3F8Yvn5GPa6i1Q1HJbZ8pYeYuJlior/3qPOYm pWvWAyvdYNe1KOvTftl8DfS9ZgKdd79137HYkWhkSh/wJwDfv3ewiSBtImmRFW7A7U ZvarCZocmdRPtYzDUFaiMvJ5bH1VBCQ8NKDAqCx3aBaIArvAa3qXftmnV0L1DDfHXm dcq2ccLZ48ltaHCa+zk8DMZdLt8Ct/ikgAdsr4oiWPspMZh73u/bWXZn24PjHOdVTj wHb0RnACHP4MokVbLX2EXzHDSyk1/geLxgp5ToaOx5mB2OjEQnHPHKj+IAYEIPY2zn KROTp0FNI8EvQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FA7A6333A for ; Tue, 29 Nov 2022 06:33:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="IUMGirjz"; dkim-atps=neutral Received: from pyrite.tail37cf.ts.net (h175-177-042-159.catv02.itscom.jp [175.177.42.159]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 583937F8; Tue, 29 Nov 2022 06:33:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1669700018; bh=qPIrXBTslCt+3tRVlHHq45B+cuJZlab0foFAbM2+WG4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IUMGirjzq85c9DF4fLmZg2KtComaQjaINFxDOlLeUdYiFoTj/+NQTsvZJ/BGPs9iW ylybGJsF50Vo9STYMT2Wu3ogS+px+jJPUdjYPLfTgQ1V0+zfLTNHEHRhf/nXkiUFR4 aVUsC7EGXlC4QvLWKsBFJ8MYZ8UhxNp0nt7vf++k= To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Nov 2022 14:33:24 +0900 Message-Id: <20221129053326.2858347-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221129053326.2858347-1-paul.elder@ideasonboard.com> References: <20221129053326.2858347-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/3] utils: libtuning: Add logger X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paul Elder via libcamera-devel From: Paul Elder Reply-To: Paul Elder Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add logging infrastructure, so that log levels and files can be set, and so that information can be logged from anywhere in libtuning easily and concicely. Signed-off-by: Paul Elder --- utils/tuning/libtuning/__init__.py | 1 + utils/tuning/libtuning/logger.py | 105 +++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 utils/tuning/libtuning/logger.py diff --git a/utils/tuning/libtuning/__init__.py b/utils/tuning/libtuning/__init__.py index 93049976..5f0478ae 100644 --- a/utils/tuning/libtuning/__init__.py +++ b/utils/tuning/libtuning/__init__.py @@ -2,6 +2,7 @@ # # Copyright (C) 2022, Paul Elder +from libtuning.logger import * from libtuning.utils import * from libtuning.libtuning import * diff --git a/utils/tuning/libtuning/logger.py b/utils/tuning/libtuning/logger.py new file mode 100644 index 00000000..03b5e1e6 --- /dev/null +++ b/utils/tuning/libtuning/logger.py @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2022, Paul Elder +# +# logger.py - Logging for libtuning + + +import datetime +from enum import IntEnum +from inspect import currentframe, getframeinfo +import math +from pathlib import Path +import psutil +import sys +import time + + +class Logger(object): + class Level(IntEnum): + Debug = 0 + Info = 1 + Warn = 2 + Error = 3 + Fatal = 4 + + level_map = { + Level.Debug: 'DEBUG', + Level.Info: 'INFO', + Level.Warn: 'WARN', + Level.Error: 'ERROR', + Level.Fatal: 'FATAL', + } + + log_levels = {} + log_level = Level.Info + log_file = sys.stderr + + # @brief Set the log levels from the command line argument + # @param argstr String of log levels from cli argument, may be empty + def set_log_levels(argstr): + if argstr == '': + return + + strings = argstr.split(',') + if len(strings) == 1 and strings[0].isnumeric(): + Logger.log_level = int(strings[0]) + return + + pairs = [pair.split('=') for pair in strings] + Logger.log_levels = {pair[0]: int(pair[1]) for pair in pairs} + + if '*' in Logger.log_levels: + Logger.log_level = Logger.log_levels['*'] + + # @brief Get the time since boot in the format HH:MM:SS.SSSSSSSSS + def get_and_convert_timestamp(): + day_mult = 24 * 60 * 60 + hour_mult = 60 * 60 + + seconds = time.time() - psutil.boot_time() + days = seconds // day_mult + hours = (seconds - (days * day_mult)) // hour_mult + hours += days * 24 + mins = (seconds - (hours * hour_mult)) // 60 + secs = (seconds - (hours * hour_mult)) % 60 + ns, s = math.modf(secs) + + return f'{int(hours)}:{int(mins):02}:{int(s):02}.{int(ns * 10**9):09}' + + # @brief Log a message + # @param obj The object instance that wants to log, or a string to use as + # component name if the caller is not an object instance + # @param level Log level + # @param msg String to log + # @param from_helper True if called from Logger's log_* helpers, False otherwise + def log(obj, level: Level, msg: str, from_helper=False): + if from_helper: + frameinfo = getframeinfo(currentframe().f_back.f_back) + else: + frameinfo = getframeinfo(currentframe().f_back) + + ts = Logger.get_and_convert_timestamp() + if isinstance(obj, str): + name = obj + else: + name = obj.__class__.__name__ + + if (name in Logger.log_levels and level >= Logger.log_levels[name]) or \ + level >= Logger.log_level: + print(f'[{ts}] {Logger.level_map[level]} {name} {Path(frameinfo.filename).name}:{frameinfo.lineno} {msg}', file=Logger.log_file) + + def log_debug(obj, msg: str): + Logger.log(obj, Logger.Level.Debug, msg, True) + + def log_info(obj, msg: str): + Logger.log(obj, Logger.Level.Info, msg, True) + + def log_warn(obj, msg: str): + Logger.log(obj, Logger.Level.Warn, msg, True) + + def log_error(obj, msg: str): + Logger.log(obj, Logger.Level.Error, msg, True) + + def log_fatal(obj, msg: str): + Logger.log(obj, Logger.Level.Fatal, msg, True)