Merge lp:~matsubara/lp-devops-dashboard/929538-incident-reports-record into lp:lp-devops-dashboard

Proposed by Diogo Matsubara
Status: Merged
Approved by: Diogo Matsubara
Approved revision: 50
Merged at revision: 48
Proposed branch: lp:~matsubara/lp-devops-dashboard/929538-incident-reports-record
Merge into: lp:lp-devops-dashboard
Diff against target: 244 lines (+106/-34)
6 files modified
buildout.cfg (+0/-2)
src/devops/incidentreports.py (+25/-13)
src/devops/tests/sample_data/incident-reports.html (+42/-0)
src/devops/tests/test_fetchbugs.py (+0/-11)
src/devops/tests/test_incidentreports.py (+31/-0)
versions.cfg (+8/-8)
To merge this branch: bzr merge lp:~matsubara/lp-devops-dashboard/929538-incident-reports-record
Reviewer Review Type Date Requested Status
Ian Booth (community) code Approve
Review via email: mp+92359@code.launchpad.net

Commit message

fix bug #929538: Wrong calculation of number of days without incident reports

Description of the change

This branch fixes how the day since the last incident report is calculated. The current code does a delta between incident records to find out how many days we had without incidents. The fix take into account the delta between today and the day of the last incident.

Also added tests for the incidentreports.py module and updated some dependencies with the dependencies available in the download-cache.

To post a comment you must log in.
50. By Diogo Matsubara

oops, forgot to add the test file and sample data

Revision history for this message
Ian Booth (wallyworld) wrote :

Hi there

I have perhaps a dumb question - if we are intending to show the days since the last incident report, is the comparison used in the code the wrong way around?

89 + if current and ((today() - current) > overall_delta):
90 + overall_delta = today() - current

The above code will end up finding the number of days since the oldest incident report I think? Where as we want the number of days since the latest incident report, so it should be:

if current and ((today() - current) < overall_delta):

The attribute used to hold the delta value, "most_days_with_no_incidents" seems incorrectly named now that we are changing the semantics of the calculation. It should now really be called "days_since_last_incident".

If what I say above is correct, then the tests are incorrect, eg:

183 + def test_get_last_reports_since(self):
184 + incidentreports._today = datetime(2011, 11, 9)
185 + self.ir.get_last_reports_since()
186 + self.assertEqual(self.ir.total_incidents, 7)
187 + self.assertEqual(self.ir.most_days_with_no_incidents, 89)
188 + self.assertEqual(self.ir.last_report, '2011-11-07-LP-some-error')

The latest incident report in the sample data is 2011-11-07 and "today" is 2011-11-09, so I would expect the days since last incident report to be 2.

review: Needs Information (code)
Revision history for this message
Diogo Matsubara (matsubara) wrote :

I replied by email but it didn't show up here.

On Thu, Feb 9, 2012 at 11:16 PM, Ian Booth <email address hidden> wrote:
> Review: Needs Information code
>
> Hi there

Hi Ian, thanks for the review!

>
> I have perhaps a dumb question - if we are intending to show the days since the last incident report, is the comparison used in the code the wrong way around?
>

We don't want to show the days since the last incident report, we want
to show how many days we managed to stay with no incidents. Kinda like
those signs on heavy traffic roads where they say: XX days without any
fatal accidents/crashes.

The days since the last incident report is already in the page.

> 89 + if current and ((today() - current) > overall_delta):
> 90 + overall_delta = today() - current
>
> The above code will end up finding the number of days since the oldest incident report I think? Where as we want the number of days since the latest incident report, so it should be:
>
> if current and ((today() - current) < overall_delta):
>
> The attribute used to hold the delta value, "most_days_with_no_incidents" seems incorrectly named now that we are changing the semantics of the calculation. It should now really be called "days_since_last_incident".
>

Given the reason above, I think the attribute is correctly named.

> If what I say above is correct, then the tests are incorrect, eg:
>
> 183 + def test_get_last_reports_since(self):
> 184 + incidentreports._today = datetime(2011, 11, 9)
> 185 + self.ir.get_last_reports_since()
> 186 + self.assertEqual(self.ir.total_incidents, 7)
> 187 + self.assertEqual(self.ir.most_days_with_no_incidents, 89)
> 188 + self.assertEqual(self.ir.last_report, '2011-11-07-LP-some-error')
>
> The latest incident report in the sample data is 2011-11-07 and "today" is 2011-11-09, so I would expect the days since last incident report to be 2.
>
> --
> https://code.launchpad.net/~matsubara/lp-devops-dashboard/929538-incident-reports-record/+merge/92359
> You are the owner of lp:~matsubara/lp-devops-dashboard/929538-incident-reports-record.

Is this ok to land?

Cheers,

Diogo

Revision history for this message
Ian Booth (wallyworld) wrote :

Hi

I understand now, thanks for the explanation. I was initially unclear what was being calculated.

>
> We don't want to show the days since the last incident report, we want
> to show how many days we managed to stay with no incidents. Kinda like
> those signs on heavy traffic roads where they say: XX days without any
> fatal accidents/crashes.
>
> The days since the last incident report is already in the page.
>

The XX days example above - I now understand that we want the greatest XX value over the time period of the report, including the time between today and the last incident.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout.cfg'
2--- buildout.cfg 2011-04-22 20:07:49 +0000
3+++ buildout.cfg 2012-02-09 20:17:56 +0000
4@@ -19,8 +19,6 @@
5
6 extends = versions.cfg
7
8-allow-picked-versions = false
9-
10 prefer-final = true
11
12 versions = versions
13
14=== modified file 'src/devops/incidentreports.py'
15--- src/devops/incidentreports.py 2011-04-21 23:02:24 +0000
16+++ src/devops/incidentreports.py 2012-02-09 20:17:56 +0000
17@@ -3,10 +3,22 @@
18 from BeautifulSoup import BeautifulSoup
19 from devops.utils import days_ago, last_date_delta
20
21-### Find last LP incident report
22+
23+_today = None
24+
25+def today():
26+ """Return a date time object from the cache.
27+
28+ This function makes it easy for test to use a cached date rather than the
29+ real date.
30+ """
31+ if _today is not None:
32+ return _today
33+ return datetime.today()
34
35
36 class Wiki:
37+
38 def __init__(self, url):
39 self.url = url
40 self.contents = []
41@@ -20,7 +32,11 @@
42 self.read_contents(moinfile)
43 return 1
44
45- if not editshortcut(self.url, action="print", editfile_func=editfunc,
46+ # If it's a local file, just read it rather than trying to open it
47+ # with editmoin.
48+ if self.url.startswith('/'):
49+ self.data = open(self.url).read()
50+ elif not editshortcut(self.url, action="print", editfile_func=editfunc,
51 change_page=False):
52 # Someone else was editing the page. Raise an exception
53 raise Exception("Couldn't get write lock for the wiki page. "
54@@ -30,19 +46,11 @@
55 self.data = moinfile._unescape(moinfile.data)
56
57
58-class Reports:
59+class IncidentReports:
60
61- def __init__(sel, source_url):
62+ def __init__(self, since=datetime(2011, 01, 01),
63+ source_url="https://wiki.canonical.com/IncidentReports"):
64 self.source_url = source_url
65-
66- def fetch_data(self):
67- raise NotImplementedError
68-
69-
70-class IncidentReports:
71-
72- def __init__(self, since=datetime(2011, 01, 01)):
73- self.source_url = "https://wiki.canonical.com/IncidentReports"
74 self.all_reports = []
75 # { Date : report}
76 self.lp_reports = {}
77@@ -111,6 +119,7 @@
78
79 overall_delta = timedelta(0)
80
81+ current = None
82 for i, report in enumerate(sorted(last_reports)):
83 current = report
84 if i == 0:
85@@ -121,6 +130,9 @@
86 overall_delta = current_delta
87 previous = current
88
89+ if current and ((today() - current) > overall_delta):
90+ overall_delta = today() - current
91+
92 self.most_days_with_no_incidents = overall_delta.days
93 self.total_incidents = len(last_reports)
94 self.last_report = self.lp_reports[current][0]
95
96=== added file 'src/devops/tests/sample_data/incident-reports.html'
97--- src/devops/tests/sample_data/incident-reports.html 1970-01-01 00:00:00 +0000
98+++ src/devops/tests/sample_data/incident-reports.html 2012-02-09 20:17:56 +0000
99@@ -0,0 +1,42 @@
100+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
101+<html>
102+<head>
103+<title>IncidentReports - Canonical Wiki</title>
104+</head>
105+
106+<body>
107+ <ol>
108+ <li>
109+ <a href="/IncidentReports/2011-01-16-LP-Rollout"><strong>IncidentReports/</strong>2011-01-16-LP-Rollout</a>
110+ </li>
111+ <li>
112+ <a href="/IncidentReports/2011-01-24-U1-Borkness"><strong>IncidentReports/</strong>2011-01-24-U1-Borkness</a>
113+ </li>
114+ <li>
115+ <a href="/IncidentReports/2011-02-13-LP-Foobar"><strong>IncidentReports/</strong>2011-02-13-LP-Foobar</a>
116+ </li>
117+ <li>
118+ <a href="/IncidentReports/2011-02-25-ISD-Snafu"><strong>IncidentReports/</strong>2011-02-25-ISD-Snafu</a>
119+ </li>
120+ <li>
121+ <a href="/IncidentReports/2011-03-03-Linaro-Doom"><strong>IncidentReports/</strong>2011-03-03-Linaro-Doom</a>
122+ </li>
123+ <li>
124+ <a href="/IncidentReports/2011-03-22-LP-Everything-on-fire"><strong>IncidentReports/</strong>2011-03-22-LP-Everything-on-fire</a>
125+ </li>
126+ <li>
127+ <a href="/IncidentReports/2011-04-21-LP-Chaos"><strong>IncidentReports/</strong>2011-04-21-LP-Chaos</a>
128+ </li>
129+ <li>
130+ <a href="/IncidentReports/2011-06-18-LP-Armaggedon"><strong>IncidentReports/</strong>2011-06-18-LP-Armaggedon</a>
131+ </li>
132+ <li>
133+ <a href="/IncidentReports/2011-08-10-LP-Apocalypse"><strong>IncidentReports/</strong>2011-08-10-LP-Apocalypse</a>
134+ </li>
135+ <li>
136+ <a href="/IncidentReports/2011-11-07-LP-some-error"><strong>IncidentReports/</strong>2011-11-07-LP-some-error</a>
137+ </li>
138+ </ol>
139+</body>
140+</html>
141+
142
143=== modified file 'src/devops/tests/test_fetchbugs.py'
144--- src/devops/tests/test_fetchbugs.py 2011-06-08 02:23:04 +0000
145+++ src/devops/tests/test_fetchbugs.py 2012-02-09 20:17:56 +0000
146@@ -50,14 +50,3 @@
147
148 self.assertEqual(len(self.lp_bugs.fetch_critical_bugs()), 4)
149 self.assertEqual(len(self.lp_bugs.fetch_open_critical_bugs()), 3)
150-
151-
152-
153-
154-
155-
156-
157-
158-
159-
160-
161
162=== added file 'src/devops/tests/test_incidentreports.py'
163--- src/devops/tests/test_incidentreports.py 1970-01-01 00:00:00 +0000
164+++ src/devops/tests/test_incidentreports.py 2012-02-09 20:17:56 +0000
165@@ -0,0 +1,31 @@
166+from datetime import datetime
167+from os.path import dirname, join
168+from unittest import TestCase
169+from urlparse import urljoin
170+
171+from devops import incidentreports
172+from devops.incidentreports import IncidentReports
173+
174+
175+class TestIncidentReports(TestCase):
176+
177+
178+ def setUp(self):
179+ source_url = join(
180+ dirname(__file__), "sample_data", "incident-reports.html")
181+ self.ir = IncidentReports(source_url=source_url)
182+
183+ def test_get_last_reports_since(self):
184+ incidentreports._today = datetime(2011, 11, 9)
185+ self.ir.get_last_reports_since()
186+ self.assertEqual(self.ir.total_incidents, 7)
187+ self.assertEqual(self.ir.most_days_with_no_incidents, 89)
188+ self.assertEqual(self.ir.last_report, '2011-11-07-LP-some-error')
189+
190+ def test_no_incidents_for_a_long_time(self):
191+ # Test when the last incident report is older than the delta between
192+ # incident reports. Bug 929538
193+ incidentreports._today = datetime(2012, 2, 9)
194+ self.ir.get_last_reports_since()
195+ self.assertEqual(self.ir.most_days_with_no_incidents, 94)
196+ self.assertEqual(self.ir.last_report, '2011-11-07-LP-some-error')
197
198=== modified file 'versions.cfg'
199--- versions.cfg 2011-04-22 20:11:46 +0000
200+++ versions.cfg 2012-02-09 20:17:56 +0000
201@@ -11,13 +11,13 @@
202 setuptools = 0.6c11
203 testtools = 0.9.4
204 z3c.recipe.scripts = 1.0.1
205-z3c.recipe.tag = 0.2.0
206+z3c.recipe.tag = 0.4.0
207 zc.buildout = 1.5.1
208 zc.recipe.egg = 1.3.2
209 zc.recipe.testrunner = 1.4.0
210 zc.sourcerelease = 0.3.1
211 zope.exceptions = 3.5.2
212-zope.interface = 3.5.1
213+zope.interface = 3.8.0
214 zope.testing = 3.10.2
215 zope.testrunner = 4.0.3
216
217@@ -25,7 +25,7 @@
218 BeautifulSoup = 3.2.0
219
220 # bzr
221-bzr = 2.1.0
222+bzr = 2.5.0dev5-r6402
223
224 # genshi
225 genshi = 0.6
226@@ -33,13 +33,13 @@
227 # launchpadlib
228 elementtree = 1.2.6-20050316
229 httplib2 = 0.6.0
230-launchpadlib = 1.6.4
231-lazr.authentication = 0.1.2
232-lazr.restfulclient = 0.11.1
233+launchpadlib = 1.9.12
234+lazr.authentication = 0.1.1
235+lazr.restfulclient = 0.12.0
236 lazr.uri = 1.0.2
237 oauth = 1.0.1
238-simplejson = 2.1.1
239-wadllib = 1.1.8
240+simplejson = 2.2.1
241+wadllib = 1.2.0
242 wsgi-intercept = 0.4
243
244 # mocker

Subscribers

People subscribed via source and target branches

to all changes: