Commit e5cd306e authored by Fred Drake's avatar Fred Drake

- re-enable several loghandler types

- make it easier for an admin to configure logging levels
  (by making the defaults more sane)
- refactor the tests a little, in preparation for more tests
parent 9ef37bd4
...@@ -2,60 +2,57 @@ ...@@ -2,60 +2,57 @@
<abstracttype name="loghandler"/> <abstracttype name="loghandler"/>
<sectiontype name="file-handler" datatype=".file_handler" <sectiontype name="base-log-handler">
implements="loghandler"> <description>
Base type for most log handlers. This is cannot be used as a
loghandler directly since it doesn't implement the loghandler
abstract section type.
</description>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype>
<sectiontype name="logfile" datatype=".file_handler"
implements="loghandler" extends="base-log-handler">
<key name="path" required="yes"/> <key name="path" required="yes"/>
<key name="format" default="------\n%(asctime)s %(message)s" <key name="format" default="------\n%(asctime)s %(message)s"
datatype=".log_format"/> datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype> </sectiontype>
<sectiontype name="syslog-handler" datatype=".syslog_handler" <sectiontype name="syslog" datatype=".syslog_handler"
implements="loghandler"> implements="loghandler" extends="base-log-handler">
<key name="facility" default="user" datatype=".syslog_facility"/> <key name="facility" default="user" datatype=".syslog_facility"/>
<key name="address" datatype="socket-address" required="yes"/> <key name="address" datatype="socket-address" required="yes"/>
<key name="format" default="%(message)s" <key name="format" default="%(message)s"
datatype=".log_format"/> datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype> </sectiontype>
<!-- <sectiontype name="nteventlog" datatype=".nteventlog_handler"
<sectiontype name="nteventlog_handler" datatype=".nteventlog_handler" implements="loghandler" extends="base-log-handler">
implements="loghandler">
<key name="appname" default="Zope"/> <key name="appname" default="Zope"/>
<key name="format" default="%(message)s" <key name="format" default="%(message)s"
datatype=".log_format"/> datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype> </sectiontype>
<sectiontype name="http_handler" datatype=".http_handler" <sectiontype name="http_handler" datatype=".http_handler"
implements="loghandler"> implements="loghandler" extends="base-log-handler">
<key name="url" default="localhost" datatype=".http_handler_url"/> <key name="url" default="localhost" datatype=".http_handler_url"/>
<key name="method" default="GET" datatype=".get_or_post"/> <key name="method" default="GET" datatype=".get_or_post"/>
<key name="format" default="%(asctime)s %(message)s" <key name="format" default="%(asctime)s %(message)s"
datatype=".log_format"/> datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype> </sectiontype>
<sectiontype name="smtp_handler" datatype=".smtp_handler" <sectiontype name="smtp_handler" datatype=".smtp_handler"
implements="loghandler"> implements="loghandler" extends="base-log-handler">
<key name="fromaddr" required="yes"/> <key name="fromaddr" required="yes"/>
<multikey name="toaddr" required="yes" attribute="toaddrs"/> <multikey name="toaddr" required="yes" attribute="toaddrs"/>
<key name="subject" default="Message from Zope"/> <key name="subject" default="Message from Zope"/>
<key name="host" default="localhost" datatype="inet-address"/> <key name="host" default="localhost" datatype="inet-address"/>
<key name="format" default="%(asctime)s %(message)s" <key name="format" default="%(asctime)s %(message)s"
datatype=".log_format"/> datatype=".log_format"/>
<key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
<key name="level" default="info" datatype=".logging_level"/>
</sectiontype> </sectiontype>
<sectiontype name="null_handler" datatype=".null_handler" <!--
implements="loghandler"/>
<sectiontype name="custom_handler" datatype=".custom_handler" <sectiontype name="custom_handler" datatype=".custom_handler"
implements="loghandler"> implements="loghandler">
<key name="constructor" datatype="constructor" required="yes"/> <key name="constructor" datatype="constructor" required="yes"/>
...@@ -66,7 +63,7 @@ ...@@ -66,7 +63,7 @@
--> -->
<sectiontype name="logger" datatype=".logger"> <sectiontype name="logger" datatype=".logger">
<key name="level" datatype=".logging_level" default="info"/> <key name="level" datatype=".logging_level" default="all"/>
<multisection type="loghandler" attribute="handlers" name="*"/> <multisection type="loghandler" attribute="handlers" name="*"/>
</sectiontype> </sectiontype>
......
...@@ -136,84 +136,80 @@ def syslog_handler(section): ...@@ -136,84 +136,80 @@ def syslog_handler(section):
section.address.address, section.address.address,
section.facility) section.facility)
## def nteventlog_handler(section): def nteventlog_handler(section):
## appname = section.appname def callback(inst,
## format = section.format format=section.format,
## dateformat = section.dateformat dateformat=section.dateformat,
## level = section.level level=section.level):
import logging
## formatter = Factory('logging.Formatter', None, format, dateformat) inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
## def callback(inst, formatter=formatter, level=level):
## inst.setFormatter(formatter())
## inst.setLevel(level)
## return Factory('zLOG.LogHandlers.NTEventLogHandler', callback, appname)
## def http_handler_url(value):
## import urlparse
## scheme, netloc, path, query, fragment = urlparse.urlsplit(value)
## if scheme != 'http':
## raise ValueError, 'url must be an http url'
## if not netloc:
## raise ValueError, 'url must specify a location'
## if not path:
## raise ValueError, 'url must specify a path'
## q = []
## if query:
## q.append('?')
## q.append(query)
## if fragment:
## q.append('#')
## q.append(fragment)
## return (netloc, path + ''.join(q))
## def get_or_post(value):
## value = value.upper()
## if value not in ('GET', 'POST'):
## raise ValueError, ('method must be "GET" or "POST", instead received '
## '%s' % repr(value))
## return value
## def http_handler(section):
## host, url = section.url
## method = section.method
## format = section.format
## dateformat = section.dateformat
## level = section.level
## formatter = Factory('logging.Formatter', None, format, dateformat)
## def callback(inst, formatter=formatter, level=level):
## inst.setFormatter(formatter())
## inst.setLevel(level)
## return Factory('zLOG.LogHandlers.HTTPHandler', callback, host, url, method)
## def smtp_handler(section): return Factory('zLOG.LogHandlers.NTEventLogHandler', callback,
## fromaddr = section.fromaddr section.appname)
## toaddrs = section.toaddrs
## subject = section.subject def http_handler_url(value):
## host, port = section.host import urlparse
## format = section.format scheme, netloc, path, param, query, fragment = urlparse.urlparse(value)
## dateformat = section.dateformat if scheme != 'http':
## level = section.level raise ValueError, 'url must be an http url'
if not netloc:
raise ValueError, 'url must specify a location'
if not path:
raise ValueError, 'url must specify a path'
q = []
if param:
q.append(';')
q.append(param)
if query:
q.append('?')
q.append(query)
if fragment:
q.append('#')
q.append(fragment)
return (netloc, path + ''.join(q))
def get_or_post(value):
value = value.upper()
if value not in ('GET', 'POST'):
raise ValueError('method must be "GET" or "POST", instead received: '
+ repr(value))
return value
## if not port: def http_handler(section):
## mailhost = host def callback(inst,
## else: format=section.format,
## mailhost = host, port dateformat=section.dateformat,
## formatter = Factory('logging.Formatter', None, format, dateformat) level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
## def callback(inst, formatter=formatter, level=level): host, selector = section.url
## inst.setFormatter(formatter()) return Factory('zLOG.LogHandlers.HTTPHandler',
## inst.setLevel(level) callback, host, selector, section.method)
## return Factory('zLOG.LogHandlers.SMTPHandler', callback, def smtp_handler(section):
## mailhost, fromaddr, toaddrs, subject) def callback(inst,
format=section.format,
dateformat=section.dateformat,
level=section.level):
import logging
inst.setFormatter(logging.Formatter(format, dateformat))
inst.setLevel(level)
## def null_handler(section): host, port = section.host
## return Factory('zLOG.LogHandlers.NullHandler', None) if not port:
mailhost = host
else:
mailhost = host, port
return Factory('zLOG.LogHandlers.SMTPHandler',
callback,
mailhost,
section.fromaddr,
section.toaddrs,
section.subject)
## def custom_handler(section): ## def custom_handler(section):
## formatter_klass, formatter_pos, formatter_kw = section.formatter ## formatter_klass, formatter_pos, formatter_kw = section.formatter
......
############################################################################## ##############################################################################
# #
# Copyright (c) 2002, 2003 Zope Corporation and Contributors. # Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved. # All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
import cStringIO as StringIO import cStringIO as StringIO
import logging import logging
import tempfile
import unittest import unittest
import ZConfig import ZConfig
...@@ -64,19 +65,39 @@ class TestzLOGConfig(unittest.TestCase): ...@@ -64,19 +65,39 @@ class TestzLOGConfig(unittest.TestCase):
self.assert_(conf.logger is None) self.assert_(conf.logger is None)
def test_config_without_handlers(self): def test_config_without_handlers(self):
conf = self.get_config("<logger/>") logger = self.check_simple_logger("<logger/>")
self.assert_(conf.logger is not None)
self.assertEqual(conf.logger.level, logging.INFO)
logger = conf.logger()
self.assert_(isinstance(logger, logging.Logger))
# Make sure there's a NullHandler, since a warning gets # Make sure there's a NullHandler, since a warning gets
# printed if there are no handlers: # printed if there are no handlers:
self.assertEqual(len(logger.handlers), 1) self.assertEqual(len(logger.handlers), 1)
self.assert_(isinstance(logger.handlers[0], self.assert_(isinstance(logger.handlers[0],
zLOG.LogHandlers.NullHandler)) zLOG.LogHandlers.NullHandler))
def test_with_logfile(self):
fn = tempfile.mktemp()
logger = self.check_simple_logger("<logger>\n"
" <logfile>\n"
" path %s\n"
" level debug\n"
" </logfile>\n"
"</logger>" % fn)
# Make sure there's exactly one handler, since a warning gets
# printed if there are no handlers, and we don't want an
# unnecessary NullHandler getting added:
self.assertEqual(len(logger.handlers), 1)
self.assertEqual(logger.handlers[0].level, logging.DEBUG)
self.assert_(isinstance(logger.handlers[0],
zLOG.LogHandlers.FileHandler))
# XXX need to make sure each loghandler datatype gets exercised. # XXX need to make sure each loghandler datatype gets exercised.
def check_simple_logger(self, text, level=logging.NOTSET):
conf = self.get_config(text)
self.assertEqual(conf.logger.level, level)
self.assert_(conf.logger is not None)
logger = conf.logger()
self.assert_(isinstance(logger, logging.Logger))
return logger
def test_suite(): def test_suite():
return unittest.makeSuite(TestzLOGConfig) return unittest.makeSuite(TestzLOGConfig)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment