DevOps Within

Stories from a man against the machines.

Visualising the network: First Encounter

This is the first article from the small series about visualising the data in my application. There will be at least three more just on that topic, so let me know if there is something if you were particularly interested in.

I'll believe it when I see it

After fixing the network issues which caused a little mess in the connections, now I can track all 119 expected devices (and some more unexpected guests). This is an amount of nodes which isn't easy to imagine on a piece of paper. There are about 360 connections between those nodes, too!

This made me think about visualising the data sooner than I have planned, but hopefully, it will allow understanding of the context for i-must-go better. Here's first entry about visualising the gathered data using JavaScript.

Ewww, JavaScript!

I believe we're not in the times of people being so afraid of javascript that they completely disable it on their browsers anymore. Since my application is meant to have a web interface for viewing and analysing the data as well as the backend for network crawling and analysing, I'll try to use web technologies to visualise the gathered data.

I've got 99 problems, but the lack of libs ain't one

There is an abundance of visualisation libraries for JavaScript, depending on what you need. d3.js seems to be the most basic (as in used as a base building block) for most of the others. While it sure is powerful, I do not want to implement my own graph drawing procedures just for the sake of it.

During the research phase, I have found a site which compares many libraries which are readily available to use. From those, I have decided to take a look at two: sigma.js and Alchemy. Both support reading JSON-encoded data, which is an easy way to transfer the data between components of the application.

Alchemy or sigma.js

At first, I looked at sigma.js and thought that it is too 'raw' for me, so I tried to use Alchemy instead - it seemed to be easy to use, yet powerful. Examples were anywhere from basic to advanced, I was almost convinced that it's the best I can have. And then I realised that I shouldn't trust a library with version 0.4.1 unless I have no other choice. I couldn't use the basic CDNs for the library, and the downloaded build didn't seem to work properly for me. That's a shame because I found Alchemy to be really user-friendly...

...a little unlike sigma.js, to which I have turned afterwards. I don't know if that's common for JS libraries, but the structure of sigma's documentation is really confusing for me. Apart from a landing page, there is a lot of hard, technical info on GitHub wiki, lots of knowledge and examples in the issues, but all of these things were for naught until I have found this gem of a blog post! Maybe I'm not the brightest programmer out there, but in my opinion, this is how a tutorial for a library should look like. A clear goal and a step-by-step solution saved me a lot of time. seal of approval

Show me your visuals, your visuals

Ok, so by connecting the dots from the bloggers, docs and my set of data generated from i-must-go, I have created a sample visualisation without too much tuning for the looks. You can see it here and it's using the following dataset generated by the application. You can zoom in and out using the mouse wheel and drag to pan the view in the demo.

The most important part of it is contained in a single <script> block:

  sigma.parsers.json('vis1-data.json', { // This part loads the data from JSON using XHR
    container: 'container',
    settings: {
      defaultNodeColor: '#1A2648',
      defaultLabelSize: 12,
      edgeColor: "#337ab7"
    }
  },

  // Now a callback for the XHR
  function(s) { //This function is passed an instance of Sigma s

    // Initialize nodes as a circle - we have to start somewhere, right?
    s.graph.nodes().forEach(function(node, i, a) {
      node.x = Math.cos(Math.PI * 2 * i / a.length);
      node.y = Math.sin(Math.PI * 2 * i / a.length);
      node.size = 0.5;
    });

    // Call refresh to render the new graph
    s.refresh();

    // Now use some force to relocate the nodes
    s.startForceAtlas2();
  });

Using the code above, I load the dataset and set some basic configuration and then relocate the nodes twice. The first time, I place them around a circle just to have them spread out somehow. The call to s.refresh() is very important, because it updates the graph on the canvas so that it can be forcefully rearranged later using s.startForceAtlas2().

This is just a basic example. The final application will have a much cleaner look.

In the next article, I will talk about serialising objects in golang using JSON. Stay tuned!