AWSTemplateFormatVersion: "2010-09-09" Description: | Creates a CloudWatch Dashboard and set of CloudWatch Alarms for monitoring Amazon Connect resources. Optionally uses Salesforce API's to send alerts to a specified chatter feed when certain Amazon Connect metrics breach configured alarm thresholds. Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Environment Parameters: - AWSRegion - AWSSCVCommonRole - AWSSCVCommonPythonLayer - ConnectInstanceId - SalesforceConfig - SalesforceOrgId - SalesforceChatterFeedId - DashboardName - Label: default: Concurrent Calls Alarm Parameters: - ConcurrentCallsPeriod - ConcurrentCallsEvaluationPeriods - ConcurrentCallsThreshold - Label: default: Concurrent Calls Percentage Alarm Parameters: - ConcurrentCallsPercentagePeriod - ConcurrentCallsPercentageEvaluationPeriods - ConcurrentCallsPercentageThreshold - Label: default: Throttled Calls Percentage Alarm Parameters: - ThrottledCallsPeriod - ThrottledCallsEvaluationPeriods - ThrottledCallsThreshold - Label: default: Misconfigured Phone Numbers Alarm Parameters: - MisconfiguredPhoneNumbersPeriod - MisconfiguredPhoneNumbersEvaluationPeriods - MisconfiguredPhoneNumbersThreshold - Label: default: Missed Calls Calls Alarm Parameters: - MissedCallsPeriod - MissedCallsEvaluationPeriods - MissedCallsThreshold - Label: default: Contact Flow Alarms Parameters: - ContactFlowName - ContactFlowFatalErrorsPeriod - ContactFlowFatalErrorsEvaluationPeriods - ContactFlowFatalErrorsThreshold Parameters: AWSS3BucketPrefix: Type: String Default: '' Description: Not required and only used for development purposes. AWSRegion: Type: String Default: us-east-1 AllowedValues: - us-east-1 - us-west-2 - ap-southeast-1 - ap-southeast-2 - ap-northeast-1 - eu-central-1 - eu-west-2 Description: The region code that you are deploying to. MAKE SURE that you have your console currently set to this region. Must be a region that supports Service Cloud Voice. AWSSCVCommonRole: Type: String Default: REPLACEME Description: ARN of the awsscv_common_role role AWSSCVCommonPythonLayer: Type: String Default: REPLACEME Description: ARN for the AWSSCV Common Python Layer. SalesforceConfig: Type: String Default: REPLACEME Description: ARN for your Salesforce config in AWS Secrets Manager. ConnectInstanceId: Description: The id of the Connect instance to monitor. Default: REPLACEME Type: String SalesforceOrgId: Description: The id of the Salesforce organization. Default: REPLACEME Type: String SalesforceChatterFeedId: Description: The id of the Salesforce chatter feed. (Optional) Type: String DashboardName: Description: The CloudWatch dashboard name. Type: String Default: AmazonConnectMetrics AllowedPattern: "^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" ConstraintDescription: "Dashboard name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-)." ConcurrentCallsPeriod: Description: Data evaluation period in seconds Type: Number Default: 60 ConcurrentCallsEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 3 ConcurrentCallsThreshold: Description: Limit above which alarms are raised Type: Number Default: 90 ConcurrentCallsPercentagePeriod: Description: Data evaluation period in seconds Type: Number Default: 60 ConcurrentCallsPercentageEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 3 ConcurrentCallsPercentageThreshold: Description: Limit above which alarms are raised Type: Number Default: 0.8 ThrottledCallsPeriod: Description: Data evaluation period in seconds Type: Number Default: 60 ThrottledCallsEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 3 ThrottledCallsThreshold: Description: Limit above which alarms are raised Type: Number Default: 1 MisconfiguredPhoneNumbersPeriod: Description: Data evaluation period in seconds Type: Number Default: 60 MisconfiguredPhoneNumbersEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 1 MisconfiguredPhoneNumbersThreshold: Description: Limit above which alarms are raised Type: Number Default: 1 MissedCallsPeriod: Description: Data evaluation period in seconds Type: Number Default: 60 MissedCallsEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 1 MissedCallsThreshold: Description: Limit above which alarms are raised Type: Number Default: 1 ContactFlowName: Description: The contact flow name (Optional) Type: String ContactFlowFatalErrorsPeriod: Description: Data evaluation period in seconds Type: Number Default: 60 ContactFlowFatalErrorsEvaluationPeriods: Description: Group size of data evaluation periods Type: Number Default: 1 ContactFlowFatalErrorsThreshold: Description: Limit above which alarms are raised Type: Number Default: 1 Conditions: HasSalesforceChatterFeedId: 'Fn::Not': - !Equals - '' - !Ref SalesforceChatterFeedId HasContactFlowName: 'Fn::Not': - !Equals - '' - !Ref ContactFlowName Resources: SCVAlarmToChatterLambda: Type: AWS::Lambda::Function Condition: HasSalesforceChatterFeedId Properties: Code: S3Bucket: !Join - '' - - !Ref AWSS3BucketPrefix - 'awsscv-supporting-code-' - !Ref AWSRegion S3Key: awsscv_alarm_to_chatter.zip Description: Writes alarm to Salesforce Chatter feed Environment: Variables: sf_config_sm_arn: Ref: SalesforceConfig sf_chatter_feed_id: Ref: SalesforceChatterFeedId FunctionName: !Join - '' - - 'AWSSCV_alarm_to_chatter_' - !Ref ConnectInstanceId Handler: awsscv_alarm_to_chatter.lambda_handler Role: !Ref AWSSCVCommonRole Layers: [ !Ref AWSSCVCommonPythonLayer ] Runtime: python3.8 Timeout: 900 SCVAlarmToLog: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Join - '' - - !Ref AWSS3BucketPrefix - 'awsscv-supporting-code-' - !Ref AWSRegion S3Key: awsscv_alarm_to_log.zip Description: Writes alarm to CloudWatch logs FunctionName: !Join - '' - - 'AWSSCV_alarm_to_log_' - !Ref ConnectInstanceId Handler: awsscv_alarm_to_log.lambda_handler Role: !Ref AWSSCVCommonRole Runtime: python3.8 Timeout: 900 SnsTopic: Type: "AWS::SNS::Topic" DependsOn: - SCVAlarmToChatterLambda Properties: TopicName: !Join - '' - - 'AWSSCV_alarm_topic_' - !Ref ConnectInstanceId Subscription: - Protocol: lambda Endpoint: !GetAtt SCVAlarmToChatterLambda.Arn SCVAlarmToChatterLambdaPermission: Type: "AWS::Lambda::Permission" Condition: HasSalesforceChatterFeedId Properties: Action: 'lambda:InvokeFunction' FunctionName: !Ref SCVAlarmToChatterLambda Principal: sns.amazonaws.com SCVAlarmToLogPermission: Type: "AWS::Lambda::Permission" Properties: Action: 'lambda:InvokeFunction' FunctionName: !Ref SCVAlarmToLog Principal: sns.amazonaws.com AlarmDashboard: Type: "AWS::CloudWatch::Dashboard" Properties: DashboardName: !Ref DashboardName DashboardBody: !If - HasContactFlowName - !Sub '{"widgets":[{"type":"metric","x":0,"y":10,"width":9,"height":6,"properties":{"title":"Misconfigured Phone Numbers","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Misconfigured Phone Numbers InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":0,"y":1,"width":6,"height":6,"properties":{"title":"Concurrent Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Concurrent Calls InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":6,"y":1,"width":6,"height":6,"properties":{"title":"Concurrent Calls Percentage","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Concurrent Calls Percentage InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":12,"y":7,"width":6,"height":3,"properties":{"title":"Throttled Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Throttled Calls InstanceId ${ConnectInstanceId}"]},"view":"singleValue","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":0,"y":7,"width":6,"height":3,"properties":{"view":"singleValue","metrics":[["AWS/Connect","ConcurrentCalls","InstanceId","${ConnectInstanceId}","MetricGroup","VoiceCalls"]],"region":"${AWS::Region}","period":300,"title":"Concurrent Calls"}},{"type":"metric","x":6,"y":7,"width":6,"height":3,"properties":{"view":"singleValue","metrics":[["AWS/Connect","ConcurrentCallsPercentage","InstanceId","${ConnectInstanceId}","MetricGroup","VoiceCalls"]],"region":"${AWS::Region}","title":"Concurrent Calls Percentage"}},{"type":"metric","x":12,"y":1,"width":6,"height":6,"properties":{"title":"Throttled Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Throttled Calls InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":9,"y":10,"width":9,"height":6,"properties":{"title":"Connect Contact Flow Fatal Errors Contact Flow test InstanceId ${ConnectInstanceId}","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Contact Flow Fatal Errors Contact Flow ${ContactFlowName} InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"text","x":0,"y":0,"width":18,"height":1,"properties":{"markdown":"# Amazon Connect Alarm Dashboard"}}]}' - !Sub '{"widgets":[{"type":"metric","x":0,"y":10,"width":9,"height":6,"properties":{"title":"Misconfigured Phone Numbers","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Misconfigured Phone Numbers InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":0,"y":1,"width":6,"height":6,"properties":{"title":"Concurrent Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Concurrent Calls InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":6,"y":1,"width":6,"height":6,"properties":{"title":"Concurrent Calls Percentage","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Concurrent Calls Percentage InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":12,"y":7,"width":6,"height":3,"properties":{"title":"Throttled Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Throttled Calls InstanceId ${ConnectInstanceId}"]},"view":"singleValue","stacked":false,"legend":{"position":"hidden"}}},{"type":"metric","x":0,"y":7,"width":6,"height":3,"properties":{"view":"singleValue","metrics":[["AWS/Connect","ConcurrentCalls","InstanceId","${ConnectInstanceId}","MetricGroup","VoiceCalls"]],"region":"${AWS::Region}","period":300,"title":"Concurrent Calls"}},{"type":"metric","x":6,"y":7,"width":6,"height":3,"properties":{"view":"singleValue","metrics":[["AWS/Connect","ConcurrentCallsPercentage","InstanceId","${ConnectInstanceId}","MetricGroup","VoiceCalls"]],"region":"${AWS::Region}","title":"Concurrent Calls Percentage"}},{"type":"metric","x":12,"y":1,"width":6,"height":6,"properties":{"title":"Throttled Calls","annotations":{"alarms":["arn:aws:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:Connect Throttled Calls InstanceId ${ConnectInstanceId}"]},"view":"timeSeries","stacked":false,"legend":{"position":"hidden"}}},{"type":"text","x":0,"y":0,"width":18,"height":1,"properties":{"markdown":"# Amazon Connect Alarm Dashboard"}}]}' ConcurrentCallsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "Connect Concurrent Calls InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of concurrent active voice calls in the connect instance during the evaluation period was greater than ${ConcurrentCallsThreshold}. All active voice calls are included, not only active calls that are connected to agents. Open a support ticket with Amazon and request a Concurrent call limit increase for the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: ConcurrentCalls Statistic: Maximum Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref ConcurrentCallsPeriod Threshold: !Ref ConcurrentCallsThreshold EvaluationPeriods: !Ref ConcurrentCallsEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: VoiceCalls ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching" ConcurrentCallsPercentageAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "Connect Concurrent Calls Percentage InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of concurrent active voice calls in the connect instance during the evaluation period was greater than ${ConcurrentCallsPercentageThreshold}. All active voice calls are included, not only active calls that are connected to agents. Open a support ticket with Amazon and request a Concurrent call limit increase for the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: ConcurrentCallsPercentage Statistic: Maximum Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref ConcurrentCallsPercentagePeriod Threshold: !Ref ConcurrentCallsPercentageThreshold EvaluationPeriods: !Ref ConcurrentCallsPercentageEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: VoiceCalls ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching" ThrottledCallsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "Connect Throttled Calls InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of voice calls that were throttled by the Amazon Connect service because the rate of calls per second (Callrate) exceeded the configured limit for the instance during the evaluation period was greater than ${ThrottledCallsThreshold}. Open a support ticket with Amazon and request a Callrate limit increase for the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: ThrottledCalls Statistic: Maximum Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref ThrottledCallsPeriod Threshold: !Ref ThrottledCallsThreshold EvaluationPeriods: !Ref ThrottledCallsEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: VoiceCalls ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching" MisconfiguredPhoneNumbersAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "Connect Misconfigured Phone Numbers InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of calls that failed because the phone number is not associated with a contact flow. Review phone number / contact flow assignments in the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: MisconfiguredPhoneNumbers Statistic: SampleCount Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref MisconfiguredPhoneNumbersPeriod Threshold: !Ref MisconfiguredPhoneNumbersThreshold EvaluationPeriods: !Ref MisconfiguredPhoneNumbersEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: VoiceCalls ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching" MissedCallsAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "Connect Missed Calls InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of calls that were missed by agents during the refresh interval. A missed call is one that is not answered by an agent within 20 seconds. Review configuration in the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: MissedCalls Statistic: SampleCount Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref MissedCallsPeriod Threshold: !Ref MissedCallsThreshold EvaluationPeriods: !Ref MissedCallsEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: VoiceCalls ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching" ContactFlowFatalErrorsAlarm: Type: AWS::CloudWatch::Alarm Condition: HasContactFlowName Properties: AlarmName: !Sub "Connect Contact Flow Fatal Errors Contact Flow ${ContactFlowName} InstanceId ${ConnectInstanceId}" AlarmDescription: !Sub "The number of times a contact flow failed to execute due to a system error. Review the contact flow ${ContactFlowName} in the instance ${ConnectInstanceId} in account ${AWS::AccountId}" Namespace: AWS/Connect MetricName: ContactFlowFatalErrors Statistic: SampleCount Unit: Count AlarmActions: - !Ref SnsTopic OKActions: - !Ref SnsTopic Period: !Ref ContactFlowFatalErrorsPeriod Threshold: !Ref ContactFlowFatalErrorsThreshold EvaluationPeriods: !Ref ContactFlowFatalErrorsEvaluationPeriods Dimensions: - Name: InstanceId Value: !Ref ConnectInstanceId - Name: MetricGroup Value: ContactFlow - Name: ContactFlowName Value: !Ref ContactFlowName ComparisonOperator: GreaterThanOrEqualToThreshold TreatMissingData: "notBreaching"