launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #13415
[Merge] lp:~beuno/python-oops-tools/show-newest-oopses into lp:python-oops-tools
Martin Albisetti has proposed merging lp:~beuno/python-oops-tools/show-newest-oopses into lp:python-oops-tools.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~beuno/python-oops-tools/show-newest-oopses/+merge/129752
Add an option to see the newest oopses by project.
--
https://code.launchpad.net/~beuno/python-oops-tools/show-newest-oopses/+merge/129752
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~beuno/python-oops-tools/show-newest-oopses into lp:python-oops-tools.
=== modified file 'src/oopstools/oops/dboopsloader.py'
--- src/oopstools/oops/dboopsloader.py 2011-10-21 13:54:29 +0000
+++ src/oopstools/oops/dboopsloader.py 2012-10-15 20:52:24 +0000
@@ -87,7 +87,7 @@
# XXX matsubara: remove the if clause when refactoring this code
# to use a single oops directory.
if type(oopsdir) == str:
- oopsdir = [oopsdir,]
+ oopsdir = [oopsdir, ]
# Walk through all subdirectories containing OOPSes and ensure there
# is a matching database structure for them.
@@ -141,7 +141,7 @@
before_date = date - datetime.timedelta(days=1)
after_date = date + datetime.timedelta(days=2)
query = Oops.objects.filter(
- date__range=(before_date,after_date),
+ date__range=(before_date, after_date),
pathname__startswith=prefix).values_list(
'pathname', flat=True)
oops_reports = set(
@@ -151,7 +151,7 @@
oops = self._load_oops(datedir, filename)
if oops is not None:
yield oops
- # We update the last_date only when oops
+ # We update the last_date only when oops
# has the date different to what we already have
# This speeds up the loading process
if entry.last_date != date:
@@ -177,7 +177,7 @@
# condition.
logger.error(
"OOPS %s/%s already in the DB.", datedir, filename)
- transaction.rollback() # Continue to next one.
+ transaction.rollback() # Continue to next one.
else:
logger.error(
"%s raised with datedir: %s filename: %s ",
=== modified file 'src/oopstools/oops/dbsummaries.py'
--- src/oopstools/oops/dbsummaries.py 2012-09-11 02:08:56 +0000
+++ src/oopstools/oops/dbsummaries.py 2012-10-15 20:52:24 +0000
@@ -32,6 +32,7 @@
#############################################################################
# Groups
+
def _format_http_method_count(data):
tmp = []
for method in TRACKED_HTTP_METHODS + ('Other',):
@@ -40,6 +41,7 @@
tmp.append("%s: %s" % (method, count))
return ' '.join(tmp)
+
def _escape(value):
if value is not None:
if not isinstance(value, unicode):
@@ -333,7 +335,7 @@
'oopsinfestation__exception_value')
)
super(ErrorSection, self).__init__(
- title, errors, max_count, _all_groups = all_groups)
+ title, errors, max_count, _all_groups=all_groups)
class NotFoundSection(ErrorSection):
@@ -362,7 +364,7 @@
'-count', 'most_expensive_statement')
)
super(TimeOutSection, self).__init__(
- title, errors, max_count, _all_groups = all_groups)
+ title, errors, max_count, _all_groups=all_groups)
# We perform the top value queries outside of the ORM for performance.
#
@@ -772,6 +774,7 @@
ErrorSection, dict(title='Exceptions', max_count=50), section_set)
self.addSections(*section_set)
+
class ISDErrorSummary(GenericErrorSummary):
"""Summarize ISD error reports (placeholder)"""
=== modified file 'src/oopstools/oops/helpers.py'
--- src/oopstools/oops/helpers.py 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/helpers.py 2012-10-15 20:52:24 +0000
@@ -101,7 +101,7 @@
def parsedate(date_string):
"""Return a naive date time object for the given string.
- This function ignores subsecond accuracy and the timezone.
+ This function ignores subsecond accuracy and the timezone.
May be used to parse a ISO 8601 date string.
>>> ds = '2009-01-02'
@@ -132,7 +132,7 @@
"""Generate a summary with the given prefix and dates."""
script_cmd = '%s/analyse_error_reports' % settings.BIN_DIR
- args = [script_cmd,]
+ args = [script_cmd, ]
for prefix in prefixes:
args.append("-p%s" % prefix)
for d in (from_date, to_date):
@@ -161,7 +161,7 @@
pos = text.find(pattern)
if pos < 0:
return "Pattern: '%s' not found in %s" % (pattern, text)
- return text[pos+len(pattern):].split("===")[0].strip()
+ return text[pos + len(pattern):].split("===")[0].strip()
def reset_database():
@@ -209,6 +209,7 @@
_cached_launchpadlib = None
+
def get_launchpadlib():
"""Return a launchpadlib instance from the cache.
@@ -225,6 +226,7 @@
_today = None
+
def today():
"""Return a date time object from the cache.
@@ -238,6 +240,6 @@
def load_prefixes(report_name):
"""Return a list of Prefix objects grouped by Report."""
- from oopstools.oops.models import Report
+ from oopstools.oops.models import Report
report = Report.objects.get(name=report_name)
return [prefix.value for prefix in report.prefixes.all()]
=== modified file 'src/oopstools/oops/oopsstore.py'
--- src/oopstools/oops/oopsstore.py 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/oopsstore.py 2012-10-15 20:52:24 +0000
@@ -77,7 +77,7 @@
# XXX matsubara: remove the if clause when refactoring this code
# to use a single oops directory.
if type(oopsdir) == str:
- oopsdir = [oopsdir,]
+ oopsdir = [oopsdir, ]
# XXX matsubara: find_dirs changes directories to do its job and
# before calling it, record the original directory the script is
# in and after it finishes building
@@ -123,7 +123,7 @@
dse = match.group('dse')
oops = match.group('oopsprefix') + match.group('id')
if date:
- pass # got enough data
+ pass # got enough data
elif dse:
# dse is the number of days since the epoch
day = epoch + datetime.timedelta(days=int(dse) - 1)
@@ -145,7 +145,7 @@
# between the OOPS filename and the OOPS id, that's why
# there're two different regex to identify those.
oops_prefix = filename.split(".")[1]
- oops_prefix = re.sub("\d+$", "", oops_prefix)
+ oops_prefix = re.sub("\d+$", "", oops_prefix)
# Normalize oops prefix
return oops_prefix.upper()
@@ -183,3 +183,16 @@
return itertools.ifilter(
lambda oops: startdatetime <= oops.date <= enddatetime,
oops_results)
+
+ def newest(self, limit=50):
+ """Get the newest oopses."""
+ oops_list = dict()
+ for dir in self.oopsdirs:
+ all_dates = os.listdir(dir)
+ if all_dates:
+ all_dates.sort(reverse=True)
+ newest_dir = os.path.join(dir, all_dates[0])
+ oops_list[dir] = os.listdir(newest_dir)[:limit]
+ oops_list[dir].sort(key=lambda x: os.stat(
+ os.path.join(newest_dir, x)).st_mtime, reverse=True)
+ return oops_list
\ No newline at end of file
=== added file 'src/oopstools/oops/templates/newest.html'
--- src/oopstools/oops/templates/newest.html 1970-01-01 00:00:00 +0000
+++ src/oopstools/oops/templates/newest.html 2012-10-15 20:52:24 +0000
@@ -0,0 +1,15 @@
+{% extends "base.html" %}
+
+{% block title %}Newest OOPS Reports{% endblock %}
+
+{% block summaries %}
+
+{% for project_name, oopses in latest_oopses.items %}
+ {{ project_name }}
+ <ul>
+ {% for oops in oopses %}
+ <li><a href="/oops/?oopsid={{ oops }}">{{ oops }}</a></li>
+ {% endfor %}
+ </ul>
+{% endfor %}
+{% endblock %}
=== modified file 'src/oopstools/oops/test/oopsstore.txt'
--- src/oopstools/oops/test/oopsstore.txt 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/test/oopsstore.txt 2012-10-15 20:52:24 +0000
@@ -119,3 +119,35 @@
>>> [oops.oopsid for oops in
... store.search(start_date, end_date, prefixes=['CCW'])]
[]
+
+Show the newest oopses for each directory.
+
+ >>> newest_oopses = store.newest()
+ >>> len(newest_oopses)
+ 2
+
+ >>> newest_oopses.values()
+ [['01149-1925canistelubuntu0.oops'], ['61295.SMPM25']]
+
+newest() can optionally limit the amount of oopses it returns.
+
+ >>> from datetime import date
+ >>> from django.conf import settings
+ >>> from oopstools.oops.helpers import create_fake_oops
+ >>> oops_dir_one = os.path.join(
+ ... settings.OOPSDIR[0], 'dir1', '2008-03-18')
+ >>> fake_oops_one = open(oops_dir_one + "/" + "68350.X1", "w")
+ >>> contents = create_fake_oops(date(2008, 3, 18))
+ >>> fake_oops_one.write(contents)
+ >>> fake_oops_one.close()
+ >>> newest_oopses = store.newest()
+ >>> newest_oopses.values()
+ [['01149-1925canistelubuntu0.oops'], ['68350.X1', '61295.SMPM25']]
+
+When limiting to 1, we only get 1 oops from dir1
+
+ >>> newest_oopses = store.newest(limit=1)
+ >>> newest_oopses.values()
+ [['01149-1925canistelubuntu0.oops'], ['68350.X1']]
+
+ >>> os.remove(fake_oops_one.name)
=== modified file 'src/oopstools/oops/test/test_runner.py'
--- src/oopstools/oops/test/test_runner.py 2011-10-13 20:18:51 +0000
+++ src/oopstools/oops/test/test_runner.py 2012-10-15 20:52:24 +0000
@@ -24,7 +24,8 @@
from django.test.simple import DjangoTestSuiteRunner
DEFAULT_OPTIONS = (
- doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS |doctest.REPORT_NDIFF)
+ doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS | doctest.REPORT_NDIFF)
+
class CustomTestRunner(DjangoTestSuiteRunner):
=== modified file 'src/oopstools/oops/views.py'
--- src/oopstools/oops/views.py 2011-11-03 00:08:18 +0000
+++ src/oopstools/oops/views.py 2012-10-15 20:52:24 +0000
@@ -44,7 +44,7 @@
oopsids.add(query_str.upper())
oopsids.add(query_str.lower())
if not query_str.upper().startswith('OOPS-'):
- oopsids.update(map(lambda x:'OOPS-'+x, oopsids))
+ oopsids.update(map(lambda x: 'OOPS-' + x, oopsids))
# Check each ID in both the database and filesystem
# (should maybe have an API option for this, instead of doing it manually?)
@@ -151,4 +151,9 @@
return render_to_response("summary.html", dictionary=data)
-
+def newest(request):
+ """Show the newest oopses for all projects."""
+ store = OopsStore(settings.OOPSDIR)
+ latest_oopses = store.newest()
+ data = {'latest_oopses': latest_oopses}
+ return render_to_response("newest.html", dictionary=data)
=== modified file 'src/oopstools/urls.py'
--- src/oopstools/urls.py 2011-10-13 20:18:51 +0000
+++ src/oopstools/urls.py 2012-10-15 20:52:24 +0000
@@ -24,7 +24,7 @@
# Example:
# (r'^oopstools/', include('oopstools.foo.urls')),
- # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+ # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
@@ -39,4 +39,5 @@
(r'^oops[.py]*/meta$', 'oopstools.oops.views.meta'),
(r'^oops/static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_DOC_ROOT}),
+ (r'^newest/$', 'oopstools.oops.views.newest')
)