Skip to content

Example of using Node js and d3 to build a dashboard for data stored in Cassandra

Notifications You must be signed in to change notification settings

simonambridge/chartDSE

Repository files navigation

chartDSE

A simple demonstration of charting data from DSE/Cassandra tables generated by a Spark streaming data source. Visualised using a d3 dashboard using a ReST json API, collecting data from DSE using the DataStax Nodejs driver.

Source Data

This demo queries two Cassandra tables and displays the data visually:

You can change the simplechart.html file to query and display data from a different table if you wish. If you do this you will also need to edit app.js to change the ReST API query for your table.

Pre-Requisites

Install node.js

$ sudo curl -sL https://deb.nodesource.com/setup_7.x | sudo bash -
$ sudo apt-get install nodejs
$ npm install pug
$ npm install cassandra-driver

Create test project to test Node server

$ mkdir test
$ cd test
$ npm init
$ npm install express --save
$ npm install connect serve-static
$ sudo npm install express-generator -g

The default server definition file is app.js - this displays a simple Hello message:

$ vi app.js

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Start the simple node server app:

$ node app.js

Example app listening on port 3000!

In your browser go to http://127.0.0.1:3000/

The browser displays:

HelloWorld!

Kill the server (press ^C).

Simple Static Content Server Example

If you simply want to serve static content (e.g. HTML files) you could try this:

$ node server - runs server.js file

This provides a simple server on port 8000 e.g. http://localhost:8000/chartdse/public/index.html

The server.js file is very simple:

var connect = require('connect');
var serveStatic = require('serve-static');
connect().use(serveStatic(__dirname)).listen(8000);

if no start script is in package .json it will default to this server.js

See also http://expressjs.com/en/starter/basic-routing.html

Build The chartDSE Application

Now let's create a proper node application.

From a parent directory create a new project and directory:

$ express chartdse

   create : chartdse
   create : chartdse/package.json
   create : chartdse/app.js
   create : chartdse/public
   create : chartdse/routes
   create : chartdse/routes/index.js
   create : chartdse/routes/users.js
   create : chartdse/views
   create : chartdse/views/index.jade
   create : chartdse/views/layout.jade
   create : chartdse/views/error.jade
   create : chartdse/bin
   create : chartdse/bin/www
   create : chartdse/public/javascripts
   create : chartdse/public/images
   create : chartdse/public/stylesheets
   create : chartdse/public/stylesheets/style.css

   install dependencies:
     $ cd chartdse && npm install

   run the app:
     $ DEBUG=chartdse:* npm start

Go into the directory that was created.

$ cd ../chartdse

Install local package dependencies:

$ npm install

Run this command to start the node server:

DEBUG=chartdse:* npm start           

Server process output:

> chartdse@0.0.0 start /root/chartdse
> node ./bin/www
  chartdse:server Listening on port 3000 +0ms

GET / 200 364.402 ms - 170
GET /stylesheets/style.css 200 5.804 ms - 111

Go to http://127.0.0.1:3000/

The browser displays:

Express

Welcome to Express

Our Express app is now up and running!

Now from the parent directory clone the repo contents into the project directory:

$ git clone http://gitchub.com/simonambridge/chartDSE

This will overlay the repo files into the directory structure created by Express.

Important Files

  • app.js - defines the environment - server, port, paths etc. maps the /public directory for static content, defines the paths to the ReST interfaces and the Cassandra query code. -- package.json contains the 'start script' element pointing to "./bin/www"
  • ./bin/www" - starts the http server
  • If an index.html file is in ./public then it will display that as the entry point e.g. http://localhost:3000
  • If not then it will use index.jade in /views and display the Express welcome message
  • ./public/chart.html - a simple d3 example chart and buttons to test the ReST interfaces for the two table queries
  • ./public/simplechart.html - a simple dashboard that displays time-series data from the custom table - from ideas at https://github.com/ESeufert/d3.js-dashboard-examples
  • ./public/multichart.html - a simple demo with multiple charts

Example Cassandra Nodejs code:

A simple example of using the Nodejs Cassandra connector:

var cassandra = require('cassandra-driver');
var client = new cassandra.Client({ contactPoints: ['localhost']});

client.execute('select key from system.local', function(err, result) {
  if (err) throw err;
  console.log(result.rows[0]);
});

Data we will pull from Cassandra

For the first ReST API we will use the system.compaction_history table:

system.compaction_history (
    id uuid PRIMARY KEY,
    bytes_in bigint,
    bytes_out bigint,
    columnfamily_name text,
    compacted_at timestamp,
    keyspace_name text,
    rows_merged map

This is the query:

select keyspace_name, columnfamily_name, compacted_at, bytes_in, bytes_out from system.compaction_history

The second table looks like this:

CREATE TABLE sparksensordata.sensordata (
    name text,
    time timestamp,
    value double,
    PRIMARY KEY ((name, time))
)

And we use this query:

select time, value from sparksensordata.sensordata

Test The ReST Interfaces

The rest interfaces are served from routes defined in app.js e.g.

app.get('/compaction', function(req, res) {
  var client = new cassandra.Client({ contactPoints: ['localhost'] , keyspace: 'system'});
  var queryString = 'select keyspace_name, columnfamily_name, compacted_at, bytes_in, bytes_out from system.compaction_history';
  client.execute(queryString, function(err, result) 
  {
    if (err) throw err;
    for (var item in result.rows) {
      console.log(result.rows[item]);
    }
    res.setHeader('Content-Type', 'application/json');
    jsonString=JSON.stringify(result.rows);
    console.log('JSON = ',jsonString);
    res.send(JSON.stringify(result.rows));
  });
});

Now we know where everything is and what we're looking for, let's test it. If the server isn't currently running, go to your project directory and run this command to start the node server:

DEBUG=chartdse:* npm start           

Compaction History

Test the system.compaction_history interface - json data is returned:

Sensor Data

Test the custom sparksensordata.sensordata interface - json data is returned:


Test The Chart Pages

These are HTML pages that call the ReST interfaces and contain scripts to build d3 charts to display the data. These are in ./public

Simple d3 Chart

This contains a simple demo to build a bar chart, plus links to the ReST interfaces for the two tables. There is also a button showing how to link to another static HTML page.

Time Series Data

This takes the sensor data in the sparksensordata.sensordata table and displays it in a time series line graph.

Installing d3js Locally

By default the d3 scripts are downloaded at runtime using a link at the top of the html page that will run your javascript (for example in simplechart.html) e.g.:

<script src="http://d3js.org/d3.v2.js"></script>

If you do not want to be dependent on an internet connection in order to run your code you can download d3 and use it locally.

Follow these steps:

Go to the d3 site at http://d3js.org Create a directory in your project directory (or centrally if you want to share between projects).

$ cd <my project directory>
$ mkdir d3

Download the entire d3 zip file from https://github.com/mbostock/d3/releases and unzip in to the d3 directory created above, or copy just the main d3 v3 js from here http://d3js.org/d3.v3.js to the d3 dir created above.

In your chart HTML file Replace

<script src="http://d3js.org/d3.v2.js"></script>

with

<script src="d3.v3.js"></script>

jquery

You can install jquery locally to remove the dependency on an internet connection.

$ npm install jqueryui
chartdse@0.0.0 /u02/dev/dse_dev/chartdse
└── jqueryui@1.11.1 
$ npm install jquery
chartdse@0.0.0 /u02/dev/dse_dev/chartdse
└── jquery@3.1.1 

In your chart HTML file: Replace

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

with

<script type="text/javascript" src="jquery.min.js"></script>

Replace

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>

with

<script type="text/javascript" src="jquery-ui.min.js"></script>

Copy files to static directory

Copy these files from their downloads into the public directory so that we can serve them locally:

$ cp node_modules/jquery/dist/jquery.min.js public
$ cp node_modules/jqueryui/jquery-ui.min.js public
$ cp d3/d3.v3.js public

Your HTML file header was like this:

<script src="http://d3js.org/d3.v2.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
Now like this:
<script src="d3.v3.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-ui.min.js"></script>

About

Example of using Node js and d3 to build a dashboard for data stored in Cassandra

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published