class_docstr: Handles preparing and sending data from the classifier function to Kinesis Firehose
docstr: Send record batches to Firehose
  
  Args:
      stream_name (str): The name of the Delivery Stream to send to
      record_batch (list): The records to send
docstr_tok: ["Send","record","batches","to","Firehose","Args",":","stream_name","(","str",")",":","The","name","of","the","Delivery","Stream","to","send","to","record_batch","(","list",")",":","The","records","to","send"]
code: def _send_batch(self, stream_name, record_batch, function_name):
      """Send record batches to Firehose
  
      Args:
          stream_name (str): The name of the Delivery Stream to send to
          record_batch (list): The records to send
      """
  
      @backoff.on_predicate(
          backoff.fibo,
          lambda resp: resp["FailedPutCount"] > 0,
          max_tries=self.MAX_BACKOFF_ATTEMPTS,
          max_value=self.MAX_BACKOFF_FIBO_VALUE,
          on_backoff=backoff_handler(debug_only=False),
          on_success=success_handler(),
          on_giveup=giveup_handler(),
      )
      @backoff.on_exception(
          backoff.fibo,
          self.EXCEPTIONS_TO_BACKOFF,
          max_tries=self.MAX_BACKOFF_ATTEMPTS,
          on_backoff=backoff_handler(debug_only=False),
          on_success=success_handler(),
          on_giveup=giveup_handler(),
      )
      def _firehose_request_helper(data):
          """Firehose request wrapper to use with backoff"""
          # Use the current length of data here so we can track failed records that are retried
          LOGGER.debug(
              "Sending %d records to firehose %s",
              len(data),
              stream_name,
          )
  
          response = self._client.put_record_batch(
              DeliveryStreamName=stream_name, Records=data
          )
  
          # Log this as an error for now so it can be picked up in logs
          if response["FailedPutCount"] > 0:
              LOGGER.warning(
                  "Received non-zero FailedPutCount: %d",
                  response["FailedPutCount"],
              )
              # Strip out the successful records so only the failed ones are retried. This happens
              # to the list of dictionary objects, so the called function sees the updated list
              self._strip_successful_records(data, response)
  
          return response
  
      # The record here already contains a newline, so do not append one
      records_data = [{"Data": record} for record in record_batch]
  
      # The try/except here is to catch the raised error at the end of the backoff
      try:
          return _firehose_request_helper(records_data)
      except self.EXCEPTIONS_TO_BACKOFF:
          LOGGER.exception("Firehose request failed")
          # Use the current length of the records_data in case some records were
          # successful but others were not
          self._log_failed(len(records_data), function_name)
  
imports: from collections import defaultdict
  import json
  import hashlib
  import re
  import backoff
  import boto3
  from botocore.exceptions import ClientError, HTTPClientError
  from botocore.exceptions import ConnectionError
  from streamalert.shared import CLASSIFIER_FUNCTION_NAME
  import streamalert.shared.helpers.boto
  from streamalert.shared.logger import get_logger
  from streamalert.shared.metrics import MetricLogger
  from streamalert.shared.backoff_handlers import backoff_handler, giveup_handler, success_handler
label_desc: Use image node_id 10 for calling the FirehoseClient obj's underlying member method code with example usage: obj._send_batch(stream_name, record_batch, function_name) and returns: response, _firehose_request_helper