class Aws::Plugins::ClientMetricsPlugin::Handler

def _calculate_service_id(context)

def _calculate_service_id(context)
  class_name = context.client.class.to_s.match(/(.+)::Client/)[1]
  class_name.sub!(/^Aws::/, '')
  _fallback_service_id(class_name)
end

def _fallback_service_id(id)

def _fallback_service_id(id)
  # Need hard-coded exceptions since information needed to
  # reverse-engineer serviceId is not present in older versions.
  # This list should not need to grow.
  exceptions = {
    "ACMPCA" => "ACM PCA",
    "APIGateway" => "API Gateway",
    "AlexaForBusiness" => "Alexa For Business",
    "ApplicationAutoScaling" => "Application Auto Scaling",
    "ApplicationDiscoveryService" => "Application Discovery Service",
    "AutoScaling" => "Auto Scaling",
    "AutoScalingPlans" => "Auto Scaling Plans",
    "CloudHSMV2" => "CloudHSM V2",
    "CloudSearchDomain" => "CloudSearch Domain",
    "CloudWatchEvents" => "CloudWatch Events",
    "CloudWatchLogs" => "CloudWatch Logs",
    "CognitoIdentity" => "Cognito Identity",
    "CognitoIdentityProvider" => "Cognito Identity Provider",
    "CognitoSync" => "Cognito Sync",
    "ConfigService" => "Config Service",
    "CostExplorer" => "Cost Explorer",
    "CostandUsageReportService" => "Cost and Usage Report Service",
    "DataPipeline" => "Data Pipeline",
    "DatabaseMigrationService" => "Database Migration Service",
    "DeviceFarm" => "Device Farm",
    "DirectConnect" => "Direct Connect",
    "DirectoryService" => "Directory Service",
    "DynamoDBStreams" => "DynamoDB Streams",
    "ElasticBeanstalk" => "Elastic Beanstalk",
    "ElasticLoadBalancing" => "Elastic Load Balancing",
    "ElasticLoadBalancingV2" => "Elastic Load Balancing v2",
    "ElasticTranscoder" => "Elastic Transcoder",
    "ElasticsearchService" => "Elasticsearch Service",
    "IoTDataPlane" => "IoT Data Plane",
    "IoTJobsDataPlane" => "IoT Jobs Data Plane",
    "IoT1ClickDevicesService" => "IoT 1Click Devices Service",
    "IoT1ClickProjects" => "IoT 1Click Projects",
    "KinesisAnalytics" => "Kinesis Analytics",
    "KinesisVideo" => "Kinesis Video",
    "KinesisVideoArchivedMedia" => "Kinesis Video Archived Media",
    "KinesisVideoMedia" => "Kinesis Video Media",
    "LambdaPreview" => "Lambda",
    "Lex" => "Lex Runtime Service",
    "LexModelBuildingService" => "Lex Model Building Service",
    "Lightsail" => "Lightsail",
    "MQ" => "mq",
    "MachineLearning" => "Machine Learning",
    "MarketplaceCommerceAnalytics" => "Marketplace Commerce Analytics",
    "MarketplaceEntitlementService" => "Marketplace Entitlement Service",
    "MarketplaceMetering" => "Marketplace Metering",
    "MediaStoreData" => "MediaStore Data",
    "MigrationHub" => "Migration Hub",
    "ResourceGroups" => "Resource Groups",
    "ResourceGroupsTaggingAPI" => "Resource Groups Tagging API",
    "Route53" => "Route 53",
    "Route53Domains" => "Route 53 Domains",
    "SecretsManager" => "Secrets Manager",
    "SageMakerRuntime" => "SageMaker Runtime",
    "ServiceCatalog" => "Service Catalog",
    "ServiceDiscovery" => "ServiceDiscovery",
    "Signer" => "signer",
    "States" => "SFN",
    "StorageGateway" => "Storage Gateway",
    "TranscribeService" => "Transcribe Service",
    "WAFRegional" => "WAF Regional",
  }
  if exceptions[id]
    exceptions[id]
  else
    id
  end
end

def call(context)

def call(context)
  publisher = context.config.client_side_monitoring_publisher
  service_id = context.config.api.metadata["serviceId"]
  # serviceId not present in all versions, need a fallback
  service_id ||= _calculate_service_id(context)
  request_metrics = ClientSideMonitoring::RequestMetrics.new(
    service: service_id,
    operation: context.operation.name,
    client_id: context.config.client_side_monitoring_client_id,
    region: context.config.region,
    timestamp: DateTime.now.strftime('%Q').to_i,
  )
  context.metadata[:client_metrics] = request_metrics
  start_time = Aws::Util.monotonic_milliseconds
  final_error_retryable = false
  final_aws_exception = nil
  final_aws_exception_message = nil
  final_sdk_exception = nil
  final_sdk_exception_message = nil
  begin
    @handler.call(context)
  rescue StandardError => e
    # Handle SDK Exceptions
    inspector = Retries::ErrorInspector.new(
      e,
      context.http_response.status_code
    )
    if inspector.retryable?(context)
      final_error_retryable = true
    end
    if request_metrics.api_call_attempts.empty?
      attempt = request_metrics.build_call_attempt
      attempt.sdk_exception = e.class.to_s
      attempt.sdk_exception_msg = e.message
      request_metrics.add_call_attempt(attempt)
    elsif request_metrics.api_call_attempts.last.aws_exception.nil?
      # Handle exceptions during response handlers
      attempt = request_metrics.api_call_attempts.last
      attempt.sdk_exception = e.class.to_s
      attempt.sdk_exception_msg = e.message
    elsif !e.class.to_s.match(request_metrics.api_call_attempts.last.aws_exception)
      # Handle response handling exceptions that happened in addition to
      # an AWS exception
      attempt = request_metrics.api_call_attempts.last
      attempt.sdk_exception = e.class.to_s
      attempt.sdk_exception_msg = e.message
    end # Else we don't have an SDK exception and are done.
    final_attempt = request_metrics.api_call_attempts.last
    final_aws_exception = final_attempt.aws_exception
    final_aws_exception_message = final_attempt.aws_exception_msg
    final_sdk_exception = final_attempt.sdk_exception
    final_sdk_exception_message = final_attempt.sdk_exception_msg
    raise e
  ensure
    end_time = Aws::Util.monotonic_milliseconds
    complete_opts = {
      latency: end_time - start_time,
      attempt_count: context.retries + 1,
      user_agent: context.http_request.headers["user-agent"],
      final_error_retryable: final_error_retryable,
      final_http_status_code: context.http_response.status_code,
      final_aws_exception: final_aws_exception,
      final_aws_exception_message: final_aws_exception_message,
      final_sdk_exception: final_sdk_exception,
      final_sdk_exception_message: final_sdk_exception_message
    }
    if context.metadata[:redirect_region]
      complete_opts[:region] = context.metadata[:redirect_region]
    end
    request_metrics.api_call.complete(complete_opts)
    # Report the metrics by passing the complete RequestMetrics object
    if publisher
      publisher.publish(request_metrics)
    end # Else we drop all this on the floor.
  end
end