def test_group_handler_mail_combo(self): mail_handler = make_fake_mail_handler(level=logbook.DEBUG) handler = logbook.GroupHandler(mail_handler) with handler: self.log.error('The other way round') self.log.warn('Testing') self.log.debug('Even more') self.assertEqual(mail_handler.mails, []) self.assertEqual(len(mail_handler.mails), 1) mail = mail_handler.mails[0][2] pieces = mail.split('Other log records in the same group:') self.assertEqual(len(pieces), 2) body, rest = pieces self.assert_(re.search('Message type:\s+ERROR', body)) self.assert_(re.search('Module:\s+logbook.testsuite.test_contextmanager', body)) self.assert_(re.search('Function:\s+test_group_handler_mail_combo', body)) related = rest.strip().split('\r\n\r\n') self.assertEqual(len(related), 2) self.assert_(re.search('Message type:\s+WARNING', related[0])) self.assert_(re.search('Message type:\s+DEBUG', related[1]))
def test_mail_handler(self): # broken in stdlib for 3.1 as far as I can see if sys.version_info >= (3, 0) and sys.version_info < (3, 2): ascii_subject = True subject = u'ascii only' else: ascii_subject = False subject = u'\xf8nicode' handler = make_fake_mail_handler(subject=subject, level=logbook.CRITICAL) with capture_stderr() as fallback: with handler: self.log.error('This is not mailed') try: 1 / 0 except Exception, e: self.log.critical('This is unfortunate', exc_info=sys.exc_info()) self.assertEqual(len(handler.mails), 1) sender, receivers, mail = handler.mails[0] self.assertEqual(sender, handler.from_addr) if not ascii_subject: self.assert_('=?utf-8?q?=C3=B8nicode?=' in mail) self.assert_(re.search('Message type:\s+CRITICAL', mail)) self.assert_(re.search('Location:.*%s' % test_file, mail)) self.assert_(re.search('Module:\s+%s' % __name__, mail)) self.assert_(re.search('Function:\s+test_mail_handler', mail)) self.assert_('Message:\r\n\r\nThis is unfortunate' in mail) self.assert_('\r\n\r\nTraceback' in mail) self.assert_('1 / 0' in mail) self.assert_('This is not mailed' in fallback.getvalue())
def test_nested_setups(self): with capture_stderr() as captured: logger = logbook.Logger('App') test_handler = logbook.TestHandler(level='WARNING') mail_handler = make_fake_mail_handler(bubble=True) handlers = logbook.NestedSetup([ logbook.NullHandler(), test_handler, mail_handler ]) with handlers: logger.warn('This is a warning') logger.error('This is also a mail') with logger.catch_exceptions(): 1 / 0 logger.warn('And here we go straight back to stderr') self.assert_(test_handler.has_warning('This is a warning')) self.assert_(test_handler.has_error('This is also a mail')) self.assertEqual(len(mail_handler.mails), 2) self.assert_('This is also a mail' in mail_handler.mails[0][2]) self.assert_('1 / 0' in mail_handler.mails[1][2]) self.assert_('And here we go straight back to stderr' in captured.getvalue()) with handlers.threadbound(): logger.warn('threadbound warning') with handlers.applicationbound(): logger.warn('applicationbound warning')
def test_mail_handler(self): subject = u'\xf8nicode' handler = make_fake_mail_handler(subject=subject) with capture_stderr() as fallback: with handler: self.log.warn('This is not mailed') try: 1 / 0 except Exception: self.log.exception(u'Viva la Espa\xf1a') self.assertEqual(len(handler.mails), 1) sender, receivers, mail = handler.mails[0] self.assertEqual(sender, handler.from_addr) self.assert_('=?utf-8?q?=C3=B8nicode?=' in mail) self.assert_(re.search('Message type:\s+ERROR', mail)) self.assert_(re.search('Location:.*%s' % test_file, mail)) self.assert_(re.search('Module:\s+%s' % __name__, mail)) self.assert_(re.search('Function:\s+test_mail_handler', mail)) body = u'Message:\r\n\r\nViva la Espa\xf1a' if sys.version_info < (3, 0): body = body.encode('utf-8') self.assert_(body in mail) self.assert_('\r\n\r\nTraceback' in mail) self.assert_('1 / 0' in mail) self.assert_('This is not mailed' in fallback.getvalue())
def test_mail_handler(self): # broken in stdlib for 3.1 as far as I can see if sys.version_info >= (3, 0) and sys.version_info < (3, 2): ascii_subject = True subject = u'ascii only' else: ascii_subject = False subject = u'\xf8nicode' handler = make_fake_mail_handler(subject=subject) with capture_stderr() as fallback: with handler: self.log.warn('This is not mailed') try: 1 / 0 except Exception: self.log.exception('This is unfortunate') self.assertEqual(len(handler.mails), 1) sender, receivers, mail = handler.mails[0] self.assertEqual(sender, handler.from_addr) if not ascii_subject: self.assert_('=?utf-8?q?=C3=B8nicode?=' in mail) self.assert_(re.search('Message type:\s+ERROR', mail)) self.assert_(re.search('Location:.*%s' % test_file, mail)) self.assert_(re.search('Module:\s+%s' % __name__, mail)) self.assert_(re.search('Function:\s+test_mail_handler', mail)) self.assert_('Message:\r\n\r\nThis is unfortunate' in mail) self.assert_('\r\n\r\nTraceback' in mail) self.assert_('1 / 0' in mail) self.assert_('This is not mailed' in fallback.getvalue())
def test_handler_processors(self): handler = make_fake_mail_handler(format_string='''\ Subject: Application Error for {record.extra[path]} [{record.extra[method]}] Message type: {record.level_name} Location: {record.filename}:{record.lineno} Module: {record.module} Function: {record.func_name} Time: {record.time:%Y-%m-%d %H:%M:%S} Remote IP: {record.extra[ip]} Request: {record.extra[path]} [{record.extra[method]}] Message: {record.message} ''') class Request(object): remote_addr = '127.0.0.1' method = 'GET' path = '/index.html' def handle_request(request): def inject_extra(record): record.extra['ip'] = request.remote_addr record.extra['method'] = request.method record.extra['path'] = request.path processor = logbook.Processor(inject_extra) processor.push_thread() try: handler.push_thread() try: try: 1 / 0 except Exception: self.log.exception('Exception happened during request') finally: handler.pop_thread() finally: processor.pop_thread() handle_request(Request()) self.assertEqual(len(handler.mails), 1) mail = handler.mails[0][2] self.assert_('Subject: Application Error ' 'for /index.html [GET]' in mail) self.assert_('1 / 0' in mail)
def test_nested_setups(self): captured = capture_stderr.start() try: logger = logbook.Logger('App') test_handler = logbook.TestHandler(level='WARNING') mail_handler = make_fake_mail_handler(bubble=True) handlers = logbook.NestedSetup([ logbook.NullHandler(), test_handler, mail_handler ]) handlers.push_thread() try: logger.warn('This is a warning') logger.error('This is also a mail') try: 1 / 0 except Exception: logger.exception() finally: handlers.pop_thread() logger.warn('And here we go straight back to stderr') self.assert_(test_handler.has_warning('This is a warning')) self.assert_(test_handler.has_error('This is also a mail')) self.assertEqual(len(mail_handler.mails), 2) self.assert_('This is also a mail' in mail_handler.mails[0][2]) self.assert_('1 / 0' in mail_handler.mails[1][2]) self.assert_('And here we go straight back to stderr' in captured.getvalue()) handlers.push_thread() try: logger.warn('threadbound warning') finally: handlers.pop_thread() handlers.push_application() try: logger.warn('applicationbound warning') finally: handlers.pop_application() finally: capture_stderr.end()
def test_mail_handler_record_limits(self): suppression_test = re.compile('This message occurred additional \d+ ' 'time\(s\) and was suppressed').search handler = make_fake_mail_handler(record_limit=1, record_delta=timedelta(seconds=0.5)) with handler: later = datetime.utcnow() + timedelta(seconds=1.1) while datetime.utcnow() < later: self.log.error('Over and over...') # first mail that is always delivered + 0.5 seconds * 2 # and 0.1 seconds of room for rounding errors makes 3 mails self.assertEqual(len(handler.mails), 3) # first mail is always delivered self.assert_(not suppression_test(handler.mails[0][2])) # the next two have a supression count self.assert_(suppression_test(handler.mails[1][2])) self.assert_(suppression_test(handler.mails[2][2]))
def test_handler_processors(self): handler = make_fake_mail_handler(format_string='''\ Subject: Application Error for {record.extra[path]} [{record.extra[method]}] Message type: {record.level_name} Location: {record.filename}:{record.lineno} Module: {record.module} Function: {record.func_name} Time: {record.time:%Y-%m-%d %H:%M:%S} Remote IP: {record.extra[ip]} Request: {record.extra[path]} [{record.extra[method]}] Message: {record.message} ''') class Request(object): remote_addr = '127.0.0.1' method = 'GET' path = '/index.html' def handle_request(request): def inject_extra(record): record.extra['ip'] = request.remote_addr record.extra['method'] = request.method record.extra['path'] = request.path with logbook.Processor(inject_extra): with handler: try: 1 / 0 except Exception: self.log.exception('Exception happened during request') handle_request(Request()) self.assertEqual(len(handler.mails), 1) mail = handler.mails[0][2] self.assert_('Subject: Application Error ' 'for /index.html [GET]' in mail) self.assert_('1 / 0' in mail)
def test_mail_handler(self): # broken in stdlib for 3.1 as far as I can see if sys.version_info >= (3, 0) and sys.version_info < (3, 2): ascii_subject = True subject = u'ascii only' else: ascii_subject = False subject = u'\xf8nicode' handler = make_fake_mail_handler(subject=subject) fallback = capture_stderr.start() try: handler.push_thread() try: self.log.warn('This is not mailed') try: 1 / 0 except Exception: self.log.exception('This is unfortunate') finally: handler.pop_thread() self.assertEqual(len(handler.mails), 1) sender, receivers, mail = handler.mails[0] self.assertEqual(sender, handler.from_addr) if not ascii_subject: self.assert_('=?utf-8?q?=C3=B8nicode?=' in mail) self.assert_(re.search('Message type:\s+ERROR', mail)) self.assert_(re.search('Location:.*%s' % test_file, mail)) self.assert_(re.search('Module:\s+%s' % __name__, mail)) self.assert_(re.search('Function:\s+test_mail_handler', mail)) self.assert_('Message:\r\n\r\nThis is unfortunate' in mail) self.assert_('\r\n\r\nTraceback' in mail) self.assert_('1 / 0' in mail) self.assert_('This is not mailed' in fallback.getvalue()) finally: capture_stderr.end()