From 20da832ec8482511fd93b67982be6c82c2bd390b Mon Sep 17 00:00:00 2001 From: Benjamin Bach Date: Tue, 18 Apr 2017 17:11:00 +0200 Subject: [PATCH] Add log rotation for 30 days - fixes #4890 --- docs/developer_docs/logging.rst | 10 ++++++++- docs/faq.rst | 12 ++++++++++ docs/installguide/release_notes.rst | 6 +++++ kalite/cli.py | 12 +++++----- kalite/settings/base.py | 35 ++++++++++++++++++++++------- 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/docs/developer_docs/logging.rst b/docs/developer_docs/logging.rst index 7e25b1834e..b29c9dd947 100644 --- a/docs/developer_docs/logging.rst +++ b/docs/developer_docs/logging.rst @@ -1,8 +1,16 @@ Logging ======= +KA Lite application logs are stored in ``~/.kalite/logs/``. When going to daemon +mode using ``kalite start``, all outputs are additionally stored in +``~/.kalite/server.log``, which may contain more crash information for the last +running instance. + +In Python, please always log to ``logging.getLogger(__name__)``! Fore more +information on how logging is setup, refer to ``kalite.settings.base.LOGGING``. + If you wish to view output from the server, you have a few options: * Start the server with ``kalite start --foreground``. This will start the server using CherryPy and a single thread, with output going to your terminal. * Start the server in development mode ``kalite manage runserver --settings=kalite.project.settings.dev`` (this doesn't start the job scheduler). -* Run the normal mode ``kalite start``, and check ``~/.kalite/server.log`` for output. + diff --git a/docs/faq.rst b/docs/faq.rst index 6ab76c0267..fda2325a37 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -1,6 +1,18 @@ Frequently Asked Questions ========================== +Something isn't working - does KA Lite have log files? +------------------------------------------------------ + +It's very important to get more technical information if KA Lite is not working +or crashing. + +Have a look at ``~/.kalite/logs`` (on Windows, locate something like +``C:\Documents and Settings\\.kalite``), where you will find the log +files which KA Lite writes to while it's running. If KA Lite has crashed, have +look at the latest log file. You can also refer to ``~/.kalite/server.log`` +which may in some cases contain more information regarding a crash. + How do I install KA Lite? ------------------------- diff --git a/docs/installguide/release_notes.rst b/docs/installguide/release_notes.rst index 99e6902a16..18b9c12ff2 100644 --- a/docs/installguide/release_notes.rst +++ b/docs/installguide/release_notes.rst @@ -25,6 +25,12 @@ Bug fixes * Add line breaks in buttons so text isn't cut :url-issue:`5004` +New features +^^^^^^^^^^^^ + + * Log rotation: Logs for 30 days are now stored in ``~/.kalite/logs`` :url-issue:`4890` + + Known issues ^^^^^^^^^^^^ diff --git a/kalite/cli.py b/kalite/cli.py index 20a6e56a2f..8e669dfa95 100644 --- a/kalite/cli.py +++ b/kalite/cli.py @@ -123,7 +123,7 @@ # Where to store user data KALITE_HOME = os.environ["KALITE_HOME"] -SERVER_LOG = os.path.join(KALITE_HOME, "server.log") +DAEMON_LOG = os.path.join(KALITE_HOME, "server.log") if not os.path.isdir(KALITE_HOME): os.mkdir(KALITE_HOME) @@ -493,11 +493,11 @@ def start(debug=False, daemonize=True, args=[], skip_job_scheduler=False, port=N from django.utils.daemonize import become_daemon kwargs = {} # Truncate the file - open(SERVER_LOG, "w").truncate() - print("Going to daemon mode, logging to {0}\n".format(SERVER_LOG)) + open(DAEMON_LOG, "w").truncate() + print("Going to daemon mode, logging to {0}\n".format(DAEMON_LOG)) print_server_address(port) - kwargs['out_log'] = SERVER_LOG - kwargs['err_log'] = SERVER_LOG + kwargs['out_log'] = DAEMON_LOG + kwargs['err_log'] = DAEMON_LOG become_daemon(**kwargs) # Write the new PID with open(PID_FILE, 'w') as f: @@ -665,7 +665,7 @@ def status(): STATUS_STOPPED: 'Stopped', STATUS_STARTING_UP: 'Starting up', STATUS_NOT_RESPONDING: 'Not responding', - STATUS_FAILED_TO_START: 'Failed to start (check log file: {0})'.format(SERVER_LOG), + STATUS_FAILED_TO_START: 'Failed to start (check log file: {0})'.format(DAEMON_LOG), STATUS_UNCLEAN_SHUTDOWN: 'Unclean shutdown', STATUS_UNKNOWN_INSTANCE: 'Unknown KA Lite running on port', STATUS_SERVER_CONFIGURATION_ERROR: 'KA Lite server configuration error', diff --git a/kalite/settings/base.py b/kalite/settings/base.py index 5a4d589276..c2bcd40d9a 100644 --- a/kalite/settings/base.py +++ b/kalite/settings/base.py @@ -44,7 +44,17 @@ # We should use local module level logging.getLogger LOG = logging.getLogger("kalite") -SERVER_LOG = os.path.join(USER_DATA_ROOT, "server.log") +DAEMON_LOG = os.path.join(USER_DATA_ROOT, "server.log") + +LOG_ROOT = os.environ.get( + "KALITE_LOG_ROOT", + os.path.join(USER_DATA_ROOT, "logs") +) + +# Ensure that path exists +if not os.path.exists(LOG_ROOT): + os.mkdir(LOG_ROOT) + LOGGING = { 'version': 1, @@ -80,6 +90,15 @@ 'formatter': 'no_format', 'stream': sys.stdout, }, + 'file': { + 'level': 'INFO', + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': os.path.join(LOG_ROOT, 'django.log'), + 'formatter': 'standard', + 'when': 'midnight', + 'backupCount': '30', + 'maxBytes': 1 * 1024 * 1024, + }, }, 'loggers': { 'django': { @@ -93,37 +112,37 @@ 'propagate': False, }, 'kalite': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, 'kalite.distributed.management.commands': { - 'handlers': ['console_no_format'], + 'handlers': ['console_no_format', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, 'fle_utils': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, 'cherrypy.console': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, 'cherrypy.access': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, 'cherrypy.error': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOGGING_LEVEL, 'propagate': False, }, '': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': 'INFO', 'propagate': False, },