class_docstr: ArtifactExtractor class will extract artifacts from "streamalert_normalization" field in the
  records. The extracted artfiacts will be saved in the S3 bucket via a dedicated Firehose
  delivery stream and searchable from "artifacts" table in Athena.
docstr: Run extract artifacts logic and send artifacts to the Firehose for retention
  
  Args:
      categorized_records (dict): A dictionary contains log source type and records with
      following format
          {
              'log_type_01_sub_type_01': [{'key': 'value'}],
              'log_type_01_sub_type_02': [{'key': 'value'}],
              'log_type_02_sub_type_01': [{'key': 'value'}],
              'log_type_02_sub_type_02': [{'key': 'value'}]
          }
docstr_tok: ["Run","extract","artifacts","logic","and","send","artifacts","to","the","Firehose","for","retention","Args",":","categorized_records","(","dict",")",":","A","dictionary","contains","log","source","type","and","records","with","following","format","{","'log_type_01_sub_type_01","'",":","[","{","'key","'",":","'value","'","}","]",",","'log_type_01_sub_type_02","'",":","[","{","'key","'",":","'value","'","}","]",",","'log_type_02_sub_type_01","'",":","[","{","'key","'",":","'value","'","}","]",",","'log_type_02_sub_type_02","'",":","[","{","'key","'",":","'value","'","}","]","}"]
code: def run(self, categorized_records):
      """Run extract artifacts logic and send artifacts to the Firehose for retention
  
      Args:
          categorized_records (dict): A dictionary contains log source type and records with
          following format
              {
                  'log_type_01_sub_type_01': [{'key': 'value'}],
                  'log_type_01_sub_type_02': [{'key': 'value'}],
                  'log_type_02_sub_type_01': [{'key': 'value'}],
                  'log_type_02_sub_type_02': [{'key': 'value'}]
              }
      """
  
      for source_type, records in categorized_records.items():
          LOGGER.debug(
              "Extracting artifacts from %d %s logs",
              len(records),
              source_type,
          )
          for artifact in self._extract_artifacts(source_type, records):
              self._artifacts.append(artifact.artifact)
  
      LOGGER.debug("Extracted %d artifact(s)", len(self._artifacts))
  
      MetricLogger.log_metric(
          CLASSIFIER_FUNCTION_NAME,
          MetricLogger.EXTRACTED_ARTIFACTS,
          len(self._artifacts),
      )
  
      self.firehose.send_artifacts(
          self._artifacts, self._dst_firehose_stream_name
      )
  
file_path: streamalert/streamalert/shared/artifact_extractor.py
imports: import re
  import uuid
  from streamalert.shared.firehose import FirehoseClient
  from streamalert.shared import CLASSIFIER_FUNCTION_NAME, config
  from streamalert.shared.metrics import MetricLogger
  from streamalert.shared.normalize import Normalizer, CONST_ARTIFACTS_FLAG
  from streamalert.shared.logger import get_logger
label_desc: Use image node_id 5 for calling the ArtifactExtractor obj's underlying member method code with example usage: obj.run(categorized_records) without return types