Commit 408e076c authored by Tres Seaver's avatar Tres Seaver

Merge branch 'products.siteerrorlog' of github.com:jfroche/Zope into jfroche-products.siteerrorlog

parents 12042f18 2dc8d095
...@@ -58,6 +58,7 @@ eggs = ...@@ -58,6 +58,7 @@ eggs =
MultiMapping MultiMapping
Persistence Persistence
Products.OFSP Products.OFSP
Products.SiteErrorLog[zope212]
Products.ZCatalog Products.ZCatalog
Products.ZCTextIndex Products.ZCTextIndex
Record Record
......
...@@ -57,6 +57,8 @@ Features Added ...@@ -57,6 +57,8 @@ Features Added
Restructuring Restructuring
+++++++++++++ +++++++++++++
- Products.SiteErrorLog: Is now a separated package.
- OFS: Removed duplicate code in ZopeFind and ZopeFindAndApply - OFS: Removed duplicate code in ZopeFind and ZopeFindAndApply
- Five: Removed obsolete metaclass. - Five: Removed obsolete metaclass.
......
...@@ -56,6 +56,7 @@ setup(name='Zope2', ...@@ -56,6 +56,7 @@ setup(name='Zope2',
'MultiMapping', 'MultiMapping',
'Persistence', 'Persistence',
'Products.OFSP >= 2.13.2', 'Products.OFSP >= 2.13.2',
'Products.SiteErrorLog[zope212]',
'Products.ZCatalog', 'Products.ZCatalog',
'Products.ZCTextIndex', 'Products.ZCTextIndex',
'Record', 'Record',
......
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import SiteErrorLog
def initialize(context):
context.registerClass(SiteErrorLog.SiteErrorLog,
constructors=(SiteErrorLog.manage_addErrorLog,),
permission=SiteErrorLog.use_error_logging)
"""SiteErrorLog tests
"""
from Testing.makerequest import makerequest
import Zope2
Zope2.startup()
import transaction
import sys
import unittest
import logging
class SiteErrorLogTests(unittest.TestCase):
def setUp(self):
transaction.begin()
self.app = makerequest(Zope2.app())
try:
if not hasattr(self.app, 'error_log'):
# If ZopeLite was imported, we have no default error_log
from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
self.app._setObject('error_log', SiteErrorLog())
self.app.manage_addDTMLMethod('doc', '')
self.logger = logging.getLogger('Zope.SiteErrorLog')
self.log = logging.handlers.BufferingHandler(sys.maxint)
self.logger.addHandler(self.log)
self.old_level = self.logger.level
self.logger.setLevel(logging.ERROR)
except:
self.tearDown()
def tearDown(self):
self.logger.removeHandler(self.log)
self.logger.setLevel(self.old_level)
transaction.abort()
self.app._p_jar.close()
def testInstantiation(self):
# Retrieve the error_log by ID
sel_ob = getattr(self.app, 'error_log', None)
# Does the error log exist?
self.assert_(sel_ob is not None)
# Is the __error_log__ hook in place?
self.assert_(self.app.__error_log__ == sel_ob)
# Right now there should not be any entries in the log
# but if another test fails and leaves something in the
# log (which belongs to app , we get a spurious error here.
# There's no real point in testing this anyway.
#self.assertEquals(len(sel_ob.getLogEntries()), 0)
def testSimpleException(self):
# Grab the Site Error Log and make sure it's empty
sel_ob = self.app.error_log
previous_log_length = len(sel_ob.getLogEntries())
# Fill the DTML method at self.root.doc with bogus code
dmeth = self.app.doc
dmeth.manage_upload(file="""<dtml-var expr="1/0">""")
# "Faking out" the automatic involvement of the Site Error Log
# by manually calling the method "raising" that gets invoked
# automatically in a normal web request environment.
try:
dmeth.__call__()
except ZeroDivisionError:
sel_ob.raising(sys.exc_info())
# Now look at the SiteErrorLog, it has one more log entry
self.assertEquals(len(sel_ob.getLogEntries()), previous_log_length+1)
def testForgetException(self):
elog = self.app.error_log
# Create a predictable error
try:
raise AttributeError, "DummyAttribute"
except AttributeError:
info = sys.exc_info()
elog.raising(info)
previous_log_length = len(elog.getLogEntries())
entries = elog.getLogEntries()
self.assertEquals(entries[0]['value'], "DummyAttribute")
# Kick it
elog.forgetEntry(entries[0]['id'])
# Really gone?
self.assertEquals(len(elog.getLogEntries()), previous_log_length-1)
def testIgnoredException(self):
# Grab the Site Error Log
sel_ob = self.app.error_log
previous_log_length = len(sel_ob.getLogEntries())
# Tell the SiteErrorLog to ignore ZeroDivisionErrors
current_props = sel_ob.getProperties()
ignored = list(current_props['ignored_exceptions'])
ignored.append('ZeroDivisionError')
sel_ob.setProperties( current_props['keep_entries']
, copy_to_zlog = current_props['copy_to_zlog']
, ignored_exceptions = ignored
)
# Fill the DTML method at self.root.doc with bogus code
dmeth = self.app.doc
dmeth.manage_upload(file="""<dtml-var expr="1/0">""")
# "Faking out" the automatic involvement of the Site Error Log
# by manually calling the method "raising" that gets invoked
# automatically in a normal web request environment.
try:
dmeth.__call__()
except ZeroDivisionError:
sel_ob.raising(sys.exc_info())
# Now look at the SiteErrorLog, it must have the same number of
# log entries
self.assertEquals(len(sel_ob.getLogEntries()), previous_log_length)
def testEntryID(self):
elog = self.app.error_log
# Create a predictable error
try:
raise AttributeError, "DummyAttribute"
except AttributeError:
info = sys.exc_info()
elog.raising(info)
entries = elog.getLogEntries()
entry_id = entries[0]['id']
self.assertTrue(entry_id in self.log.buffer[-1].msg,
(entry_id, self.log.buffer[-1].msg))
def testCleanup(self):
# Need to make sure that the __error_log__ hook gets cleaned up
self.app._delObject('error_log')
self.assertEquals(getattr(self.app, '__error_log__', None), None)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(SiteErrorLogTests))
return suite
<h1 tal:replace="structure context/manage_page_header">Header</h1>
<h1 tal:replace="structure context/manage_tabs">Tabs</h1>
<p class="form-help">
This page lists the exceptions that have occurred in this site
recently. You can configure how many exceptions should be kept
and whether the exceptions should be copied to Zope's event log
file(s).
</p>
<form action="setProperties" method="post">
<table tal:define="props container/getProperties">
<tr>
<td align="left" valign="top">
<div class="form-label">
Number of exceptions to keep
</div>
</td>
<td align="left" valign="top">
<input type="text" name="keep_entries" size="40"
tal:attributes="value props/keep_entries" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Copy exceptions to the event log
</div>
</td>
<td align="left" valign="top">
<input type="checkbox" name="copy_to_zlog"
tal:attributes="checked props/copy_to_zlog;
disabled not:container/checkEventLogPermission|nothing" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Ignored exception types
</div>
</td>
<td align="left" valign="top">
<textarea name="ignored_exceptions:lines" cols="40" rows="3"
tal:content="python: '\n'.join(props['ignored_exceptions'])"></textarea>
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Save Changes " />
</div>
</td>
</tr>
</table>
<h3>Exception Log (most recent first)</h3>
<div tal:define="entries container/getLogEntries">
<em tal:condition="not:entries">
No exceptions logged.
</em>
<table tal:condition="entries">
<tr>
<th align="left">Time</th>
<th align="left">Username (User Id)</th>
<th align="left">Exception</th>
<th></th>
</tr>
<tr tal:repeat="entry entries">
<td valign="top" nowrap="nowrap">
<span tal:content="python: modules['DateTime'].DateTime(entry['time']).Time()">13:04:41</span>
</td>
<td>
<span tal:content="string: ${entry/username} (${entry/userid})">
joe (joe)
</span>
</td>
<td valign="top">
<a href="showEntry" tal:attributes="href string:showEntry?id=${entry/id}"
>
<span tal:content="entry/type">AttributeError</span>:
<span tal:define="value entry/value"
tal:content="python: len(value) &lt; 70 and value or value[:70] + '...'">
Application object has no attribute "zzope"</span>
</a>
</td>
<td><a href="#"
tal:attributes="href string:${context/absolute_url}/forgetEntry?id=${entry/id}"
>Forget this entry</a></td>
</tr>
</table>
</div>
</form>
<p>
<form action="manage_main" method="GET">
<input type="submit" name="submit" value=" Refresh " />
</form>
</p>
<h1 tal:replace="structure context/manage_page_footer">Footer</h1>
<h1 tal:replace="structure here/manage_page_header">Header</h1>
<h1 tal:replace="structure here/manage_tabs">Tabs</h1>
<h3>Exception traceback</h3>
<p>
<form action="manage_main" method="GET">
<input type="submit" name="submit" value=" Return to log " />
</form>
</p>
<div tal:define="entry python:container.getLogEntryById(request.get('id'))">
<em tal:condition="not:entry">
The specified log entry was not found. It may have expired.
</em>
<div tal:condition="entry">
<table>
<tr>
<th align="left" valign="top">Time</th>
<td tal:content="python: modules['DateTime'].DateTime(entry['time'])"></td>
</tr>
<tr>
<th align="left" valign="top">User Name (User Id)</th>
<td tal:content="string: ${entry/username} (${entry/userid})">joe (joe)</td>
</tr>
<tr>
<th align="left" valign="top">Request URL</th>
<td tal:content="entry/url">http://example.com</td>
</tr>
<tr>
<th align="left" valign="top">Exception Type</th>
<td tal:content="entry/type">AttributeError</td>
</tr>
<tr>
<th align="left" valign="top">Exception Value</th>
<td tal:content="entry/value">zzope</td>
</tr>
</table>
<div tal:condition="entry/tb_html" tal:content="structure entry/tb_html">
Traceback (HTML)
</div>
<pre tal:condition="not:entry/tb_html" tal:content="entry/tb_text">
Traceback (text)
</pre>
<p tal:condition="entry/tb_text"><a href="" tal:attributes="href
string:getLogEntryAsText?id=${entry/id}">Display
traceback as text</a></p>
<div tal:condition="entry/req_html">
<p>
<form action="manage_main" method="GET">
<input type="submit" name="submit" value=" Return to log " />
</form>
</p>
<h3>REQUEST</h3>
<div tal:replace="structure entry/req_html"></div>
</div>
</div>
<p>
<form action="manage_main" method="GET">
<input type="submit" name="submit" value=" Return to log " />
</form>
</p>
</div>
<h1 tal:replace="structure here/manage_page_footer">Footer</h1>
...@@ -29,6 +29,7 @@ Products.BTreeFolder2 = 2.13.4 ...@@ -29,6 +29,7 @@ Products.BTreeFolder2 = 2.13.4
Products.ExternalMethod = 2.13.0 Products.ExternalMethod = 2.13.0
Products.MailHost = 2.13.1 Products.MailHost = 2.13.1
Products.PythonScripts = 2.13.2 Products.PythonScripts = 2.13.2
Products.SiteErrorLog = 2.13.2
Products.StandardCacheManagers = 2.13.0 Products.StandardCacheManagers = 2.13.0
# ZTK KGS overrides # ZTK KGS overrides
......
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