diff --git a/bin/netsvc.py b/bin/netsvc.py index ed3c01d0dba..1e807693f24 100644 --- a/bin/netsvc.py +++ b/bin/netsvc.py @@ -36,6 +36,7 @@ import sys import threading import time import xmlrpclib +import release _service = {} _group = {} @@ -139,6 +140,7 @@ class LocalService(Service): def service_exist(name): return (name in _service) and bool(_service[name]) +LOG_NOTSET = 'notset' LOG_DEBUG_RPC = 'debug_rpc' LOG_DEBUG = 'debug' LOG_INFO = 'info' @@ -153,7 +155,24 @@ def init_logger(): from tools import config import os + logger = logging.getLogger() + + if config['syslog']: + # SysLog Handler + if os.name == 'nt': + sysloghandler = logging.handlers.NTEventLogHandler("%s %s" % + (release.description, + release.version)) + else: + sysloghandler = logging.handlers.SysLogHandler('/dev/log') + formatter = logging.Formatter('%(application)s:%(uncoloredlevelname)s:%(name)s:%(message)s') + sysloghandler.setFormatter(formatter) + logger.addHandler(sysloghandler) + + # create a format for log messages and dates + formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s', '%a %b %d %Y %H:%M:%S') if config['logfile']: + # LogFile Handler logf = config['logfile'] try: dirname = os.path.dirname(logf) @@ -164,19 +183,17 @@ def init_logger(): sys.stderr.write("ERROR: couldn't create the logfile directory\n") handler = logging.StreamHandler(sys.stdout) else: + # Normal Handler on standard output handler = logging.StreamHandler(sys.stdout) - # create a format for log messages and dates - formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s', '%a %b %d %H:%M:%S %Y') # tell the handler to use this format handler.setFormatter(formatter) # add the handler to the root logger - logging.getLogger().addHandler(handler) - logging.getLogger().setLevel(config['log_level']) + logger.addHandler(handler) + logger.setLevel(config['log_level']) - if isinstance(handler, logging.StreamHandler) and os.name != 'nt': # change color of level names # uses of ANSI color codes @@ -201,21 +218,37 @@ def init_logger(): class Logger(object): + def uncoloredlevelname(self, level): + # The level'names are globals to all loggers, so we must strip-off the + # color formatting for some specific logger (i.e: syslog) + levelname = logging.getLevelName(getattr(logging, level.upper(), 0)) + if levelname.startswith("\x1b["): + return levelname[10:-4] + return levelname + def notifyChannel(self, name, level, msg): log = logging.getLogger(name) + if level == LOG_NOTSET: + return + if level == LOG_DEBUG_RPC and not hasattr(log, level): fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs) setattr(log, LOG_DEBUG_RPC, fct) + extra = { + 'uncoloredlevelname': self.uncoloredlevelname(level), + 'application' : "%s %s" % (release.description, release.version), + } + level_method = getattr(log, level) result = str(msg).strip().split('\n') if len(result)>1: for idx, s in enumerate(result): - level_method('[%02d]: %s' % (idx+1, s,)) + level_method('[%02d]: %s' % (idx+1, s,), extra=extra) elif result: - level_method(result[0]) + level_method(result[0], extra=extra) init_logger() diff --git a/bin/openerp-server.py b/bin/openerp-server.py index 943f13be25b..f1378ddef5d 100755 --- a/bin/openerp-server.py +++ b/bin/openerp-server.py @@ -55,6 +55,14 @@ __version__ = release.version import netsvc logger = netsvc.Logger() +def atexit_callback(): + logger.notifyChannel('shutdown', netsvc.LOG_INFO, "Shutdown Server!") + #logger.notifyChannel('pan! pan!', netsvc.LOG_INFO, "Killed Server ;-)") + +import atexit + +atexit.register(atexit_callback) + #----------------------------------------------------------------------- # import the tools module so that the commandline parameters are parsed #----------------------------------------------------------------------- diff --git a/bin/tools/config.py b/bin/tools/config.py index 4f57bd8c216..3ad41ee47a0 100644 --- a/bin/tools/config.py +++ b/bin/tools/config.py @@ -41,7 +41,6 @@ class configmanager(object): def __init__(self, fname=None): self.options = { 'email_from':False, - 'verbose': False, 'interface': '', # this will bind the server to all interfaces 'port': '8069', 'netinterface': '', @@ -74,22 +73,22 @@ class configmanager(object): 'stop_after_init': False, # this will stop the server after initialization 'price_accuracy': 2, 'secure' : False, + 'syslog' : False, 'log_level': logging.INFO, 'assert_exit_level': logging.WARNING, # level above which a failed assert will be raise } hasSSL = check_ssl() - loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC')]) + loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x)) + for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC', 'NOTSET')]) version = "%s %s" % (release.description, release.version) parser = optparse.OptionParser(version=version) parser.add_option("-c", "--config", dest="config", help="specify alternate config file") parser.add_option("-s", "--save", action="store_true", dest="save", default=False, help="save configuration to ~/.openerp_serverrc") - parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="enable debugging") parser.add_option("--pidfile", dest="pidfile", 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("-n", "--interface", dest="interface", help="specify the TCP IP address") parser.add_option("-p", "--port", dest="port", help="specify the TCP port") @@ -104,16 +103,26 @@ class configmanager(object): # stops the server from launching after initialization parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False, help="stop the server after it initializes") parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode') - parser.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(), help='specify the level of the logging. Accepted values: ' + str(loglevels.keys())) parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(), help="specify the level at which a failed assertion will stop the server. Accepted values: " + str(loglevels.keys())) if hasSSL: parser.add_option("-S", "--secure", dest="secure", action="store_true", help="launch server over https instead of http", default=False) + # Logging Group + group = optparse.OptionGroup(parser, "Logging Configuration") + group.add_option("--logfile", dest="logfile", help="file where the server log will be stored") + group.add_option("--syslog", action="store_true", dest="syslog", + default=False, help="Send the log to the syslog server") + group.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(), + help='specify the level of the logging. Accepted values: ' + str(loglevels.keys())) + parser.add_option_group(group) + + # SMTP Group group = optparse.OptionGroup(parser, "SMTP Configuration") group.add_option('--email-from', dest='email_from', default='', help='specify the SMTP email address for sending email') group.add_option('--smtp', dest='smtp_server', default='', help='specify the SMTP server for sending email') group.add_option('--smtp-port', dest='smtp_port', default='25', help='specify the SMTP port') - group.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not') + if hasSSL: + group.add_option('--smtp-ssl', dest='smtp_ssl', default='', help='specify the SMTP server support SSL or not') group.add_option('--smtp-user', dest='smtp_user', default='', help='specify the SMTP username for sending email') group.add_option('--smtp-password', dest='smtp_password', default='', help='specify the SMTP password for sending email') group.add_option('--price_accuracy', dest='price_accuracy', default='2', help='specify the price accuracy') @@ -183,13 +192,13 @@ class configmanager(object): if getattr(opt, arg): self.options[arg] = getattr(opt, arg) - for arg in ('language', 'translate_out', 'translate_in', - 'upgrade', 'verbose', 'debug_mode', - 'stop_after_init', 'without_demo', 'netrpc', 'xmlrpc'): + for arg in ('language', 'translate_out', 'translate_in', 'upgrade', 'debug_mode', + 'stop_after_init', 'without_demo', 'netrpc', 'xmlrpc', 'syslog'): self.options[arg] = getattr(opt, arg) if opt.assert_exit_level: self.options['assert_exit_level'] = loglevels[opt.assert_exit_level] + if opt.log_level: self.options['log_level'] = loglevels[opt.log_level]