def testReportStats(self):
    retry_stats.SetupStats()

    # Insert some stats to report.
    retry_stats.RetryWithStats(
        self.CAT, self.handlerNoRetry, 3, self.callSuccess)
    retry_stats.RetryWithStats(
        self.CAT_B, self.handlerNoRetry, 3, self.callSuccess)
    self.assertRaises(TestRetryException,
                      retry_stats.RetryWithStats,
                      self.CAT, self.handlerRetry, 3, self.callFailure)

    out = StringIO()
    retry_stats.ReportStats(out)

    # Expecting reports for both CAT and CAT_B used above.
    expected = """************************************************************
** Performance Statistics for Test Service A
**
** Success: 1
** Failure: 1
** Retries: 3
** Total: 2
************************************************************
************************************************************
** Performance Statistics for Test Service B
**
** Success: 1
** Failure: 0
** Retries: 0
** Total: 1
************************************************************
"""

    self.assertEqual(out.getvalue(), expected)
  def testSuccessNoSetup(self):
    """Verify that we can handle a successful call if we're never setup."""
    self.assertEqual(retry_stats._STATS_COLLECTION, None)

    result = retry_stats.RetryWithStats(
        self.CAT, self.handlerNoRetry, 3, self.callSuccess)
    self.assertEqual(result, self.SUCCESS_RESULT)

    result = retry_stats.RetryWithStats(
        self.CAT, self.handlerNoRetry, 3, self.callSuccess)
    self.assertEqual(result, self.SUCCESS_RESULT)

    self.assertEqual(retry_stats._STATS_COLLECTION, None)
  def testSuccess(self):
    """Verify that we can handle a successful call."""
    retry_stats.SetupStats()
    self._verifyStats(self.CAT)

    # Succeed once.
    result = retry_stats.RetryWithStats(
        self.CAT, self.handlerNoRetry, 3, self.callSuccess)
    self.assertEqual(result, self.SUCCESS_RESULT)
    self._verifyStats(self.CAT, success=1)

    # Succeed twice.
    result = retry_stats.RetryWithStats(
        self.CAT, self.handlerNoRetry, 3, self.callSuccess)
    self.assertEqual(result, self.SUCCESS_RESULT)
    self._verifyStats(self.CAT, success=2)
예제 #4
0
def PerformSymbolsFileUpload(symbols, upload_url, api_key):
  """Upload the symbols to the crash server

  Args:
    symbols: An iterable of SymbolFiles to be uploaded.
    upload_url: URL of crash server to upload too.
    api_key: Authentication key.
    failures: Tracker for total upload failures.

  Yields:
    Each symbol from symbols, perhaps modified.
  """
  failures = 0

  for s in symbols:
    if (failures < MAX_TOTAL_ERRORS_FOR_RETRY and
        s.status in (SymbolFile.INITIAL, SymbolFile.ERROR)):
      # Keeps us from DoS-ing the symbol server.
      time.sleep(SLEEP_DELAY)
      logging.info('Uploading symbol_file: %s', s.display_path)
      try:
        # This command retries the upload multiple times with growing delays. We
        # only consider the upload a failure if these retries fail.
        def ShouldRetryUpload(exception):
          if isinstance(exception, (requests.exceptions.RequestException,
                                    IOError,
                                    httplib.HTTPException, socket.error)):
            logging.info('Request failed, retrying: %s', exception)
            return True
          return False

        with cros_build_lib.TimedSection() as timer:
          retry_stats.RetryWithStats(
              UPLOAD_STATS, ShouldRetryUpload, MAX_RETRIES,
              UploadSymbolFile,
              upload_url, s, api_key,
              sleep=INITIAL_RETRY_DELAY,
              log_all_retries=True)
        if s.status != SymbolFile.DUPLICATE:
          logging.info('upload of %10i bytes took %s', s.FileSize(),
                       timer.delta)
          s.status = SymbolFile.UPLOADED
      except requests.exceptions.RequestException as e:
        logging.warning('could not upload: %s: HTTP error: %s',
                        s.display_name, e)
        s.status = SymbolFile.ERROR
        failures += 1
      except (httplib.HTTPException, IOError, socket.error) as e:
        logging.warning('could not upload: %s: %s %s', s.display_name,
                        type(e).__name__, e)
        s.status = SymbolFile.ERROR
        failures += 1

    # We pass the symbol along, on both success and failure.
    yield s
예제 #5
0
def PerformSymbolsFileUpload(symbols, upload_url, product_name='ChromeOS'):
    """Upload the symbols to the crash server

  Args:
    symbols: An iterable of SymbolFiles to be uploaded.
    upload_url: URL of crash server to upload too.
    failures: Tracker for total upload failures.
    product_name: A string for stats purposes. Usually 'ChromeOS' or 'Android'.

  Yields:
    Each symbol from symbols, perhaps modified.
  """
    failures = 0

    for s in symbols:
        if (failures < MAX_TOTAL_ERRORS_FOR_RETRY
                and s.status in (SymbolFile.INITIAL, SymbolFile.ERROR)):
            # Keeps us from DoS-ing the symbol server.
            time.sleep(SLEEP_DELAY)
            logging.info('Uploading symbol_file: %s', s.display_path)
            try:
                # This command retries the upload multiple times with growing delays. We
                # only consider the upload a failure if these retries fail.
                def ShouldRetryUpload(exception):
                    return isinstance(exception,
                                      (urllib2.HTTPError, urllib2.URLError))

                with cros_build_lib.TimedSection() as timer:
                    retry_stats.RetryWithStats(UPLOAD_STATS,
                                               ShouldRetryUpload,
                                               MAX_RETRIES,
                                               UploadSymbolFile,
                                               upload_url,
                                               s,
                                               product_name,
                                               sleep=INITIAL_RETRY_DELAY,
                                               log_all_retries=True)
                logging.info('upload of %10i bytes took %s', s.FileSize(),
                             timer.delta)
                s.status = SymbolFile.UPLOADED
            except urllib2.HTTPError as e:
                logging.warning('could not upload: %s: HTTP %s: %s',
                                s.display_name, e.code, e.reason)
                s.status = SymbolFile.ERROR
                failures += 1
            except (urllib2.URLError, httplib.HTTPException,
                    socket.error) as e:
                logging.warning('could not upload: %s: %s', s.display_name, e)
                s.status = SymbolFile.ERROR
                failures += 1

        # We pass the symbol along, on both success and failure.
        yield s
  def testSuccessRetry(self):
    """Verify that we can handle a successful call after tries."""
    retry_stats.SetupStats()
    self._verifyStats(self.CAT)

    # Use this scoped list as a persistent counter.
    call_counter = ['fail 1', 'fail 2']

    def callRetrySuccess():
      if call_counter:
        raise TestRetryException(call_counter.pop())
      else:
        return self.SUCCESS_RESULT

    # Retry twice, then succeed.
    result = retry_stats.RetryWithStats(
        self.CAT, self.handlerRetry, 3, callRetrySuccess)
    self.assertEqual(result, self.SUCCESS_RESULT)
    self._verifyStats(self.CAT, success=1, retry=2)
예제 #7
0
파일: gs.py 프로젝트: sjg20/chromite
    def DoCommand(self,
                  gsutil_cmd,
                  headers=(),
                  retries=None,
                  version=None,
                  parallel=False,
                  **kwargs):
        """Run a gsutil command, suppressing output, and setting retry/sleep.

    Args:
      gsutil_cmd: The (mostly) constructed gsutil subcommand to run.
      headers: A list of raw headers to pass down.
      parallel: Whether gsutil should enable parallel copy/update of multiple
        files. NOTE: This option causes gsutil to use significantly more
        memory, even if gsutil is only uploading one file.
      retries: How many times to retry this command (defaults to setting given
        at object creation).
      version: If given, the generation; essentially the timestamp of the last
        update.  Note this is not the same as sequence-number; it's
        monotonically increasing bucket wide rather than reset per file.
        The usage of this is if we intend to replace/update only if the version
        is what we expect.  This is useful for distributed reasons- for example,
        to ensure you don't overwrite someone else's creation, a version of
        0 states "only update if no version exists".

    Returns:
      A RunCommandResult object.
    """
        kwargs = kwargs.copy()
        kwargs.setdefault('redirect_stderr', True)

        cmd = [self.gsutil_bin]
        cmd += self.gsutil_flags
        for header in headers:
            cmd += ['-h', header]
        if version is not None:
            cmd += ['-h', 'x-goog-if-generation-match:%d' % int(version)]

        # Enable parallel copy/update of multiple files if stdin is not to
        # be piped to the command. This does not split a single file into
        # smaller components for upload.
        if parallel and kwargs.get('input') is None:
            cmd += ['-m']

        cmd.extend(gsutil_cmd)

        if retries is None:
            retries = self.retries

        extra_env = kwargs.pop('extra_env', {})
        if self.boto_file and os.path.isfile(self.boto_file):
            extra_env.setdefault('BOTO_CONFIG', self.boto_file)

        if self.dry_run:
            logging.debug("%s: would've run: %s", self.__class__.__name__,
                          cros_build_lib.CmdToStr(cmd))
        else:
            try:
                return retry_stats.RetryWithStats(retry_stats.GSUTIL,
                                                  self._RetryFilter,
                                                  retries,
                                                  cros_build_lib.RunCommand,
                                                  cmd,
                                                  sleep=self._sleep_time,
                                                  extra_env=extra_env,
                                                  **kwargs)
            except cros_build_lib.RunCommandError as e:
                raise GSCommandError(e.msg, e.result, e.exception)