Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: dashboard/dashboard/pinpoint/models/job.py

Issue 2956343003: [pinpoint] Post bug comments when a job starts and completes. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « dashboard/dashboard/pinpoint/handlers/new.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import collections 5 import collections
6 import logging 6 import logging
7 import numbers 7 import numbers
8 import os
8 9
9 from google.appengine.api import taskqueue 10 from google.appengine.api import taskqueue
10 from google.appengine.ext import ndb 11 from google.appengine.ext import ndb
11 12
13 from dashboard.common import utils
12 from dashboard.pinpoint import mann_whitney_u 14 from dashboard.pinpoint import mann_whitney_u
13 from dashboard.pinpoint.models import attempt as attempt_module 15 from dashboard.pinpoint.models import attempt as attempt_module
14 from dashboard.pinpoint.models import change as change_module 16 from dashboard.pinpoint.models import change as change_module
15 from dashboard.pinpoint.models import quest as quest_module 17 from dashboard.pinpoint.models import quest as quest_module
18 from dashboard.services import issue_tracker_service
16 19
17 20
18 # We want this to be fast to minimize overhead while waiting for tasks to 21 # We want this to be fast to minimize overhead while waiting for tasks to
19 # finish, but don't want to consume too many resources. 22 # finish, but don't want to consume too many resources.
20 _TASK_INTERVAL = 10 23 _TASK_INTERVAL = 10
21 24
22 25
23 _DEFAULT_MAX_ATTEMPTS = 2 26 _DEFAULT_MAX_ATTEMPTS = 2
24 _SIGNIFICANCE_LEVEL = 0.5 27 _SIGNIFICANCE_LEVEL = 0.5
25 28
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 # Request parameters. 60 # Request parameters.
58 configuration = ndb.StringProperty(required=True) 61 configuration = ndb.StringProperty(required=True)
59 test_suite = ndb.StringProperty() 62 test_suite = ndb.StringProperty()
60 test = ndb.StringProperty() 63 test = ndb.StringProperty()
61 metric = ndb.StringProperty() 64 metric = ndb.StringProperty()
62 65
63 # If True, the service should pick additional Changes to run (bisect). 66 # If True, the service should pick additional Changes to run (bisect).
64 # If False, only run the Changes explicitly added by the user. 67 # If False, only run the Changes explicitly added by the user.
65 auto_explore = ndb.BooleanProperty(required=True) 68 auto_explore = ndb.BooleanProperty(required=True)
66 69
70 # TODO: The bug id is only used for posting bug comments when a job starts and
71 # completes. This probably should not be the responsibility of Pinpoint.
72 bug_id = ndb.IntegerProperty()
perezju 2017/06/29 09:03:30 Note that, probably, we would still want to mainta
73
67 state = ndb.PickleProperty(required=True) 74 state = ndb.PickleProperty(required=True)
68 75
69 @classmethod 76 @classmethod
70 def New(cls, configuration, test_suite, test, metric, auto_explore): 77 def New(cls, configuration, test_suite, test, metric, auto_explore, bug_id):
71 # Get list of quests. 78 # Get list of quests.
72 quests = [quest_module.FindIsolate(configuration)] 79 quests = [quest_module.FindIsolate(configuration)]
73 if test_suite: 80 if test_suite:
74 quests.append(quest_module.RunTest(configuration, test_suite, test)) 81 quests.append(quest_module.RunTest(configuration, test_suite, test))
75 if metric: 82 if metric:
76 quests.append(quest_module.ReadValue(metric, test)) 83 quests.append(quest_module.ReadValue(metric, test))
77 84
78 # Create job. 85 # Create job.
79 return cls( 86 return cls(
80 configuration=configuration, 87 configuration=configuration,
81 test_suite=test_suite, 88 test_suite=test_suite,
82 test=test, 89 test=test,
83 metric=metric, 90 metric=metric,
84 auto_explore=auto_explore, 91 auto_explore=auto_explore,
92 bug_id=bug_id,
85 state=_JobState(quests, _DEFAULT_MAX_ATTEMPTS)) 93 state=_JobState(quests, _DEFAULT_MAX_ATTEMPTS))
86 94
87 @property 95 @property
88 def job_id(self): 96 def job_id(self):
89 return self.key.urlsafe() 97 return self.key.urlsafe()
90 98
91 @property 99 @property
92 def status(self): 100 def status(self):
93 if self.task: 101 if self.task:
94 return 'Running' 102 return 'Running'
95 103
96 if self.exception: 104 if self.exception:
97 return 'Failed' 105 return 'Failed'
98 106
99 return 'Completed' 107 return 'Completed'
100 108
109 @property
110 def url(self):
111 return 'https://%s/job/%s' % (os.environ['HTTP_HOST'], self.job_id)
112
101 def AddChange(self, change): 113 def AddChange(self, change):
102 self.state.AddChange(change) 114 self.state.AddChange(change)
103 115
104 def Start(self): 116 def Start(self):
117 self.Schedule()
118
119 comment = 'Pinpoint job started.\n' + self.url
120 issue_tracker = issue_tracker_service.IssueTrackerService(
121 utils.ServiceAccountHttp())
122 issue_tracker.AddBugComment(self.bug_id, comment, send_email=False)
123
124 def Complete(self):
125 comment = 'Pinpoint job complete!\n' + self.url
126 issue_tracker = issue_tracker_service.IssueTrackerService(
127 utils.ServiceAccountHttp())
128 issue_tracker.AddBugComment(self.bug_id, comment, send_email=False)
129
130 def Schedule(self):
105 task = taskqueue.add(queue_name='job-queue', url='/api/run/' + self.job_id, 131 task = taskqueue.add(queue_name='job-queue', url='/api/run/' + self.job_id,
106 countdown=_TASK_INTERVAL) 132 countdown=_TASK_INTERVAL)
107 self.task = task.name 133 self.task = task.name
108 134
109 def Run(self): 135 def Run(self):
110 self.exception = None # In case the Job succeeds on retry. 136 self.exception = None # In case the Job succeeds on retry.
111 self.task = None # In case an exception is thrown. 137 self.task = None # In case an exception is thrown.
112 138
113 try: 139 try:
114 if self.auto_explore: 140 if self.auto_explore:
115 self.state.Explore() 141 self.state.Explore()
116 work_left = self.state.ScheduleWork() 142 work_left = self.state.ScheduleWork()
117 143
118 # Schedule moar task. 144 # Schedule moar task.
119 if work_left: 145 if work_left:
120 self.Start() 146 self.Schedule()
147 else:
148 self.Complete()
121 except BaseException as e: 149 except BaseException as e:
122 self.exception = str(e) 150 self.exception = str(e)
123 raise 151 raise
124 152
125 def AsDict(self): 153 def AsDict(self):
126 return { 154 return {
127 'job_id': self.job_id, 155 'job_id': self.job_id,
128 156
129 'configuration': self.configuration, 157 'configuration': self.configuration,
130 'test_suite': self.test_suite, 158 'test_suite': self.test_suite,
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 # We want the results_values to provide both a message that can be shown to 344 # We want the results_values to provide both a message that can be shown to
317 # the user for why something failed, and also something comparable that can 345 # the user for why something failed, and also something comparable that can
318 # be used for bisect. Therefore, they contain the thrown Exceptions. This 346 # be used for bisect. Therefore, they contain the thrown Exceptions. This
319 # function then converts them into comparable numbers for bisect. 347 # function then converts them into comparable numbers for bisect.
320 if isinstance(obj, numbers.Number): 348 if isinstance(obj, numbers.Number):
321 return obj 349 return obj
322 elif isinstance(obj, Exception): 350 elif isinstance(obj, Exception):
323 return hash(obj.__class__) 351 return hash(obj.__class__)
324 else: 352 else:
325 return hash(obj) 353 return hash(obj)
OLDNEW
« no previous file with comments | « dashboard/dashboard/pinpoint/handlers/new.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698