Skip to content

Instantly share code, notes, and snippets.

@brettf
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brettf/3515571f187b56b6229f to your computer and use it in GitHub Desktop.
Save brettf/3515571f187b56b6229f to your computer and use it in GitHub Desktop.
JavaScript Amazon Kinesis Stream Reader
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Javascript Amazon Kinesis Stream Reader</title>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.0.11.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.compat.min.js"></script>
<script src="https://d2cdc0w3k7b2of.cloudfront.net/d3.min.js" charset="utf-8"></script>
<script src="https://d2cdc0w3k7b2of.cloudfront.net/nv.d3.min.js"></script>
<link rel="stylesheet" href="nv.d3.css">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<!-- Optional Bootstrap theme -->
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
<style>
body {
overflow-y:scroll;
}
.barChart {
/*width: 500px;*/
height: 350px;
border: 1px;
}
.header {
border-bottom: 1px solid #ccc;
margin-bottom: 16px;
}
</style>
</head>
<body>
<div id="amazon-root"></div>
<div class="container">
<div class="row">
<div class="col-xs-9">
<h1>Kinesis Stream Reader</h1>
</div>
<div class="col-lg-1">
<h1><div id="logout"></div></h1>
</div>
</div>
</div>
<hr/>
<div class="container">
<div id="login">
<div class="jumbotron">
<p>Login with your Amazon.com credentials</p>
<p><a class="btn btn-primary btn-lg" role="button" href="#" id="LoginWithAmazon">Login <span
class="glyphicon glyphicon-log-in"></span></a></p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div id="chart" class="col-lg-12">
<svg id="chart" class="barChart" />
</div>
</div>
</div>
<script type="text/javascript">
var roleArn = 'arn:aws:iam::<accountID>:role/web-spa', // IAM Role created for Login With Amazon
awsRegion = '<region>',
streamName = '<streamname>'; // Kinesis stream that we'll use in this example
var chartData = new Array();
var colors = ['#CC6600', '#3333FF', '#33FF00']
var series = new Array();
var next_color = 0;
// Login with Amazon
window.onAmazonLoginReady = function() {
amazon.Login.setClientId('amzn1.application-oa2-client.XXXXXXXXYYYYYYYYZZZZZZZZYYYYYYYY');
};
(function(d) {
var a = d.createElement('script'); a.type = 'text/javascript';
a.async = true; a.id = 'amazon-login-sdk';
a.src = 'https://api-cdn.amazon.com/sdk/login1.js?v=3';
d.getElementById('amazon-root').appendChild(a);
})(document);
function include(arr,obj) {
return (arr.indexOf(obj) != -1);
}
function determineSeries(datum){
if (include(series, datum.key) == false) {
series.push(datum.key)
}
return series.indexOf(datum.key);
}
function drawChart(d3Data) {
var finalData = d3Data
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(100) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
;
chart.xAxis //Chart x-axis settings
.axisLabel('Time (sequence)')
.tickFormat(d3.format(',r'));
chart.yAxis //Chart y-axis settings
.axisLabel('Audio')
.tickFormat(d3.format(',f'));
d3.select('#chart svg') //Select the <svg> element you want to render the chart in.
.datum(finalData) //Populate the <svg> element with chart data...
.call(chart); //Finally, render the chart!
//Update the chart when window resizes.
nv.utils.windowResize(function() { chart.update() });
return chart;
});
}
function amazonAuth(response) {
if (response.error) {
console.log(response.error);
return;
}
document.getElementById('login').innerHTML = '';
document.getElementById('logout').innerHTML = '<button type="button" class="btn btn-danger">Logout <span class="glyphicon glyphicon-log-out"></span></button>';
AWS.config.credentials = new AWS.WebIdentityCredentials({
RoleArn: roleArn,
ProviderId: 'www.amazon.com',
WebIdentityToken: response.access_token
});
AWS.config.region = awsRegion;
kinesis = new AWS.Kinesis();
amazon.Login.retrieveProfile(response.access_token, getStream);
}
function getStream() {
kinesis.describeStream({StreamName: streamName}, function (err, data) {
if (err) {
console.log(err);
return;
}
if (_.size(data.StreamDescription.Shards > 1)) {
console.log('WARNING: this demo was designed to work with a single Kinesis shard');
}
// now get the Stream's shardIterator and start getting records in a loop
kinesis.getShardIterator({
StreamName:streamName,
ShardId:data.StreamDescription.Shards[0].ShardId,
ShardIteratorType:'LATEST'
}, getRecords);
});
}
function getRecords(err, data) {
if (err) {
console.log(err);
return;
}
kinesis.getRecords({ShardIterator:data.ShardIterator,Limit:100}, function (err, data) {
if (err) {
console.log(err);
return;
}
// process the records, determine which series they are associated with
// and add them to the Chart
for (var record in data.Records) {
/* Expected data record format
{
"values": [
{ "x": <x-axis-value-XX>, "y": <y-axis-value>},
{ "x": <x-axis-value-YY>, "y": <y-axis-value>},
{ "x": <x-axis-value-ZZ>, "y": <y-axis-value>}
...
],
"key": "<series-key-name>",
}
*/
decodedData = window.atob(data.Records[record].Data)
datum = JSON.parse(decodedData);se
if (series.indexOf(datum.key) == -1) { // new series so add metadata
chartData.push({
"values": [],
"key": datum.key,
"color": colors[next_color] });
next_color++;
}
series_number = determineSeries(datum);
chartData[series_number].values.push(datum.values) // add to the series
putRecord(datum.values.x)
// Truncate the number of data items in the chart
if (chartData[series_number].values.length > 250) {
chartData[series_number].values = chartData[series_number].values.slice(50)
}
// console.log(datum); // un-comment this to see the entire datum in the console
}
if (chartData.length > 0) {
for (var i in chartData) {
// Sort the 'values' array based upon the 'x' value
chartData[i].values.sort(function (a, b) {
if (a.x > b.x)
return 1;
if (a.x < b.x)
return -1;
// a must be equal to b
return 0;
});
}
}
drawChart(chartData);
// pass the iterator for the next batch
// and wait 500 ms before getting records again
setTimeout(function() {
data.ShardIterator = data.NextShardIterator;
getRecords(null, data);
}, 500);
});
}
document.getElementById('LoginWithAmazon').onclick = function() {
options = { scope : 'profile' };
amazon.Login.authorize(options, amazonAuth);
};
document.getElementById('logout').onclick = function() {
amazon.Login.logout();
location.reload();
};
</script>
<script src="https://code.jquery.com/jquery.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</div></body></html>
@maxrabin
Copy link

Line 151 should be

        if (_.size(data.StreamDescription.Shards) > 1) {

instead of

        if (_.size(data.StreamDescription.Shards > 1)) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment