Skip to content

Commit e44cac0

Browse files
authored
Merge branch 'add-reponse-times-bugzilla' of 'https://github.com/sduenas/grimoirelab-elk/'
Merges #1171 Closes #1171
2 parents ef7d581 + ceb1c9b commit e44cac0

File tree

7 files changed

+268
-16
lines changed

7 files changed

+268
-16
lines changed

grimoire_elk/enriched/bugzilla.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,29 @@ def get_rich_item(self, item):
195195

196196
# Add extra JSON fields used in Kibana (enriched fields)
197197
eitem['comments'] = 0
198+
eitem['last_comment_date'] = None
198199
eitem['url'] = None
199200

200201
if 'long_desc' in issue:
201202
eitem['comments'] = len(issue['long_desc'])
203+
204+
last_comment_date = None
205+
206+
if eitem['comments'] > 1:
207+
last_comment = issue['long_desc'][-1]
208+
last_comment_date = str_to_datetime(last_comment['bug_when'][0]['__text__'])
209+
last_comment_date = last_comment_date.isoformat()
210+
211+
eitem['last_comment_date'] = last_comment_date
212+
202213
eitem['url'] = item['origin'] + "/show_bug.cgi?id=" + issue['bug_id'][0]['__text__']
203214
eitem['resolution_days'] = \
204215
get_time_diff_days(eitem['creation_date'], eitem['delta_ts'])
205216
eitem['timeopen_days'] = \
206217
get_time_diff_days(eitem['creation_date'], datetime_utcnow().replace(tzinfo=None))
218+
eitem['time_to_first_attention'] = \
219+
get_time_diff_days(eitem['creation_date'],
220+
self.get_time_to_first_attention(issue))
207221

208222
if self.sortinghat:
209223
eitem.update(self.get_item_sh(item, self.roles))
@@ -216,3 +230,29 @@ def get_rich_item(self, item):
216230
self.add_repository_labels(eitem)
217231
self.add_metadata_filter_raw(eitem)
218232
return eitem
233+
234+
def get_time_to_first_attention(self, item):
235+
"""Set the time to first attention.
236+
237+
This date is defined as the first date at which a comment by someone
238+
other than the user who created the issue.
239+
"""
240+
if 'long_desc' not in item:
241+
return None
242+
243+
comment_dates = []
244+
reporter = item['reporter'][0]['__text__']
245+
246+
# First comment is the description of the issue
247+
# Real comments start at the second position (index 1)
248+
for comment in item['long_desc'][1:]:
249+
user = comment['who'][0]['__text__']
250+
if user == reporter:
251+
continue
252+
dt = str_to_datetime(comment['bug_when'][0]['__text__']).replace(tzinfo=None)
253+
comment_dates.append(dt)
254+
255+
if comment_dates:
256+
return min(comment_dates)
257+
else:
258+
return None

grimoire_elk/enriched/bugzillarest.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,29 @@ def get_rich_item(self, item):
136136

137137
# Add extra JSON fields used in Kibana (enriched fields)
138138
eitem['comments'] = 0
139+
eitem['last_comment_date'] = None
139140
eitem['number_of_comments'] = 0
140141
eitem['time_to_last_update_days'] = None
142+
eitem['time_to_first_attention'] = None
141143
eitem['url'] = None
142144

143145
# Add the field to know if the ticket is open
144146
eitem['is_open'] = issue.get('is_open', None)
145147

146148
if 'long_desc' in issue:
147149
eitem['number_of_comments'] = len(issue['long_desc'])
150+
148151
if 'comments' in issue:
149152
eitem['comments'] = len(issue['comments'])
153+
154+
last_comment_date = None
155+
156+
if eitem['comments'] > 1:
157+
last_comment_date = str_to_datetime(issue['comments'][-1]['time'])
158+
last_comment_date = last_comment_date.isoformat()
159+
160+
eitem['last_comment_date'] = last_comment_date
161+
150162
eitem['url'] = item['origin'] + "/show_bug.cgi?id=" + str(issue['id'])
151163
eitem['time_to_last_update_days'] = \
152164
get_time_diff_days(eitem['creation_ts'], eitem['delta_ts'])
@@ -155,6 +167,9 @@ def get_rich_item(self, item):
155167
if 'is_open' in issue and not issue['is_open']:
156168
eitem['timeopen_days'] = eitem['time_to_last_update_days']
157169

170+
eitem['time_to_first_attention'] = \
171+
get_time_diff_days(eitem['creation_ts'], self.get_time_to_first_attention(issue))
172+
158173
eitem['changes'] = 0
159174
for history in issue['history']:
160175
if 'changes' in history:
@@ -177,3 +192,28 @@ def get_rich_item(self, item):
177192
self.add_repository_labels(eitem)
178193
self.add_metadata_filter_raw(eitem)
179194
return eitem
195+
196+
def get_time_to_first_attention(self, item):
197+
"""Set the time to first attention.
198+
199+
This date is defined as the first date at which a comment by someone
200+
other than the user who created the issue.
201+
"""
202+
if 'comments' not in item:
203+
return None
204+
205+
comment_dates = []
206+
creator = item['creator']
207+
208+
# First comment is the description of the issue
209+
# Real comments start at the second position (index 1)
210+
for comment in item['comments'][1:]:
211+
user = comment['creator']
212+
if user == creator:
213+
continue
214+
comment_dates.append(str_to_datetime(comment['time']).replace(tzinfo=None))
215+
216+
if comment_dates:
217+
return min(comment_dates)
218+
else:
219+
return None
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: New reponse times on bugzilla items
3+
category: added
4+
author: Santiago Dueñas <sduenas@bitergia.com>
5+
issue: null
6+
notes: >
7+
The Bugzilla enriched items include two new
8+
fields to track response times on these type
9+
of repositories.
10+
The field `time_to_first_attention` is the
11+
the time expressed in days between the ticket
12+
creation and the first comment from a contributor
13+
different from the author creating the bug.
14+
The field `last_comment_date` is the date of
15+
the last comment posted in the bug.

schema/bugzilla.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ is_bugzillarest_bugrest,long
5858
is_open,boolean
5959
keywords,keyword
6060
labels,list
61+
last_comment_date,date
6162
main_description,keyword
6263
main_description_analyzed,string,false
6364
metadata__enriched_on,date
@@ -110,6 +111,7 @@ severity,keyword
110111
status,keyword
111112
tag,keyword
112113
timeopen_days,float
114+
time_to_first_attention,float
113115
url,keyword
114116
uuid,keyword
115117
whiteboard,keyword

tests/data/bugzilla.json

Lines changed: 106 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@
181181
],
182182
"reporter": [
183183
{
184-
"__text__": "rocapal@example.org",
185-
"name": "Roberto Calvo"
184+
"__text__": "sduenas@example.org",
185+
"name": "Santiago Due\u00f1as"
186186
}
187187
],
188188
"reporter_accessible": [
@@ -507,8 +507,8 @@
507507
],
508508
"reporter": [
509509
{
510-
"__text__": "rocapal@example.org",
511-
"name": "Roberto Calvo"
510+
"__text__": "sduenas@example.org",
511+
"name": "Santiago Due\u00f1as"
512512
}
513513
],
514514
"reporter_accessible": [
@@ -668,8 +668,8 @@
668668
],
669669
"who": [
670670
{
671-
"__text__": "sduenas@example.org",
672-
"name": "Santiago Due\u00f1as"
671+
"__text__": "dizquierdo@example.org",
672+
"name": "Daniel Izquierdo Cortazar"
673673
}
674674
]
675675
}
@@ -1026,8 +1026,8 @@
10261026
],
10271027
"reporter": [
10281028
{
1029-
"__text__": "rocapal@example.com",
1030-
"name": "Roberto Calvo"
1029+
"__text__": "sduenas@example.org",
1030+
"name": "Santiago Due\u00f1as"
10311031
}
10321032
],
10331033
"reporter_accessible": [
@@ -1251,8 +1251,8 @@
12511251
],
12521252
"reporter": [
12531253
{
1254-
"__text__": "rocapal@example.org",
1255-
"name": "Roberto Calvo"
1254+
"__text__": "sduenas@example.org",
1255+
"name": "Santiago Due\u00f1as"
12561256
}
12571257
],
12581258
"reporter_accessible": [
@@ -1446,8 +1446,8 @@
14461446
],
14471447
"reporter": [
14481448
{
1449-
"__text__": "dizquierdo@example.org",
1450-
"name": "Daniel Izquierdo Cortazar"
1449+
"__text__": "sduenas@example.org",
1450+
"name": "Santiago Due\u00f1as"
14511451
}
14521452
],
14531453
"reporter_accessible": [
@@ -1661,7 +1661,7 @@
16611661
],
16621662
"creation_ts": [
16631663
{
1664-
"__text__": "2015-05-23 06:06:06 +0200"
1664+
"__text__": "2013-06-25 11:49:36 +0200"
16651665
}
16661666
],
16671667
"delta_ts": [
@@ -1720,7 +1720,7 @@
17201720
],
17211721
"bug_when": [
17221722
{
1723-
"__text__": "2013-06-25 11:55:46 +0200"
1723+
"__text__": "2013-07-01 12:00:00 +0200"
17241724
}
17251725
],
17261726
"commentid": [
@@ -1740,6 +1740,96 @@
17401740
"name": "Santiago Due\u00f1as"
17411741
}
17421742
]
1743+
},
1744+
{
1745+
"__text__": "\n ",
1746+
"attachid": [
1747+
{
1748+
"__text__": "172"
1749+
}
1750+
],
1751+
"bug_when": [
1752+
{
1753+
"__text__": "2014-06-25 11:55:46 +0200"
1754+
}
1755+
],
1756+
"commentid": [
1757+
{
1758+
"__text__": "1086"
1759+
}
1760+
],
1761+
"isprivate": "0",
1762+
"thetext": [
1763+
{
1764+
"__text__": "This patch is great"
1765+
}
1766+
],
1767+
"who": [
1768+
{
1769+
"__text__": "lcanas@example.org",
1770+
"name": "Luis Ca\u00f1as"
1771+
}
1772+
]
1773+
},
1774+
{
1775+
"__text__": "\n ",
1776+
"attachid": [
1777+
{
1778+
"__text__": "172"
1779+
}
1780+
],
1781+
"bug_when": [
1782+
{
1783+
"__text__": "2014-06-25 11:55:46 +0200"
1784+
}
1785+
],
1786+
"commentid": [
1787+
{
1788+
"__text__": "1086"
1789+
}
1790+
],
1791+
"isprivate": "0",
1792+
"thetext": [
1793+
{
1794+
"__text__": "Thanks!"
1795+
}
1796+
],
1797+
"who": [
1798+
{
1799+
"__text__": "sduenas@example.org",
1800+
"name": "Santiago Due\u00f1as"
1801+
}
1802+
]
1803+
},
1804+
{
1805+
"__text__": "\n ",
1806+
"attachid": [
1807+
{
1808+
"__text__": "172"
1809+
}
1810+
],
1811+
"bug_when": [
1812+
{
1813+
"__text__": "2014-08-01 11:55:46 +0200"
1814+
}
1815+
],
1816+
"commentid": [
1817+
{
1818+
"__text__": "1086"
1819+
}
1820+
],
1821+
"isprivate": "0",
1822+
"thetext": [
1823+
{
1824+
"__text__": "Applied"
1825+
}
1826+
],
1827+
"who": [
1828+
{
1829+
"__text__": "sduenas@example.org",
1830+
"name": "Santiago Due\u00f1as"
1831+
}
1832+
]
17431833
}
17441834
],
17451835
"op_sys": [
@@ -1770,8 +1860,8 @@
17701860
],
17711861
"reporter": [
17721862
{
1773-
"__text__": "carlosgc@example.com",
1774-
"name": "Carlos Garcia Campos"
1863+
"__text__": "sduenas@example.org",
1864+
"name": "Santiago Due\u00f1as"
17751865
}
17761866
],
17771867
"reporter_accessible": [

tests/test_bugzilla.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# Alvaro del Castillo <acs@bitergia.com>
2020
# Valerio Cosentino <valcos@bitergia.com>
2121
#
22+
2223
import logging
2324
import unittest
2425

@@ -93,6 +94,38 @@ def test_enrich_keywords(self):
9394
eitem = enrich_backend.get_rich_item(item)
9495
self.assertEqual(eitem['keywords'], [])
9596

97+
def test_time_to_first_attention(self):
98+
"""Test whether time_to_first_attention is calculated"""
99+
100+
self._test_raw_to_enrich()
101+
enrich_backend = self.connectors[self.connector][2]()
102+
103+
expected = [None, None, None, None, None, None, 365]
104+
105+
for index in range(0, len(self.items)):
106+
eitem = enrich_backend.get_rich_item(self.items[index])
107+
self.assertEqual(eitem['time_to_first_attention'], expected[index])
108+
109+
def test_last_comment_date(self):
110+
"""Test whether last_comment_date is added to the enriched item"""
111+
112+
self._test_raw_to_enrich()
113+
enrich_backend = self.connectors[self.connector][2]()
114+
115+
expected = [
116+
"2013-06-25T11:55:46+02:00",
117+
"2013-06-25T11:55:46+02:00",
118+
None,
119+
"2013-06-25T11:55:46+02:00",
120+
"2013-06-25T11:55:46+02:00",
121+
None,
122+
"2014-08-01T11:55:46+02:00"
123+
]
124+
125+
for index in range(0, len(self.items)):
126+
eitem = enrich_backend.get_rich_item(self.items[index])
127+
self.assertEqual(eitem['last_comment_date'], expected[index])
128+
96129
def test_raw_to_enrich_sorting_hat(self):
97130
"""Test enrich with SortingHat"""
98131

0 commit comments

Comments
 (0)