Lessons Learned from Creating a Custom Graph Visualization in React
By: Horst Werner
Tags: React, Graph, Splunk, Visualizations, Engineering

By Horst Werner and Simon Fishel

Graphs are probably the most powerful and versatile of all data structures. Graph structures are everywhere: in social media, genealogy, supply and distribution chains, financial networks, security, and business processes, to name just a few.

Visualizations of graphs, in the form of circles connected by lines, have been used for centuries (see e.g. The Great Stemma, the “Tree of Knowledge”, or any Mind Map). Computers have enabled us to automatically create such visualizations from data and layout algorithm research has been done for decades. Open source libraries such as d3.js provide generic graph visualizations that can be used and adapted with minimal effort. One could assume that by today there is a perfect layout strategy for pretty much every common use case and probably some open source library implementing it.

So open source libraries were our first stop when we set out to build Splunk Business Flow, an application that provides business operations professionals with insights into their actual end-to-end business processes and customer experiences through interactive exploration and visualization. Oftentimes, the actual (“as-is”) business processes of our customers differ from the ideal (“to-be”) processes they have defined, and surfacing such discrepancies, bottlenecks and delays creates tremendous value.

Fig. 1: Simple process graph generated with Cytoscape + Dagre layout

We evaluated vis.js, some d3.js solutions, and Cytoscape, a Canvas-based visualization library that allows you to select from multiple layout algorithms, and provides the option to implement your own. The Dagre layout algorithm appeared to be the most advanced, but the graphs it creates don’t look quite like a business process (Fig. 1). Other generic algorithms, such as the force-directed graph layout, don’t produce much better results either (Fig. 2).

Fig. 2: Force-directed layout

This is due to the fact that generic layout algorithms can’t take the meaning of a graph into account, so while they can optimize for certain geometric properties (such as keeping the edges as short as possible, or minimizing the intersection of edges), they can’t produce a visual pattern reflecting the meaning. This insight led us to the decision to write a custom layout algorithm to visualize business processes.

We use React to develop our UI; unfortunately, the graph libraries we evaluated don’t properly support the rendering paradigm of React (e.g. in Cytoscape, the graph component is a Canvas, which is updated in a way that completely bypasses React’s virtual DOM optimizations). So we also developed a new, React-based rendering module, with an abstraction layer that allows us to switch between multiple layout implementations. Here is what we learned in the process:

Map the Meaning of the Data to an Intuitive Visual Structure

In our specific case, we expect the graph to represent a process flow, which has a clear direction. We decided that a vertical downward flow would be the most intuitive representation of this direction. Of course, there are lots of branches and loops blurring that ideal straightforward structure. Therefore, one of our core challenges was making the structure of the main process visible through the noise. We started with the following rules:

Wherever the process is linear (i.e. each step has exactly one successor), that segment of the graph should appear as a strictly vertical structure in the graph.

Where processes are branching and looping, keep the most frequent process flows close to the center, to get as close as possible to a central main flow and peripheral variants.

Establish a clear sequence of steps, so that loops become visible in the form of backward-pointing edges.

Needless to say, while these rules make sense for process flows, the rules for other types of graphs will be completely different.

Fig. 3 shows two of our layout iterations using these rules.