Chapter 6. Advanced Integrations and Development

In this chapter, we will be discussing additional methods of integration and development. We will start with building a modular D3 visualization, which is an expansion of the D3 visualization from the last chapter. Using modular visualizations allows you to be more flexible with your dashboards and allows you to tweak a particular visualization for all dashboards in which it has been used. We will discuss modular inputs and how to create and test them. Modular inputs allow you to consume the same type of data in a modular fashion, similar to the native directory or file monitoring inputs found in Splunk. We will also cover the KV Store, how to use it, and why to use it. The KV Store allows you to store information in a key-value manner, which has the potential to speed up lookup tables, as the data is stored in the memory. We will also cover how to use Bower, npm, Gulp, and Git as tools for customizing and tracking our apps.

Modular D3 visualization

In this section, we will convert our previously used D3 box plot graph (we added this in Chapter 5, The Splunk Web Framework) into extended SimpleSplunkView. The benefits here are substantial. Primarily, you gain the ability to quickly reuse the view in other dashboards. Simply assign the SearchManager to the view and off you go. Retrieving the events from the SearchManager is also easier, as it is handled natively within the extension. Another great benefit is that when the view is loading, the default loading screens are used, so it's not just a blank panel until it is loaded; it is actually a first-class-citizen view. The first thing to have when creating an extended SimpleSplunkView is the base template.

Let's take a look at the basic structure and then fill in the pieces we are missing:

define(function(require, exports, module) {
    var _ = require("underscore");
    var mvc = require("splunkjs/mvc");
    var SimpleSplunkView = require("splunkjs/mvc/simplesplunkview");
    var D3BoxPlot = SimpleSplunkView.extend({
        className: "d3boxplot",
        options: {
            data: "preview"
        },
        createView: function() {
            return vis;
        },
        formatData: function(data) {
            return data;
        },
        updateView: function(vis, data) {
        }
    });
    return D3BoxPlot;
});

This is the basic template for SimpleSplunkView. It is written as a RequireJS module (remember RequireJS from Chapter 5, The Splunk Web Framework?), and you should notice that it references internal Splunk modules. RequireJS is a framework meant for loading JavaScript files and modules. A RequireJS module is written to be included in different parts of an application, allowing you to extend any RequireJS-compatible installation. You can find the documentation and some really awesome examples on their website at http://requirejs.org. The internal Splunk modules are underscore and any modules that start with splunkjs. These are already part of the stack, making it easier to import the modules. Once the additional modules are included, you call on the extend function of SimpleSplunkView. The configuration object you are passing includes some functions that are required for a simple Splunk view. "Where does this JavaScript go?" you might ask. Into appserver/static/js, of course! Let's call this file d3boxplotModule.js. There is another important thing to note here. Since we are using D3 as the visualization library, we have to include that library in the view class. Add the following code directly before the SimpleSplunkView require statement:

require('../app
/SDG/js/d3.min');

Note

Note that SDG here is actually the name of your App. The path is required in this instance because when the file is included in the dashboard, it will call it relative to the page, not the file.

Now give your view a class name relevant to the visualization being presented. Keep it simple; it doesn't have to be a book! Following that is the options configuration. This doesn't have to contain anything, but if it does, you can use these values as defaults within the view. For example, if you want a base height and width, you can define it here. If a new value is passed via the JavaScript instantiation, then your default will be overwritten. Let's now move to the formatData function. This function will take the results being passed in from the assigned SearchManager, format the data into the structure required by the box plot, and return it. Here is what our formatData function will look like:

formatData: function(data) { 
                var d3_data = []; 
                var index = 0; 
                _.each(data, function(Rcolumn, RrowCount) { 
                        Rcolumn.shift(); 
                        _.each(Rcolumn, function(DColumn, DrowCount) { 
                          d3_data.push( [index, DColumn ]); }); 
                          index++; 
                        }); 
                var mydata = []; 
                var min = Infinity, 
                    max = -Infinity; 

                d3_data.forEach(function(x) { 
                    var e = Math.floor(x[0]), 
                        s = Math.floor(x[1]), 
                        d = mydata[e]; 
                    if (!d) d = mydata[e] = [s]; 
                    else d.push(s); 
                    if (s > max) max = s; 
                    if (s < min) min = s; 
                  }); 
            return data; 
        }

This is essentially the same function we used previously in the configuration of the box plot in Chapter 5, The Splunk Web Framework. The only major changes were some naming conventions for the data arrays, just to keep inline with the standard module definitions. This function is what does the heavy lifting for the boxPlot chart data. Now that we've had the data formatted properly, let's take a look at the createView function:

createView: function() { 
                var iqr = function(k) { 
                        return function(d, i) { 
                        var q1 = d.quartiles[0], 
                            q3 = d.quartiles[2], 
                            iqr = (q3 - q1) * k, 
                            i = -1, 
                            j = d.length; 
                            while (d[++i] < q1 - iqr); 
                            while (d[--j] > q3 + iqr); 
                            return [i, j]; 
                 }}; 
                var margin = {top: 10, right: 50, bottom: 20, left: 50}, 
                    width = 130 - margin.left - margin.right, 
                    height = 500 - margin.top - margin.bottom; 
                var chart = d3.box() 
                    .whiskers(iqr(1.5)) 
                    .width(width) 
                    .height(height); 
            return { "chart": chart, "width":width,"height ":height, "margin":margin }; 
        }

Again, this looks pretty similar to the code we had earlier for the box plot in Chapter 5, The Splunk Web Framework, but with some slight changes. The iqr function is now a variable placed inline so that it can be easily referenced for the whiskers of the box plot. This function can be called globally, but since it is limited in scope for us in this view, we just set it as local. The other change from the normal function of this function is the return object. The chart is returned as an object within an object, which allows easy expansion to other variables as needed on the fly, as the only objects given to the updateView function are those returned from this function (createView) and the formatData function.

Speaking of the updateView function, let's take a peek in there:

updateView: function(chartObj, data) { 
                var width = chartObj.width, 
                    height = chartObj.height, 
                    margin = chartObj.margin, 
                    chart = chartObj.chart; 

                console.log("update view"); 
                d3.select(this.el).selectAll("svg") 
                      .data(data) 
                      .enter().append("svg") 
                      .attr("class", "box") 
                      .attr("width", width + margin.left + margin.right) 
                      .attr("height", height + margin.bottom + margin.top) 
                      .append("g") 
                      .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
                      .call(chart); 
        } 

Yet again, this is basically the same D3 code as we had previously in Chapter 5, The Splunk Web Framework, with minor tweaks for modularity. The biggest change is the d3.select call is that it now references this.el, which was passed in from the instantiation. This is the element that will contain the chart. So, with that change, we can now instantiate multiple box charts in the same dashboard. How? Here's how:

var salesBoxPlotResults = new boxPlot({
                 el: $('#boxPlotElement'),
                 id: "salesBoxPlotResults",  
                 managerid: "salesBoxPlotSearch"
               }).render();

That's it. Now that we've modularized the box plot, as shown in the following diagram, we simply call it using new boxPlot (which is the name of our variable after we include the module in RequireJS). Pass in the parameters required and render the visualization.

So simple! It keeps your dashboards clean and easy to read. How does it look? You tell me.

Modular D3 visualization

As you can see, it looks identical to what we created in the last chapter, but with the advantage of being plug and play. Keep in mind that this is a simple demonstration of how to create a custom view; these can be as simple or as complex as you like. This is far from customizable in terms of coloring, labels, legends, axes, and formatting. Each of these options can be included in the custom view and taken as far as you are able to take them.

However, what about SimpleXML, you ask? It's a very valid question. Including custom visualizations into SimpleXML dashboards can be very easy, depending on how you choose to implement the code. Splunk's approach uses the autodiscover.js methodology; you can learn more about their method from https://dev.splunk.com. However, what happens if I want to change the App name? Using the autodiscover.js approach will break all the defined dashboards. So, let's add a few things to the dashboard.js file in appserver/static. Let's start with a configuration for RequireJS:

var APPNAME = "SDG";
require.config({
  paths: {
    "boxplot": "../app/"+APPNAME+"/js/d3boxPlot",
    "d3": "../app/"+APPNAME+"/js/d3.min"
  },
  shim: {
    "d3":{exports:"d3"},
    "boxplot" : { deps: ["d3"]}
  }
});

The preceding code starts up by creating some configurations needed to point to the correct location. With a simple change of the APPNAME variable, all references to the App's name will change, and all the custom visualizations using this method in the dashboards will work again. Simple! Now for some magic!

require([    "splunkjs/ready!",    "splunkjs/mvc/simplexml/ready!",    "jquery",    "underscore",    "boxplot"], 
function(    mvc,    ignored,    $,    _,    boxPlot) {
    $(".boxPlot").each(function(index){
        el = $(this);
        data = el.data();
        data["el"] = el;
        new boxPlot(data).render();
    });
});

This section of code does a very simple thing. It uses jQuery to find each element with the specific class boxPlot. For each such element that is found, we will use the data() function of each element to pull the required configuration settings. Let's look at an example of the HTML element to use to support this instantiation method. The really important part is the HTML div, and it can be used in either the SimpleXML or the HTML dashboard:

<panel>
    <html>
       <div class="boxPlot" data-managerid="mySearch"></div>
    </html>
</panel>

The data-managerid attribute will be parsed to the item of managerid. This makes it clean and easy to read. For each option that is required for the visualization (and that you'd normally include in a messy JSON option in the data-require attribute), you place it into a data-<option> format. That's it! Now you can define the visualization once and allow your App developers to use a simple div class and some options without having to build a JSON object to build the dashboard.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.186.6