Description

Even though Splunk has advanced charting and visualization capabilities, sometimes you might want to use third-party tools to display your data. For example, you might set up a website with Google Charts.

This example performs a simple Splunk search (using exec_mode=oneshot for simplicity), and presents the results using Google Charts. The result format that Splunk provides is very similar to what Google Charts expects. So, with just a little data massaging, you can have a chart up and running in no time.

Code

var http = new splunkjs.ProxyHttp("/proxy");
service = new splunkjs.Service(http, { 
  scheme: scheme,
  host: host,
  port: port,
  username: username,
  password: password,
  version: version
});

var drawChart = function(rows) {  
  var chart = new google.visualization.ComboChart(document.getElementById('google-container'));
  var data = google.visualization.arrayToDataTable(rows);
  
  var options = {
    title : 'HTTP Status Codes For Every 10 Minutes on Splunkd',
    vAxis: {title: "Count", logScale: true},
    hAxis: {title: "Time"},
    seriesType: "bars",
    isStacked: false
  };
  
  chart.draw(data, options);
};

// First, we log in
service.login(function(err, success) {
  // We check for both errors in the connection as well
  // as if the login itself failed.
  if (err || !success) {
      console.log("Error in logging in");
      done(err || "Login failed");
      return;
  }
    
  // OK, we're logged in, let's do a oneshot search and just
  // get the results
  var query = "" +
    'search index=_internal sourcetype=splunkd* | head 10000 | bucket span=10m _time | eval formatted_time=strftime(_time, "%D %H:%M") | chart count over formatted_time by status usenull=f';
  service.oneshotSearch(query, {}, function(err, results) {
    if (err) {
      console.log(err);
      alert("An error occurred with the search");
      return;
    }
  
    // The format Google Charts needs data in is very similar to ours - we just
    // need to put the field headers in the same array, and convert the strings
    // into numbers.
    var rows = results.rows.slice();
    var fields = results.fields.slice();
    
    var timeIndex = utils.indexOf(fields, "formatted_time");
    for(var i = 0; i < rows.length; i++) {
      var row = rows[i];
      for(var j = 0; j < row.length; j++) {
        
        // Don't change the time field
        if (j !== timeIndex) {
          row[j] = parseInt(row[j]);
        }
      }
    }
    
    // Add the headers in
    rows.unshift(results.fields);
    
    drawChart(rows);
  }); 
});
            

Description

Rickshaw is a time-series visualization library built by the excellent folks over at Shutterstock. This library is built on the immensely powerful d3 library, and exposes a lot of the raw power of d3 in a user-friendly way.

Much like the Google Charts example, this example shows how to create a simple line graph from a Splunk search. This graph shows the HTTP status codes broken down by minute, as observed by splunkd.

This might look like a lot of code, but most of it is for setting up the Rickshaw graph—so have no fear!

Note: This example doesn't work in Internet Explorer 9 or earlier, due to browser limitations.

Code

var http = new splunkjs.ProxyHttp("/proxy");
service = new splunkjs.Service(http, { 
  scheme: scheme,
  host: host,
  port: port,
  username: username,
  password: password,
  version: version
});

var palette = new Rickshaw.Color.Palette( { scheme: 'httpStatus' } );

var transformData = function(d) {
  var data = [];
  var statusCounts = {};

  Rickshaw.keys(d).sort().forEach( function(t) {
    Rickshaw.keys(d[t]).forEach( function(status) {
      statusCounts[status] = statusCounts[status] || [];
      statusCounts[status].push( { x: parseFloat(t), y: d[t][status] } );
    } );
  } );

  Rickshaw.keys(statusCounts).sort().forEach( function(status) {
    data.push( {
      name: status,
      data: statusCounts[status],
      color: palette.color(status)
    } );
  } );

  Rickshaw.Series.zeroFill(data);
  return data;
};

var drawChart = function(rows, fields) {  
  
  var data = {};
  
  var timeIndex = utils.indexOf(fields, "formatted_time");    
  for(var i = 0; i < rows.length; i++) {
    var row = rows[i];
    var timeValue = parseInt(row[timeIndex]);
    data[timeValue] = {};
    for(var j = 0; j < row.length; j++) {
      if (j !== timeIndex) {
        data[timeValue][fields[j]] = row[j];
      }
    }
  }

  var transformed = transformData(data);

  // Setup the graph
  var graph = new Rickshaw.Graph( {
    element: document.getElementById("rickshaw-chart"),
    series: transformed,
    renderer: 'line',
    width: 550
  });
  
  var y_ticks = new Rickshaw.Graph.Axis.Y({
    graph: graph,
    orientation: 'left',
    tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
    element: document.getElementById('y_axis')
  });
  
  // Render the graph
  graph.render();

  var hoverDetail = new Rickshaw.Graph.HoverDetail( {
    graph: graph
  });

  var legend = new Rickshaw.Graph.Legend( {
    graph: graph,
    element: document.getElementById('rickshaw-legend')

  });

  var shelving = new Rickshaw.Graph.Behavior.Series.Toggle( {
    graph: graph,
    legend: legend
  });
  
  var axes = new Rickshaw.Graph.Axis.Time({
    graph: graph
  });
  axes.render();
};

// First, we log in
service.login(function(err, success) {
  // We check for both errors in the connection as well
  // as if the login itself failed.
  if (err || !success) {
      console.log("Error in logging in");
      done(err || "Login failed");
      return;
  }
    
  // OK, we're logged in, let's do a oneshot search and just
  // get the results
  var query = "" +
    'search index=_internal sourcetype=splunkd* | head 10000 ' + 
    '| timechart span=1m count by status | eval formatted_time=_time' +
    '| fields - NULL, _*, _time';
  service.oneshotSearch(query, {count: 0}, function(err, results) {
    if (err) {
      console.log(err);
      alert("An error occurred with the search");
      return;
    }
  
    var rows = results.rows.slice();
    var fields = results.fields.slice();
    
    var timeIndex = utils.indexOf(fields, "formatted_time");
    for(var i = 0; i < rows.length; i++) {
      var row = rows[i];
      for(var j = 0; j < row.length; j++) {
        
        // Don't change the time field
        if (j !== timeIndex && fields[j] !== "_time") {
          row[j] = parseInt(row[j]);
        }
      }
    }
    
    drawChart(rows, fields);
  });
});