Beispiel #1
0
def _GetMasterJsonData(http_client,
                       master_name,
                       builder_name='',
                       build_number=''):
    response_json = rpc_util.DownloadJsonData(_MILO_ENDPOINT_MASTER,
                                              {'name': master_name},
                                              http_client)

    return _ProcessMiloData(response_json, master_name, builder_name,
                            build_number)
Beispiel #2
0
def GetBuildDataFromBuildMaster(master_name, builder_name, build_number,
                                http_client):
    """Returns the json-format data of the build."""
    data = {
        'master': master_name,
        'builder': builder_name,
        'buildNum': build_number
    }
    response_json = rpc_util.DownloadJsonData(_MILO_ENDPOINT_BUILD, data,
                                              http_client)
    return _ProcessMiloData(response_json, master_name, builder_name,
                            str(build_number))
Beispiel #3
0
    def testDownloadJsonData(self, mock_fn_1, mock_fn_2):
        mocked_response_json = {'a': 'a'}
        mocked_response = json.dumps(mocked_response_json)
        mock_fn_1.return_value = mocked_response
        mock_fn_2.return_value = mocked_response_json

        url = 'url'
        data = {'data': 'data'}
        http_client = RetryHttpClient()

        response_json = rpc_util.DownloadJsonData(url, data, http_client)

        self.assertEqual(response_json, mocked_response_json)
        mock_fn_1.assert_called_once_with(url, data, http_client)
        mock_fn_2.assert_called_once_with(mocked_response)
Beispiel #4
0
def _GetAnnotationsProtoForPath(host, project, path, http_client):
    base_error_log = 'Error when load annotations protobuf: %s'

    data = {'project': project, 'path': path}

    response_json = rpc_util.DownloadJsonData(_LOGDOG_TAIL_ENDPOINT % host,
                                              data, http_client)
    if not response_json:
        return None

    # Gets data for proto. Data format as below:
    # {
    #    'logs': [
    #        {
    #            'datagram': {
    #                'data': (base64 encoded data)
    #            }
    #        }
    #     ]
    # }
    logs = json.loads(response_json).get('logs')
    if not logs or not isinstance(logs, list):
        logging.error(base_error_log % 'Wrong format - "logs"')
        return None

    annotations_b64 = logs[-1].get('datagram', {}).get('data')
    if not annotations_b64:
        logging.error(base_error_log % 'Wrong format - "data"')
        return None

    # Gets proto.
    try:
        annotations = base64.b64decode(annotations_b64)
        step = annotations_pb2.Step()
        step.ParseFromString(annotations)
        return step
    except Exception:
        logging.error(base_error_log % 'could not get annotations.')
        return None
Beispiel #5
0
def _GetLogForPath(host, project, path, http_client):
    base_error_log = 'Error when fetch log: %s'
    data = {'project': project, 'path': path}

    response_json = rpc_util.DownloadJsonData(_LOGDOG_GET_ENDPOINT % host,
                                              data, http_client)
    if not response_json:
        logging.error(base_error_log % 'cannot get json log.')
        return None

    # Gets data for log. Data format as below:
    # {
    #    'logs': [
    #        {
    #            'text': {
    #                'lines': [
    #                   {
    #                       'value': 'line'
    #                   }
    #                ]
    #            }
    #        }
    #     ]
    # }
    logs = json.loads(response_json).get('logs')
    if not logs or not isinstance(logs, list):
        logging.error(base_error_log % 'Wrong format - "logs"')
        return None

    sio = cStringIO.StringIO()
    for log in logs:
        for line in log.get('text', {}).get('lines', []):
            sio.write('%s\n' % line.get('value', '').encode('utf-8'))
    data = sio.getvalue()
    sio.close()

    return data
Beispiel #6
0
def _GetRawLogsFromGetEndpoint(host, data, http_client, retry_delay=5):
    """Gets raw logs from Get endpoint.

   The raw logs can be further processed to get annotations or a specific log.

   For logs of annotations, it should look like:
    [
       {
           'datagram': {
               'data': (base64 encoded data)
           }
       }
    ].

  For an actual log, it should look like:
    [
       {
           'text': {
               'lines': [
                  {
                      'value': 'line'
                  }
               ]
           }
       }
    ].
  """
    tries = 0
    error_message = ''

    # It seems possible to get empty log or log with wrong format.
    # So also retry for several times even on 200s if the log cannot be used.
    while tries < 5:
        # Retry 7 times to allow for logdog's up to 180 second propagation delay.
        # Exponential backoff starts at 1.5 seconds, reaches 96 seconds for the 7th
        # retry, for an accumulated total of 190.5 seconds of waiting time.
        # Should be enough for our purposes.
        _, response_json = rpc_util.DownloadJsonData(_LOGDOG_GET_ENDPOINT %
                                                     host,
                                                     data,
                                                     http_client,
                                                     max_retries=7)
        if response_json is None:
            # If response is None, it means after 7 retries, Findit still failed to
            # get response. Seems no need to keep retrying at this case.
            error_message = 'cannot get json log.'
            break
        else:
            try:
                logs = json.loads(response_json).get('logs')
                if not logs or not isinstance(logs, list):
                    error_message = 'Wrong format - %s' % response_json
                else:
                    return logs
            except ValueError as e:
                # For unknown reason sometimes the response_json is truncated and cannot
                # be json loaded.
                # This will also help to catch if the response_json is not serializable.
                error_message = 'Failed to load json - %s' % e.message
        tries += 1
        time.sleep(tries * retry_delay)

    # Only logs error when the log was failed to get at last.
    logging.error('Error when fetch log or annotations: %s' % error_message)
    return None
Beispiel #7
0
def _GetAnnotationsProtoForPath(host, project, path, http_client):
    """Gets annotations from logdog endpoint(s).

  By default sends request to Tail endpoint for annotations, if only gets a
  partial results, use Get endpoint instead.
  """
    base_error_log = 'Error when load annotations protobuf: %s'

    data = {'project': project, 'path': path}

    _, response_json = rpc_util.DownloadJsonData(_LOGDOG_TAIL_ENDPOINT % host,
                                                 data,
                                                 http_client,
                                                 max_retries=7)
    if not response_json:
        return None

    # Gets data for proto. Data format as below:
    # {
    #    'logs': [
    #        {
    #            'datagram': {
    #                'data': (base64 encoded data)
    #            }
    #        }
    #     ]
    # }
    logs = json.loads(response_json).get('logs')
    if not logs or not isinstance(logs, list):
        logging.error(base_error_log % 'Wrong format - "logs"')
        return None

    partial = logs[-1].get('datagram', {}).get('partial')
    if partial:
        # Only gets partial result from Tail, use Get instead to get annotations.
        index = int(logs[-1]['streamIndex'])
        partial_index = partial['index']
        data = {
            'project': project,
            'path': path,
            'index': index - partial_index
        }
        logs = _GetRawLogsFromGetEndpoint(host, data, http_client)

    annotations = ''
    if not logs:
        logging.error(base_error_log % 'Wrong format - "logs"')
        return None

    sio = cStringIO.StringIO()
    for log in logs:
        annotations_b64 = log.get('datagram', {}).get('data')
        if not annotations_b64:
            sio.close()
            logging.error(base_error_log % 'Wrong format - "data"')
            return None

        sio.write(base64.b64decode(annotations_b64))
    annotations = sio.getvalue()
    sio.close()

    # Gets proto.
    try:
        step = annotations_pb2.Step()
        step.ParseFromString(annotations)
        return step
    except Exception:
        logging.error(base_error_log % 'could not get annotations.')
        return None