このラボでは、Kinesis Streams を使用して、Amazon Connect の問い合わせ履歴である CTR(Contact Trace Record) およびエージェントイベントストリームを Amazon DynamoDB にエクスポートします。
このラボで使用する IAM ポリシーの json、Lambda 関数のコードはこちら からダウンロード可能です。
kinesisCtrStream
)。この名前をメモしておきます。Connect-ContactTraceRecords
(文字列)ContactId
(文字列)ctrToDynamo
)。DynamoDB に書き込みを許可する IAM ポリシーを作成し、Lambda にアタッチ
JSON タブを開き、以下に示す IAM ポリシーのサンプルをペーストします。このとき Resource 欄の kinesis の ARN と、dynamodb の ARN を、メモしておいた値に書き換えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:DescribeTable",
"kinesis:GetShardIterator",
"dynamodb:GetItem",
"kinesis:GetRecords",
"kinesis:DescribeStream",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:kinesis:us-east-1:xxxxxxxxxxx:stream/kinesisCtrStream",
"arn:aws:dynamodb:us-east-1:xxxxxxxxxxx:table/Connect-ContactTraceRecords"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "kinesis:ListStreams",
"Resource": "*"
}
]
}
次のステップ:タグをクリックます。このページでは何も設定しません。
次のステップ:確認をクリックします。
ポリシーの名前を入力し(例:ctrKinesisDynamoPolicy
)、ポリシーの作成をクリックします。
作成したポリシーを既存のロールにアタッチします。サイドバーのロールに移動します。
Lambda 作成時にメモしておいたロール名を検索し、ヒットしたロール名をクリックします。
ポリシーをアタッチしますをクリックします。
検索を使用して、上記で作成したポリシー名を検索します。ヒットしたポリシーのチェックボックスをオンにして、ポリシーのアタッチをクリックします。
Lambda のトリガーに Kinesis ストリームを設定
コードタブに移動し、コードソースセクションに、以下のサンプルコードをコピーして貼り付け、Deploy をクリックします。
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
console.log(JSON.stringify(event, null, 2));
event.Records.forEach(function(record) {
// Kinesis data is base64 encoded so decode here
let payload = new Buffer.from(record.kinesis.data, 'base64');
console.log('Decoded payload:', payload.toString('utf8'));
// Create a JSON object from the core payload
let dpObject = JSON.parse(payload.toString('utf8'));
console.log('Converting to JSON:', dpObject.toString());
// Extract the fields that will be inserted into the DynamoDB table
if (dpObject){
let ContactId = dpObject.ContactId;
let AgentUsername = "";
if (dpObject.Agent){
AgentUsername = dpObject.Agent.Username;
}
let CallerAni = dpObject.CustomerEndpoint.Address;
let Timestamp = dpObject.DisconnectTimestamp;
//Create the item to be inserted into the table
let item = {
"ContactId": ContactId,
"Agent": AgentUsername,
"CallerAni": CallerAni,
"Timestamp": Timestamp
};
const tableName = "Connect-ContactTraceRecords";
let params = {
TableName: tableName,
Item: item
};
//Insert the item into the database
docClient.put(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
}
});
};
Amazon Connect インスタンスで取得した番号に電話から発信を行い、DynamoDB テーブルに値が入力されることを確認します。
kinesisAgentStream
)。この名前をメモしておきます。Connect-AgentEvents
(文字列)agentId
(文字列)agentToDynamo
)。DynamoDB に書き込みを許可する IAM ポリシーを作成し、Lambda にアタッチ
JSON タブを開き、以下に示すIAMポリシーのサンプルをペーストします。このとき Resource 欄の kinesis の ARN と、dynamodb の ARN を、メモしておいた値に書き換えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:DescribeTable",
"kinesis:GetShardIterator",
"dynamodb:GetItem",
"kinesis:GetRecords",
"kinesis:DescribeStream",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:kinesis:us-east-1:xxxxxxxxxxx:stream/kinesisAgentStream",
"arn:aws:dynamodb:us-east-1:xxxxxxxxxxx:table/Connect-AgentEvents"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "kinesis:ListStreams",
"Resource": "*"
}
]
}
次のステップ:タグをクリックます。このページでは何も設定しません。
次のステップ:確認をクリックします。
ポリシーの名前を入力し(例:agentKinesisDynamoPolicy
)、ポリシーの作成をクリックします。
作成したポリシーを既存のロールにアタッチします。サイドバーのロールに移動します。
Lambda 作成時にメモしておいたロール名を検索し、ヒットしたロール名をクリックします。
ポリシーをアタッチしますをクリックします。
検索を使用して、上記で作成したポリシー名を検索します。ヒットしたポリシーのチェックボックスをオンにして、ポリシーのアタッチをクリックします。
Lambda のトリガーに Kinesis ストリームを設定
コードタブに移動し、コードソースセクションに、以下のサンプルコードをコピーして貼り付け、Deployをクリックします。
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
if (event.Records) {
for (var record of event.Records) {
// Kinesis data is base64 encoded so decode here
var payload = Buffer.from(record.kinesis.data, 'base64').toString('utf-8');
if (payload) {
var eventData = JSON.parse(payload);
logState(eventData);
}
}
}
};
function logState(record) {
console.log('entering logState', record);
if (record && record.EventType && record.EventType != 'HEART_BEAT')
{
console.log('I have an event type', record.EventType);
if (
record.CurrentAgentSnapshot &&
record.CurrentAgentSnapshot.Configuration &&
record.CurrentAgentSnapshot.Configuration.Username)
{
console.log('processing record', record);
var hierarchy = getHierarchy(record);
var contact = getContact(record.CurrentAgentSnapshot.Contacts);
var paramsPut = {
TableName: 'Connect-AgentEvents',
Item:{
"agentId": record.CurrentAgentSnapshot.Configuration.Username,
"name": (record.CurrentAgentSnapshot.Configuration.FirstName + " " +
record.CurrentAgentSnapshot.Configuration.LastName),
"hierarchy": hierarchy,
"state": record.CurrentAgentSnapshot.AgentStatus.Name,
"stateStartTime": record.CurrentAgentSnapshot.AgentStatus.StartTimestamp,
"contactId": (contact ? contact.contactId : null),
"initialContactId": (contact ? contact.initialContactId : null),
"contactChannel": (contact ? contact.contactChannel : null),
"contactQueue": (contact ? contact.contactQueue : null),
"contactState": (contact ? contact.contactState : null),
"prevState": record.PreviousAgentSnapshot.AgentStatus.Name,
"prevStateStartTime": record.PreviousAgentSnapshot.AgentStatus.StartTimestamp
}
};
console.log("updating state for ", paramsPut.Item.agentid);
docClient.put(paramsPut, function(err, data) {
if (err) {
console.log(err);
}
});
}
}
}
function getHierarchy(record)
{
var hierarchy = "";
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups)
{
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level1){
hierarchy = record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level1.Name;
}
hierarchy += "-";
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level2){
hierarchy += record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level2.Name;
}
hierarchy += "-";
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level3){
hierarchy += record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level3.Name;
}
hierarchy += "-";
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level4){
hierarchy += record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level4.Name;
}
hierarchy += "-";
if (record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level5){
hierarchy += record.CurrentAgentSnapshot.Configuration.AgentHierarchyGroups.Level5.Name;
}
}
console.log('hierarchy', hierarchy);
return hierarchy;
}
function getContact(contacts){
if (contacts.length > 0){
console.log('contacts', contacts);
var contact = {
"contactId": contacts[0].ContactId,
"initialContactId": contacts[0].InitialContactId,
"contactChannel": contacts[0].Channel,
"contactQueue": contacts[0].Queue ? contacts[0].Queue.Name : "",
"contactState": contacts[0].State
};
console.log('contact',contact);
return contact;
}
console.log('no contacts');
return null;
}
Connect インスタンスで取得した番号に電話から発信してエージェントで受けたり、エージェントステータスを変更して、DynamoDB テーブルに値が入力されることを確認します。
このラボでは、Amazon Connect の CTR、エージェントイベントをストリーミング出力する方法を確認しました。Amazon DynamoDB に記録された CTR やエージェントイベントを出力・整形することで、任意の形式にレポートを生成することが可能になり、より柔軟にコンタクトセンターの稼働状況を可視化することが可能になります。