From b44a2916ba410366078fd2f8dc5ddb10b3c4e65a Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Tue, 09 Oct 2007 16:58:39 +0000 Subject: Rework sugar.logger and make activities just redirect their output to a log. --- (limited to 'sugar/logger.py') diff --git a/sugar/logger.py b/sugar/logger.py index da07dd8..bc6af85 100644 --- a/sugar/logger.py +++ b/sugar/logger.py @@ -19,105 +19,44 @@ import sys import os import logging -import traceback -from cStringIO import StringIO import time -import dbus -import dbus.service -import dbus.glib +_MAX_BACKUP_DIRS = 3 -from sugar import env - -_log_writer = None - -STDOUT_LEVEL = 1000 -STDERR_LEVEL = 2000 - -formatter = logging.Formatter('%(name)s: %(message)s') - -_LOGGER_SERVICE_NAME = "org.laptop.Logger" -_LOGGER_OBJECT_PATH = "/org/laptop/Logger" -_LOGGER_INTERFACE = "org.laptop.Logger" - -class LoggerManagerService(dbus.service.Object): - def __init__(self): - bus = dbus.SessionBus() - bus_name = dbus.service.BusName(_LOGGER_SERVICE_NAME, bus = bus) - dbus.service.Object.__init__(self, bus_name, _LOGGER_OBJECT_PATH) - - @dbus.service.method(_LOGGER_INTERFACE) - def SetLevel(self, level): - set_level(level) - -class LogWriter: - def __init__(self, module_id): - self._module_id = module_id - - logs_dir = _get_logs_dir() - log_path = os.path.join(logs_dir, module_id + '.log') - self._log_file = open(log_path, 'w') - - def write_record(self, record): - self.write(record.levelno, formatter.format(record)) - - def write(self, level, msg): - if level == logging.ERROR: - level_txt = 'ERROR' - elif level == logging.WARNING: - level_txt = 'WARNING' - elif level == logging.DEBUG: - level_txt = 'DEBUG' - elif level == logging.INFO: - level_txt = 'INFO' - elif level == STDERR_LEVEL: - level_txt = 'STDERR' - elif level == STDOUT_LEVEL: - level_txt = 'STDOUT' - - if not len(msg) or msg[len(msg) - 1] != '\n': - msg += "\n" - fmt = "%.4f %s - %s" % (time.time(), level_txt, msg) - fmt = fmt.encode("utf8") - self._log_file.write(fmt) - self._log_file.flush() - -class Handler(logging.Handler): - def __init__(self, writer): - logging.Handler.__init__(self) - - self._writer = writer - - def emit(self, record): - self._writer.write_record(record) - -class StdoutCatcher: - def write(self, txt): - _log_writer.write(STDOUT_LEVEL, txt) - sys.__stdout__.write(txt) - - def flush(self): - sys.__stderr__.flush() - -class StderrCatcher: - def write(self, txt): - _log_writer.write(STDERR_LEVEL, txt) - sys.__stderr__.write(txt) - - def flush(self): - sys.__stderr__.flush() - -def __exception_handler(typ, exc, tb): - trace = StringIO() - traceback.print_exception(typ, exc, tb, None, trace) - print >> sys.stderr, trace.getvalue() - - _log_writer.write(logging.ERROR, trace.getvalue()) - -def _get_logs_dir(): - logs_dir = os.path.join(env.get_profile_path(), 'logs') +def setup_logs_dir(): + logs_dir = get_logs_dir() if not os.path.isdir(logs_dir): os.makedirs(logs_dir) + + backup_logs = [] + backup_dirs = [] + for f in os.listdir(logs_dir): + path = os.path.join(logs_dir, f) + if os.path.isfile(path): + backup_logs.append(f) + elif os.path.isdir(path): + backup_dirs.append(path) + + if len(backup_dirs) > _MAX_BACKUP_DIRS: + backup_dirs.sort() + root = backup_dirs[0] + for f in os.listdir(root): + os.remove(os.path.join(root, f)) + os.rmdir(root) + + if len(backup_logs) > 0: + name = str(int(time.time())) + backup_dir = os.path.join(logs_dir, name) + os.mkdir(backup_dir) + for log in backup_logs: + source_path = os.path.join(logs_dir, log) + dest_path = os.path.join(backup_dir, log) + os.rename(source_path, dest_path) + +def get_logs_dir(): + profile = os.environ.get('SUGAR_PROFILE', 'default') + logs_dir = os.path.join(os.path.expanduser('~'), + '.sugar', profile, 'logs') return logs_dir def set_level(level): @@ -125,91 +64,20 @@ def set_level(level): 'warning' : logging.WARNING, 'debug' : logging.DEBUG, 'info' : logging.INFO } - root_logger = logging.getLogger('') if levels.has_key(level): - root_logger.setLevel(levels[level]) - -def start(module_id): - log_writer = LogWriter(module_id) - - root_logger = logging.getLogger('') - root_logger.setLevel(logging.ERROR) - root_logger.addHandler(Handler(log_writer)) + logging.getLogger('').setLevel(levels[level]) +def start(log_filename=None, redirect_io=True): if os.environ.has_key('SUGAR_LOGGER_LEVEL'): set_level(os.environ['SUGAR_LOGGER_LEVEL']) - sys.stdout = StdoutCatcher() - sys.stderr = StderrCatcher() - - global _log_writer - _log_writer = log_writer - sys.excepthook = __exception_handler - - service = LoggerManagerService() - -def cleanup(): - logs_dir = _get_logs_dir() + if log_filename: + log_path = os.path.join(get_logs_dir(), log_filename + '.log') + log_file = open(log_path, 'w') - # File extension for backed up logfiles. - - file_suffix = int(time.time()) - - # Absolute directory path where to store old logfiles. - # It will be created recursivly if it's not present. - - backup_dirpath = os.path.join(logs_dir, 'old') - - # How many versions shall be backed up of every logfile? - - num_backup_versions = 4 - - # Make sure the backup location for old log files exists - - if not os.path.exists(backup_dirpath): - os.makedirs(backup_dirpath) - - # Iterate over every item in 'logs' directory - - for filename in os.listdir(logs_dir): + handler = logging.StreamHandler(log_file) + logging.getLogger('').addHandler(handler) - old_filepath = os.path.join(logs_dir, filename) - - if os.path.isfile(old_filepath): - - # Backup every file - - new_filename = filename + '.' + str(file_suffix) - new_filepath = os.path.join(backup_dirpath, new_filename) - os.rename(old_filepath, new_filepath) - - backup_map = {} - - # Temporarily map all backup logfiles - - for filename in os.listdir(backup_dirpath): - - # Remove the 'file_suffix' from the filename. - - end = filename.rfind(".") - key = filename[0:end].lower() - key = key.replace(".", "_") - - if key not in backup_map: - backup_map[key] = [] - - backup_list = backup_map[key] - - backup_list.append( os.path.join(backup_dirpath, filename) ) - - # Only keep 'num_backup_versions' versions of every logfile. - # Remove the others. - - for key in backup_map: - backup_list = backup_map[key] - backup_list.sort() - backup_list.reverse() - - for i in range(num_backup_versions, len(backup_list)): - os.remove(backup_list[i]) - + if redirect_io: + os.dup2(log_file.fileno(), sys.stdout.fileno()) + os.dup2(log_file.fileno(), sys.stderr.fileno()) -- cgit v0.9.1