Merge lp:~gmb/maas/fix-bug-1402237-1.7 into lp:maas/1.7

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 3332
Proposed branch: lp:~gmb/maas/fix-bug-1402237-1.7
Merge into: lp:maas/1.7
Diff against target: 69 lines (+29/-8)
2 files modified
src/maasserver/views/nodes.py (+19/-8)
src/maasserver/views/tests/test_nodes.py (+10/-0)
To merge this branch: bzr merge lp:~gmb/maas/fix-bug-1402237-1.7
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+244986@code.launchpad.net

Commit message

When fetching the non-debug events for a node, fetch the non-debug EventTypes first and then query the Event table using 'WHERE type_id IN <non-debug-EventTypes>'.

Previously, this query was the default Django-generated one, which did an INNER JOIN between Event and EventType. The new version is significantly faster, because there's an index missing on EventType.level which makes things slow at scale.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

Looks good. Couple of remarks below but nothing major.

[0]

Typo in the commit message: fecthing

[1]

Could you say in the commit message why we're using this trick instead of adding the index… and that the index is being added to trunk…?

review: Approve
Revision history for this message
Graham Binns (gmb) :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/views/nodes.py'
2--- src/maasserver/views/nodes.py 2014-12-10 16:28:52 +0000
3+++ src/maasserver/views/nodes.py 2014-12-18 13:51:39 +0000
4@@ -81,7 +81,10 @@
5 Tag,
6 )
7 from maasserver.models.config import Config
8-from maasserver.models.event import Event
9+from maasserver.models.event import (
10+ Event,
11+ EventType,
12+ )
13 from maasserver.models.nodeprobeddetails import get_single_probed_details
14 from maasserver.node_action import ACTIONS_DICT
15 from maasserver.node_constraint_filter_forms import (
16@@ -238,17 +241,25 @@
17 # Add event information to the generated node dictionary. We exclude
18 # debug after we calculate the count, so we show the correct total
19 # number of events.
20- events = Event.objects.filter(node=node)
21- total_num_events = events.count()
22- events = events.exclude(type__level=logging.DEBUG).order_by('-id')
23- events_count = events.count()
24+ node_events = Event.objects.filter(node=node)
25+ total_num_events = node_events.count()
26+
27+ # We fetch the IDs of the EventTypes that are non-DEBUG here
28+ # because in MAAS 1.7 the EventType.level field is missing an
29+ # index. That makes querying for Events whose EventType has a
30+ # non-DEBUG level (using an INNER JOIN) slow at scale. Doing it
31+ # this way speeds things up considerably.
32+ non_debug_event_type_ids = EventType.objects.exclude(
33+ level=logging.DEBUG).values_list('id', flat=True)
34+ non_debug_events = node_events.filter(
35+ type__id__in=non_debug_event_type_ids).order_by('-id')
36 if event_log_count > 0:
37 # Limit the number of events.
38- events = events.all()[:event_log_count]
39- events_count = len(events)
40+ events = non_debug_events.all()[:event_log_count]
41+ displayed_events_count = len(events)
42 node_dict['events'] = dict(
43 total=total_num_events,
44- count=events_count,
45+ count=displayed_events_count,
46 events=[event_to_dict(event) for event in events],
47 more_url=reverse('node-event-list-view', args=[node.system_id]),
48 )
49
50=== modified file 'src/maasserver/views/tests/test_nodes.py'
51--- src/maasserver/views/tests/test_nodes.py 2014-12-15 10:04:18 +0000
52+++ src/maasserver/views/tests/test_nodes.py 2014-12-18 13:51:39 +0000
53@@ -164,6 +164,16 @@
54 dict_node['events']['more_url'],
55 Equals(reverse('node-event-list-view', args=[node.system_id])))
56
57+ def test_node_to_dict_excludes_debug_events(self):
58+ node = factory.make_Node()
59+ debug_type = factory.make_EventType(level=logging.DEBUG)
60+ debug_event = factory.make_Event(node, debug_type)
61+
62+ node_dict = node_to_dict(node, event_log_count=2)
63+ self.assertThat(
64+ [event_dict['id'] for event_dict in node_dict['events']['events']],
65+ Not(Contains(debug_event.id)))
66+
67 def test_event_to_dict_keys(self):
68 event = factory.make_Event()
69 self.assertThat(

Subscribers

People subscribed via source and target branches

to all changes: