Enabling CloudWatch Logs for Pinpoint SMS Voice Events
Tags: aws, cloudwatch, pinpointvoice, smsvoice
Published: 2021-07-19 17:33:46

In order to enable CloudWatch logs for Pinpoint SMS Voice events, we'll have to use the API as there is currently not a way to do this from the AWS console. I'll be showing examples using python/boto3, but you can reference the [API docs][0] or your language's equivalent library. This article assumes you already have a working Voice setup.

## Initial Setup

We'll need to setup two things in AWS before we proceed. A role that has permissions to write CloudWatch log events and a CloudWatch Log Group to contain those events.

The Log Group is easy, just create a new Log Group within CloudWatch with a relevant name and settings as you see fit.

The IAM Role is pretty much standard, except you won't find Pinpoint or SMS Voice in the list of services when choosing a the trusted entity. We will need to manually change this after creating the role, so just pick something like Lambda. For permissions, you need to make sure the role has access to at least `logs:PutLogEvents`. Finish by giving the role a name and any other info AWS needs.

Now we need to modify the trust relationships for the role we just created. Find it under the Roles page and click on it to get to the Summary page. There should be a tab called "Trust relationships". On that tab, you'll see something like `lambda.amazonaws.com` under Trusted entities. Click "Edit trust relationship" and you'll get an editor page with some JSON. Find `"Service"` and change the value to `sms-voice.amazonaws.com`.

**Important:** If you don't add sms-voice, future steps will work correctly, but you will never get event data in CloudWatch. This caused a lot of frustration and took me a while to figure out. I wasn't able to find anything when searching for the solution, which is the entire reason why I'm writing this article.

## Creating the Configuration Set

Now we need to create a Configuration Set for SMS Voice. We will give the config set a name that we'll pass to the API when sending a Voice message later. 
```python
# Change region to match your setup
voice_client = boto3.client('sms-voice', region_name='us-east-1')

# Feel free to change the config set name
voice_client.create_configuration_set(
    ConfigurationSetName='default-config-set'
)
```

## Creating the Event Destination

Next, we'll need to create an Event Destination tied to our new Configuration Set. The Event Destination contains details on where to send the voice events. It has three options for where to send events: CloudWatch, SNS, and Kinesis. Obviously, we'll choose CloudWatch, but you can create multiple Event Destinations tied to the same Configuration Set if you need to.

```python
voice_client.create_configuration_set_event_destination(
    # references the name for the config set we just created
    ConfigurationSetName='default-config-set',
    # feel free to change the event destination name below
    EventDestinationName='cloudwatch-all-events',
    Enabled=True,
    MatchingEventTypes=[
        # this is a list of all events, but you can omit those you don't need
        'INITIATED_CALL',
        'RINGING',
        'ANSWERED',
        'COMPLETED_CALL',
        'BUSY',
        'FAILED',
        'NO_ANSWER',
    ], 
    CloudWatchLogsDestination={
        # the ARN for the role we created earlier
        'IamRoleArn': 'arn:aws:iam::12345:role/SMSVoiceLogging', 
         # the ARN for the log group we created earlier 
        'LogGroupArn': 'arn:aws:logs:us-east-1:12345:log-group:SMSVoiceLogs:*'
    }
)
```

The `EventDestinationName` is just a reference for you to update the Event Destination later (if necessary).

Assuming you had no errors, you should now be able to send a Voice message referencing the newly created Configuration Set and have event logs for the call in CloudWatch.

## Time to Test

```python
response = voice_client.send_voice_message(
        DestinationPhoneNumber='+10005551234',
        OriginationPhoneNumber='+19995551234',
        ConfigurationSetName='default-config-set',
        Content={
            'SSMLMessage': {
                'LanguageCode': 'en-US',
                'Text': "<speak><break time='2s' />This is a test message. You should have several events in CloudWatch after receiving this message.</speak>",
                'VoiceId': 'Salli'
            }
        }
    )
```

If you don't see any logs in CloudWatch after sending the message, check that your Event Destination is still enabled:

```python
response = voice_client.get_configuration_set_event_destinations(
    ConfigurationSetName='default-config-set'
)

del response['ResponseMetadata'] # for readability, not required

print(response)
```

Find the correct Event Destination (if you have multiple) and look for the `Enabled` value. If your Event Destination has been disabled, make sure that the role is setup correctly (especially the trust relationship) and all of your ARNs are referencing the correct entities.

## Updating Event Destinations

If you need to make any changes to the Event Destination, you can use the same code we wrote when creating it, but change `create` to `update` and update the arguments as needed.

```python
voice_client.update_configuration_set_event_destination(
    ConfigurationSetName='default-config-set',
    EventDestinationName='cloudwatch-all-events',
    Enabled=True,
    MatchingEventTypes=[
        'INITIATED_CALL',
        'RINGING',
        'ANSWERED',
        'COMPLETED_CALL',
        'BUSY',
        'FAILED',
        'NO_ANSWER',
    ], 
    CloudWatchLogsDestination={
        'IamRoleArn': 'arn:aws:iam::12345:role/SMSVoiceLogging', 
        'LogGroupArn': 'arn:aws:logs:us-east-1:12345:log-group:SMSVoiceLogs:*'
    }
)
```

[0]: https://docs.aws.amazon.com/pinpoint-sms-voice/latest/APIReference/resources.html