Reviewers: ,


Please review this at http://codereview.tryton.org/831002/

Affected files:
  M bin/trytond
  M etc/trytond.conf
  M trytond/config.py
  A trytond/log.py
  M trytond/protocols/dispatcher.py
  M trytond/protocols/webdav.py
  M trytond/server.py


Index: bin/trytond
===================================================================
--- a/bin/trytond
+++ b/bin/trytond
@@ -24,8 +24,6 @@
     parser.add_option('--debug', dest='debug_mode', action='store_true',
         help='enable debug mode (start post-mortem debugger if exceptions'
         ' occur)')
-    parser.add_option("-v", "--verbose", action="store_true",
-        dest="verbose", help="enable verbose mode")

     parser.add_option("-d", "--database", dest="db_name",
         help="specify the database name")
@@ -38,6 +36,9 @@
         help="file where the server pid will be stored")
     parser.add_option("--logfile", dest="logfile",
         help="file where the server log will be stored")
+    parser.add_option('--log-level', dest='log_level',
+        help='verbosity of the messages recorded in the logs. One of: '
+        'debug,info,warning,error,critical.')
     parser.add_option("--disable-cron", dest="cron",
         action="store_false", help="disable cron")

@@ -54,10 +55,10 @@
         options['configfile'] = None

     for arg in (
-            'verbose',
             'debug_mode',
             'pidfile',
             'logfile',
+            'log_level',
             'cron',
             ):
         if getattr(opt, arg) is not None:
Index: etc/trytond.conf
===================================================================
--- a/etc/trytond.conf
+++ b/etc/trytond.conf
@@ -47,6 +47,8 @@
 # Configure the path of the files for the pid and the logs
 #pidfile = False
 #logfile = False
+# Configure log level (debug, info, warning, error, critical)
+#log_level = info

 #privatekey = server.pem
 #certificate = server.pem
Index: trytond/config.py
===================================================================
--- a/trytond/config.py
+++ b/trytond/config.py
@@ -57,10 +57,10 @@
             'db_maxconn': 64,
             'pg_path': None,
             'admin_passwd': 'admin',
-            'verbose': False,
             'debug_mode': False,
             'pidfile': None,
             'logfile': None,
+            'log_level': 'info',
             'privatekey': '/etc/ssl/trytond/server.key',
             'certificate': '/etc/ssl/trytond/server.pem',
             'smtp_server': 'localhost',
Index: trytond/log.py
===================================================================
new file mode 100644
--- /dev/null
+++ b/trytond/log.py
@@ -0,0 +1,55 @@
+#This file is part of Tryton.  The COPYRIGHT file at the top level of
+#this repository contains the full copyright notices and license terms.
+
+from logging import Formatter, CRITICAL, ERROR, WARNING, INFO, DEBUG
+from sys import platform, stdout
+
+RESET_SEQ = "\x1b[0m"
+COLOR_SEQ = "%s%%s" + RESET_SEQ
+
+COLORS = {
+    'DEBUG': COLOR_SEQ % "\x1b[36m",                   # light blue
+    'INFO': COLOR_SEQ % "\x1b[1;1m",                   # bold white
+    'WARNING': COLOR_SEQ % "\x1b[1;33m",               # bold yellow
+    'ERROR': COLOR_SEQ % "\x1b[1;31m",                 # bold red
+ 'CRITICAL': COLOR_SEQ % ("\x1b[1;33m\x1b[1;41m"), # bold yellow over red
+}
+
+LOG_LEVELS = {
+    'DEBUG': DEBUG,
+    'INFO': INFO,
+    'WARNING': WARNING,
+    'ERROR': ERROR,
+    'CRITICAL': CRITICAL,
+}
+
+
+def getLogLevel(name):
+    try:
+        return LOG_LEVELS[name.upper()]
+    except KeyError:
+        raise ValueError('Invalid log level: %s' % name)
+
+
+class ColoredFormatter(Formatter):
+    """
+    Class written by airmind:
+    http://stackoverflow.com/questions/384076/
+    """
+    def format(self, record):
+        levelname = record.levelname
+        msg = Formatter.format(self, record)
+        if levelname in COLORS:
+            if stdout.isatty():
+                msg = COLORS[levelname] % msg
+        else:
+ print ("*" * 100, levelname, "(%s)" % type(levelname), "not in",
+                    COLORS.keys())
+        return msg
+
+
+def createColoredFormatter(stream, fmt, datefmt):
+    if (platform != 'win32'):
+        return ColoredFormatter(fmt=fmt, datefmt=datefmt)
+    else:
+        return Formatter('%(message)s')
Index: trytond/protocols/dispatcher.py
===================================================================
--- a/trytond/protocols/dispatcher.py
+++ b/trytond/protocols/dispatcher.py
@@ -172,12 +172,12 @@
                     continue
                 raise
             except Exception, exception:
-                if CONFIG['verbose'] and not isinstance(exception, (
+                if not isinstance(exception, (
                             NotLogged, ConcurrencyException, UserError,
                             UserWarning)):
tb_s = ''.join(traceback.format_exception(*sys.exc_info()))
                     logger = logging.getLogger('dispatcher')
-                    logger.error('Exception calling method %s on '
+                    logger.debug('Exception calling method %s on '
                         '%s %s from %s@%s:%d/%s:\n'
% (method, object_type, object_name, user, host, port,
                             database_name) + tb_s)
Index: trytond/protocols/webdav.py
===================================================================
--- a/trytond/protocols/webdav.py
+++ b/trytond/protocols/webdav.py
@@ -131,12 +131,12 @@
         self.verbose = False

     def _log_exception(self, exception):
-        if CONFIG['verbose'] and not isinstance(exception, (
+        if not isinstance(exception, (
NotLogged, ConcurrencyException, UserError, UserWarning,
                     DAV_Error, DAV_NotFound, DAV_Secret, DAV_Forbidden)):
             tb_s = ''.join(traceback.format_exception(*sys.exc_info()))
             logger = logging.getLogger('webdav')
-            logger.error('Exception:\n' + tb_s)
+            logger.debug('Exception:\n' + tb_s)

     @staticmethod
     def get_dburi(uri):
Index: trytond/server.py
===================================================================
--- a/trytond/server.py
+++ b/trytond/server.py
@@ -10,6 +10,7 @@
 import signal
 import time
 from trytond.config import CONFIG
+from trytond.log import createColoredFormatter, getLogLevel
 from getpass import getpass
 import hashlib
 import threading
@@ -22,13 +23,13 @@
     def __init__(self, options):
         format = '[%(asctime)s] %(levelname)s:%(name)s:%(message)s'
         datefmt = '%a %b %d %H:%M:%S %Y'
-        logging.basicConfig(level=logging.INFO, format=format,
-                datefmt=datefmt)

         CONFIG.update_etc(options['configfile'])
         CONFIG.update_cmdline(options)
         CONFIG.set_timezone()

+        logging.getLogger().setLevel(getLogLevel(CONFIG['log_level']))
+
         if CONFIG['logfile']:
             logf = CONFIG['logfile']
             # test if the directories exist, else create them
@@ -41,8 +42,8 @@
                 handler.rolloverAt -= diff
             except Exception, exception:
                 sys.stderr.write(
-                    "ERROR: couldn't create the logfile directory:"
-                    + str(exception))
+                    "ERROR: couldn't create the logfile directory:%s\n"
+                    % exception)
             else:
                 formatter = logging.Formatter(format, datefmt)
                 # tell the handler to use this format
@@ -50,14 +51,11 @@

                 # add the handler to the root logger
                 logging.getLogger().addHandler(handler)
-                logging.getLogger().setLevel(logging.INFO)
-        elif os.name != 'nt':
-            reverse = '\x1b[7m'
-            reset = '\x1b[0m'
-            # reverse color for error and critical messages
-            for level in logging.ERROR, logging.CRITICAL:
-                msg = reverse + logging.getLevelName(level) + reset
-                logging.addLevelName(level, msg)
+
+        default_handler = logging.StreamHandler(sys.stdout)
+        formatter = createColoredFormatter(sys.stdout, format, datefmt)
+        default_handler.setFormatter(formatter)
+        logging.getLogger().addHandler(default_handler)

         self.logger = logging.getLogger("server")



Reply via email to