76d3e78302
All logfiles will be backed up to ~./sugar/default/logs/old . You can adjust the backup directory and the number of backup versions. You can also adjust the file suffix for the backup files. Konrad Kleine
173 lines
5.2 KiB
Python
173 lines
5.2 KiB
Python
"""Logging module configuration for Sugar"""
|
|
# Copyright (C) 2006, Red Hat, Inc.
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2 of the License, or (at your option) any later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the
|
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
# Boston, MA 02111-1307, USA.
|
|
|
|
import sys
|
|
import os
|
|
import logging
|
|
import traceback
|
|
from cStringIO import StringIO
|
|
import time
|
|
|
|
from sugar import env
|
|
|
|
_log_writer = None
|
|
|
|
STDOUT_LEVEL = 1000
|
|
STDERR_LEVEL = 2000
|
|
|
|
formatter = logging.Formatter('%(name)s: %(message)s')
|
|
|
|
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 msg[len(msg) - 1] != '\n':
|
|
msg += "\n"
|
|
fmt = "%s - %s" % (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)
|
|
|
|
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')
|
|
if not os.path.isdir(logs_dir):
|
|
os.makedirs(logs_dir)
|
|
return logs_dir
|
|
|
|
def start(module_id):
|
|
log_writer = LogWriter(module_id)
|
|
|
|
root_logger = logging.getLogger('')
|
|
root_logger.setLevel(logging.DEBUG)
|
|
root_logger.addHandler(Handler(log_writer))
|
|
|
|
sys.stdout = StdoutCatcher()
|
|
sys.stderr = StderrCatcher()
|
|
|
|
global _log_writer
|
|
_log_writer = log_writer
|
|
sys.excepthook = __exception_handler
|
|
|
|
def cleanup():
|
|
logs_dir = _get_logs_dir()
|
|
|
|
#---------------------------------------------------------
|
|
# Configure logfile backups
|
|
#---------------------------------------------------------
|
|
# 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):
|
|
|
|
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 = {}
|
|
|
|
# Tempoarily 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) )
|
|
|
|
print backup_map
|
|
|
|
# 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])
|
|
|