Esempio n. 1
0
def IsDone(job_id):
  """Transactionally check whether a job is done executing.

  Returns True IFF the job is executing under the execution engine and that
  internal state is consistent with the job being "done".

  Raises any errors encountered in execution engine evaluation.
  """
  job = JobFromId(job_id)
  if not job.use_execution_engine:
    return False

  # This comes from an eventually consistent read, but we can treat that as a
  # relaxed load -- if this ever is true, then that means a transaction before
  # this call had already marked the job "done".
  if job.done:
    return True

  try:
    context = task_module.Evaluate(
        job, event_module.SelectEvent(),
        evaluators.DispatchByTaskType({
            'find_culprit':
                evaluators.TaskPayloadLiftingEvaluator(exclude_keys=['commits'])
        }))
    if not context:
      return False
    for payload in context.values():
      status = payload.get('status')
      if status in {'pending', 'ongoing'}:
        return False
    return True
  except task_module.Error as error:
    logging.error('Evaluation error: %s', error)
    raise
Esempio n. 2
0
    def _FormatAndPostBugCommentOnComplete(self):
        logging.debug('Processing outputs.')
        if self._IsTryJob():
            # There is no comparison metric.
            title = '<b>%s Job complete. See results below.</b>' % _ROUND_PUSHPIN
            deferred.defer(_PostBugCommentDeferred,
                           self.bug_id,
                           '\n'.join((title, self.url)),
                           labels=['Pinpoint-Tryjob-Completed'],
                           _retry_options=RETRY_OPTIONS)
            return

        # There is a comparison metric.
        differences = []
        result_values = {}
        if not self.use_execution_engine:
            differences = self.state.Differences()
            for change_a, change_b in differences:
                result_values.setdefault(change_a,
                                         self.state.ResultValues(change_a))
                result_values.setdefault(change_b,
                                         self.state.ResultValues(change_b))
        else:
            logging.debug('Execution Engine: Finding culprits.')
            context = task_module.Evaluate(
                self, event_module.SelectEvent(),
                evaluators.Selector(
                    event_type='select',
                    include_keys={'culprits', 'change', 'result_values'}))
            differences = [
                (change_module.ReconstituteChange(change_a),
                 change_module.ReconstituteChange(change_b))
                for change_a, change_b in context.get('performance_bisection',
                                                      {}).get('culprits', [])
            ]
            result_values = {
                change_module.ReconstituteChange(v.get('change')):
                v.get('result_values')
                for v in context.values()
                if 'change' in v and 'result_values' in v
            }

        if not differences:
            title = "<b>%s Couldn't reproduce a difference.</b>" % _ROUND_PUSHPIN
            deferred.defer(_PostBugCommentDeferred,
                           self.bug_id,
                           '\n'.join((title, self.url)),
                           labels=['Pinpoint-No-Repro'],
                           _retry_options=RETRY_OPTIONS)
            return

        # Collect the result values for each of the differences
        difference_details = []
        commit_infos = []
        commits_with_deltas = {}
        for change_a, change_b in differences:
            if change_b.patch:
                commit = change_b.patch
            else:
                commit = change_b.last_commit
            commit_info = commit.AsDict()

            values_a = result_values[change_a]
            values_b = result_values[change_b]
            difference = _FormatDifferenceForBug(commit_info, values_a,
                                                 values_b, self.state.metric)
            difference_details.append(difference)
            commit_infos.append(commit_info)
            if values_a and values_b:
                mean_delta = job_state.Mean(values_b) - job_state.Mean(
                    values_a)
                commits_with_deltas[commit.id_string] = (mean_delta,
                                                         commit_info)

        deferred.defer(_UpdatePostAndMergeDeferred,
                       difference_details,
                       commit_infos,
                       list(commits_with_deltas.values()),
                       self.bug_id,
                       self.tags,
                       self.url,
                       _retry_options=RETRY_OPTIONS)
Esempio n. 3
0
    def _FormatAndPostBugCommentOnComplete(self):
        logging.debug('Processing outputs.')
        if self._IsTryJob():
            # There is no comparison metric.
            title = '<b>%s Job complete. See results below.</b>' % _ROUND_PUSHPIN
            deferred.defer(_PostBugCommentDeferred,
                           self.bug_id,
                           '\n'.join((title, self.url)),
                           project=self.project,
                           labels=['Pinpoint-Tryjob-Completed'],
                           _retry_options=RETRY_OPTIONS)
            return

        # There is a comparison metric.
        differences = []
        result_values = {}
        changes_examined = None
        if not self.use_execution_engine:
            differences = self.state.Differences()
            for change_a, change_b in differences:
                result_values.setdefault(change_a,
                                         self.state.ResultValues(change_a))
                result_values.setdefault(change_b,
                                         self.state.ResultValues(change_b))
            changes_examined = self.state.ChangesExamined()
        else:
            logging.debug('Execution Engine: Finding culprits.')
            context = task_module.Evaluate(
                self, event_module.SelectEvent(),
                evaluators.Selector(
                    event_type='select',
                    include_keys={'culprits', 'change', 'result_values'}))
            differences = [
                (change_module.ReconstituteChange(change_a),
                 change_module.ReconstituteChange(change_b))
                for change_a, change_b in context.get('performance_bisection',
                                                      {}).get('culprits', [])
            ]
            result_values = {
                change_module.ReconstituteChange(v.get('change')):
                v.get('result_values')
                for v in context.values()
                if 'change' in v and 'result_values' in v
            }

        if not differences:
            # When we cannot find a difference, we want to not only update the issue
            # with that (minimal) information but also automatically mark the issue
            # WontFix. This is based on information we've gathered in production that
            # most issues where we find Pinpoint cannot reproduce the difference end
            # up invariably as "Unconfirmed" with very little follow-up.
            title = "<b>%s Couldn't reproduce a difference.</b>" % _ROUND_PUSHPIN
            deferred.defer(_PostBugCommentDeferred,
                           self.bug_id,
                           '\n'.join((title, self.url)),
                           project=self.project,
                           labels=['Pinpoint-No-Repro'],
                           status='WontFix',
                           _retry_options=RETRY_OPTIONS)
            return

        # Collect the result values for each of the differences
        bug_update_builder = job_bug_update.DifferencesFoundBugUpdateBuilder(
            self.state.metric)
        bug_update_builder.SetExaminedCount(changes_examined)
        for change_a, change_b in differences:
            if change_b.patch:
                commit = change_b.patch
            else:
                commit = change_b.last_commit

            values_a = result_values[change_a]
            values_b = result_values[change_b]
            bug_update_builder.AddDifference(commit, values_a, values_b)

        deferred.defer(job_bug_update.UpdatePostAndMergeDeferred,
                       bug_update_builder,
                       self.bug_id,
                       self.tags,
                       self.url,
                       self.project,
                       _retry_options=RETRY_OPTIONS)