in source/resources/solution-helper/lib/cloudwatch-helper.js [62:281]
createDashboard(event) {
let cloudwatch = new AWS.CloudWatch(this.config);
console.log(`Generate dashboard with input params: ${JSON.stringify(event)}`);
let widgets = [];
// Dashboard Header
widgets.push({
type: 'text',
x: 0,
y: 0,
width: 24,
height: 2,
properties: {
markdown: '\n# **Game Analytics Pipeline - Operational Health**\nThis dashboard contains operational metrics for the Game Analytics Pipeline. Use these metrics to help you monitor the operational status of the AWS services used in the solution and track important application metrics.\n'
}
});
// Stream Ingestion and Processing Header
widgets.push({
type: 'text',
x: 0,
y: 2,
width: 12,
height: 3,
properties: {
markdown: `\n## Stream Ingestion & Processing\nThis section covers metrics related to ingestion of data into the solution's Events Stream and processing by Kinesis Data Firehose and AWS Lambda Events Processing Function. Use the metrics here to track data freshness/latency and any issues with processor throttling/errors. \n`
}
});
// Events Ingestion and Delivery
widgets.push({
type: 'metric',
x: 0,
y: 8,
width: 6,
height: 6,
properties: {
metrics: [
['AWS/Kinesis', 'IncomingRecords', 'StreamName', event.Kinesis.GameEventsStream, {id: 'records', color: '#2ca02c', label: 'Events Stream Incoming Records (Kinesis)'}],
['AWS/Firehose', 'DeliveryToS3.Records', 'DeliveryStreamName', event.Kinesis.GameEventsFirehose, {id: 'delivered', label: 'Firehose Records Delivered to S3', color: '#17becf'}],
['AWS/ApiGateway', 'Count', 'ApiName', event.GameAnalyticsApi.Name, 'Resource', '/applications/{applicationId}/events', 'Stage', event.GameAnalyticsApi.Stage, 'Method', 'POST', {label: 'Events REST API Request Count', color: '#1f77b4'}]
],
view: 'timeSeries',
stacked: false,
region: this.config.region,
title: 'Events Ingestion and Delivery',
stat: 'Sum',
yAxis: {
left: {
label: 'Count',
showUnits: false
}
}
}
});
// Events Processing Function Error and Success Rate
widgets.push({
type: 'metric',
x: 6,
y: 8,
width: 6,
height: 6,
properties: {
metrics: [
['AWS/Lambda','Errors', 'FunctionName', event.Functions.EventsProcessingFunction, 'Resource', event.Functions.EventsProcessingFunctionArn, {id: 'errors', stat: 'Sum', color: '#d13212', region: this.config.region}],
['AWS/Lambda', 'Invocations', 'FunctionName', event.Functions.EventsProcessingFunction, 'Resource', event.Functions.EventsProcessingFunctionArn, {id: 'invocations', stat: 'Sum', visible: false, region: this.config.region}],
[{ expression: '100 - 100 * errors / MAX([errors, invocations])', label: 'Success rate (%)', id: 'availability', yAxis: 'right', region: this.config.region}]
],
region: this.config.region,
title: 'Lambda Error count and success rate (%)',
period: 60,
stat: 'Sum',
yAxis: {
right: {
max: 100,
label: 'Percent',
showUnits: false
},
left: {
showUnits: false,
label: ''
}
},
view: 'timeSeries',
stacked: false
}
});
// Events Processing Health
widgets.push({
type: 'metric',
x: 0,
y: 5,
width: 12,
height: 3,
properties: {
metrics: [
['AWS/Firehose', 'DeliveryToS3.DataFreshness', 'DeliveryStreamName', event.Kinesis.GameEventsFirehose, {visible: true, label: 'Data Freshness', period: 300, id: 'datafreshness', stat: 'Maximum'}],
['AWS/Lambda', 'Duration', 'FunctionName', event.Functions.EventsProcessingFunction, 'Resource', event.Functions.EventsProcessingFunctionArn, {id: 'duration', label: 'Lambda Duration', stat: 'Average', period: 300}],
['AWS/Lambda', 'ConcurrentExecutions', 'FunctionName', event.Functions.EventsProcessingFunction, {visible: true, label: 'Lambda Concurrency', id: 'concurrency', stat: 'Maximum', period: 300}],
['AWS/Lambda', 'Throttles', 'FunctionName', event.Functions.EventsProcessingFunction, {label: 'Lambda Throttles', id: 'throttles', visible: true, stat: 'Sum', period: 300}]
],
view: 'singleValue',
stacked: true,
region: this.config.region,
title: 'Events Processing Health',
stat: 'Average'
}
});
// Optionally create widgets for streaming analytics solution components if enabled
if (event.StreamingAnalyticsEnabled === 'true') {
// Streaming Analytics Header
widgets.push({
type: 'text',
x: 12,
y: 2,
width: 12,
height: 3,
properties: {
markdown: '\n## Real-time Streaming Analytics\nThe below metrics can be used to monitor the real-time streaming SQL analytics of events. Use the Kinesis Data Analytics MillisBehindLatest metric to help you track the lag on the Kinesis SQL Application from the latest events. The Analytics Processing function that processes KDA application outputs can be tracked to measure function concurrency, success percentage, processing duration and throttles.\n'
}
});
// Streaming Analytics Function
widgets.push({
type: 'metric',
properties: {
metrics: [
['AWS/Lambda', 'ConcurrentExecutions', 'FunctionName', event.Functions.AnalyticsProcessingFunction, {label: 'Analytics Processing Concurrent Executions', stat: 'Maximum', id: 'concurrency'}],
['.', 'Duration', '.', '.', {label: 'Lambda Duration', id: 'duration', stat: 'Average'}],
['.', 'Throttles', '.', '.', {label: 'Lambda Throttles', id: 'throttles'}]
],
view: 'singleValue',
region: this.config.region,
title: 'Real-time Analytics Health',
stat: 'Sum',
setPeriodToTimeRange: false
},
x: 12,
y: 5,
width: 12,
height: 3
});
// Kinesis Analytics SQL Application
widgets.push({
type: 'metric',
x: 12,
y: 8,
width: 6,
height: 6,
properties: {
metrics: [
['AWS/KinesisAnalytics', 'MillisBehindLatest', 'Id', '1.1', 'Application', event.Kinesis.KinesisAnalyticsApp, 'Flow', 'Input']
],
view: 'timeSeries',
stacked: true,
period: 60,
region: this.config.region,
stat: 'Average',
title: 'Kinesis Analytics Latency'
}
});
// Analytics Processing Function Error and Success Rate
widgets.push({
type: 'metric',
x: 18,
y: 8,
width: 6,
height: 6,
properties: {
metrics: [
['AWS/Lambda','Errors', 'FunctionName', event.Functions.AnalyticsProcessingFunction, 'Resource', event.Functions.AnalyticsProcessingFunctionArn, {id: 'errors', stat: 'Sum', color: '#d13212', region: this.config.region}],
['AWS/Lambda', 'Invocations', 'FunctionName', event.Functions.AnalyticsProcessingFunction, 'Resource', event.Functions.AnalyticsProcessingFunctionArn, {id: 'invocations', stat: 'Sum', visible: false, region: this.config.region}],
[{ expression: '100 - 100 * errors / MAX([errors, invocations])', label: 'Success rate (%)', id: 'availability', yAxis: 'right', region: this.config.region}]
],
region: this.config.region,
title: 'Lambda Error count and success rate (%)',
period: 60,
stat: 'Sum',
yAxis: {
right: {
max: 100,
label: 'Percent',
showUnits: false
},
left: {
showUnits: false,
label: ''
}
},
view: 'timeSeries',
stacked: false
}
});
}
console.log(`widgets: ${JSON.stringify(widgets)}`);
let dashboard = {
widgets: widgets
};
return new Promise((resolve, reject) => {
const params = {
DashboardName: event.DashboardName,
DashboardBody: JSON.stringify(dashboard)
};
cloudwatch.putDashboard(params, function(err, data) {
if (err) {
console.log(JSON.stringify(err));
reject(err);
} else {
console.log(data);
resolve(data);
}
})
});
}