1
# Copyright 2005-2011 Canonical Ltd. All rights reserved.
3
# This program is free software: you can redistribute it and/or modify
4
# it under the terms of the GNU Affero General Public License as published by
5
# the Free Software Foundation, either version 3 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU Affero General Public License for more details.
13
# You should have received a copy of the GNU Affero General Public License
14
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
from django.conf import settings
22
"""Group of OOPS with a particular exception type and value"""
23
def __init__(self, etype, evalue):
29
self.local_referrers = 0
32
self.request_methods = {"POST": 0, "GET": 0, "Other": 0}
33
self.referrer_urls = {}
35
def addOops(self, oops):
36
# Ideally the assert would be done on etype and evalue. Assert is not
37
# done on evalue because the evalue is pre-processed while
38
# oops.exception_value is the raw value generated by the web
39
# application. Assert on etype only is good enough, though.
40
# XXX matsubara: this doesn't work anymore when using the Django
41
# objects. Corresponding test was disabled as well.
42
#assert self.etype == oops.exception_type, (
43
# "Oops etype: '%s' doesn't match group etype: '%s'" %
44
# (oops.exception_type, self.etype))
45
self.urls.setdefault(oops.url, set()).add(oops.oopsid)
47
if oops.url.startswith(pageid):
49
self.pageids[oops.url] = pageid
51
self.bug = oops.oopsinfestation.bug
52
referrer = oops.referrer
53
if self._isLocalReferrer(referrer):
54
self.local_referrers += 1
55
if referrer in self.referrer_urls.keys():
56
self.referrer_urls[referrer] += 1
58
self.referrer_urls[referrer] = 1
61
if oops.http_method in ["POST", "GET"]:
62
self.request_methods[oops.http_method] += 1
64
self.request_methods["Other"] += 1
66
def renderTXT(self, fp):
67
"""Render this group in plain text."""
68
fp.write('%4d %s: %s\n' % (self.count, self.etype, self.evalue))
70
fp.write(' Bug: https://launchpad.net/bugs/%s\n' % self.bug)
71
if self.etype == 'NotFound' and self.local_referrers:
73
' %s Robots: %d Local: %d Most Common Referrer: %s\n'
74
% (self.formatted_request_methods, self.bots,
75
self.local_referrers, self.printTopReferrer()))
77
fp.write(' %s Robots: %d Local: %d\n' %
78
(self.formatted_request_methods, self.bots,
79
self.local_referrers))
80
urls = sorted(((len(oopsids), url) for (url, oopsids)
81
in self.urls.iteritems()),
83
# print the first three URLs
84
for (count, url) in urls[:3]:
85
fp.write(' %4d %s (%s)\n' % (count, url, self.pageids[url]))
87
' %s\n' % ', '.join(sorted(self.urls[url])[:5]))
89
fp.write(' [%s other URLs]\n' % (len(urls) - 3))
92
def renderHTML(self, fp):
93
"""Render this group in HTML."""
94
fp.write('<div class="exc">%d <b>%s</b>: %s</div>\n'
95
% (self.count, cgi.escape(self.etype),
96
cgi.escape(self.evalue)))
98
bug_link = "https://launchpad.net/bugs/%s" % self.bug
99
fp.write('Bug: <a href="%s">%s</a>\n' % (bug_link, self.bug))
100
if self.etype == 'NotFound' and self.local_referrers:
101
top_referrer = cgi.escape(self.printTopReferrer())
102
fp.write('<div class="pct">%s Robots: %d Local: %d Most '
103
'Common Referrer: <a href="%s">%s</a></ul></div>\n'
104
% (self.formatted_request_methods, self.bots,
105
self.local_referrers, top_referrer, top_referrer))
107
fp.write('<div class="pct">%s Robots: %d Local: %d</div>\n'
108
% (self.formatted_request_methods, self.bots,
109
self.local_referrers))
110
urls = self.errorUrls()
111
# print the first five URLs
113
for (count, url) in urls[:5]:
114
fp.write('<li>%d <a class="errurl" href="%s">%s</a> (%s)\n' %
115
(count, cgi.escape(url), cgi.escape(url),
117
sample_oopses = sorted(self.urls[url])[:10]
119
'<a href="%s/oops/?oopsid=%s">%s</a>' % (
120
settings.ROOT_URL, oops, oops)
121
for oops in sample_oopses]
122
fp.write('<ul class="oops"><li>%s</li></ul>\n' %
123
', '.join(sample_oops_urls))
126
fp.write('<li>[%d more]</li>\n' % (len(urls) - 5))
127
fp.write('</ul>\n\n')
130
#XXX missing test and docstring and better name
131
return sorted(((len(oopsids), url) for (url, oopsids)
132
in self.urls.iteritems()), reverse=True)
134
def printTopReferrer(self):
135
top_referrers = sorted(self.referrer_urls.items(),
136
key=lambda (x,y): (y,x), reverse=True)
137
return top_referrers[0][0]
140
def formatted_request_methods(self):
141
formatted_output = ''
142
for method, count in self.request_methods.iteritems():
143
if self.request_methods[method]:
144
formatted_output += "%s: %s " % (method, count)
145
return formatted_output
147
def _isLocalReferrer(self, referrer):
148
"""Return True if 'referrer' is a local domain like launchpad.net or
151
url, query = urllib.splitquery(referrer)
152
if 'launchpad.net' in url or 'ubuntu.com' in url: