Share live dashboards with external users

This tutorial describes how to construct a live dashboard to share with an external user who may not have login access to your Traffic Sentinel installation. Before proceeding with this tutorial it is worth studying the Scripting Queries tutorial since it introduces the scripting capabilities of Traffic Sentinel and the REST API Builder tutorial since that interface is used by this mechanism.

Note: This tutorial describes a feature that was added in Traffic Sentinel 7.2.29. If you are running an older version of Traffic Sentinel you will need to upgrade before you can use this.

Overview

Each dashboard takes the form of a REST-API query script added to:

/usr/local/inmsf/queries
or submitted via the File>REST page. The structured comments at the top of the script work the same way as for any REST-API script, so that is where you can set the custom access control for the dashboard, and configure the ttl setting to ensure that multiple viewers will not trigger multiple queries on the server side.

Within the script, you create an instance of Dash, and add instances of DashCell to it. Each DashCell is given a list of DashKey and DashValue instances, along with a number of other settings controlling the query and the presentation. Finally, a call to dash.run() executes the dashboard.

Generating a dashboard from a script is powerful because it is common for dashboard cells to share some characteristics, such as a filter, keys, or threshold. The result can be a surprisingly short script that is easy to maintain and resuse.

Classes

  • DashKey
  • DashValue
  • DashCell
  • Dash

Example

Below is a simple example of a REST API dashboard script:

// author: Neil McKee
// date: 8/1/2015
// version: 1.0
// description: Dashboard1
// inputs: action,update,interval,debug
// resultFormat: html
// ttl: 60

var action = action || "dash";
var update = update || "no";
var interval = interval || "";
var debug = debug || 0;
debug = parseInt(debug);

include("dashboard-1.0.js");

var dash = new Dash("Dash Class Example", 2, "500px", "300px");
var bps = new DashVal("Bits/sec", "rate(bytes)", 8);
var srcaddr = new DashKey("Source Addr", "sourceaddress", dash.format_dns_name);
var dstaddr = new DashKey("Dest Addr", "destinationaddress",
                          dash.format_dns_name);

if(interval) {
  dash.common.setInterval(interval);
  dash.setRefreshTimeout(0);
}

var cell1 = new DashCell("rttraffic", [ srcaddr ], [ bps ],
			 "sourcezone = EXTERNAL");
dash.addCell(cell1);
var cell2 = cell1.clone();
cell2.setKeys([ dstaddr ]);
cell2.setFilter("destinationzone = EXTERNAL");
dash.addCell(cell2);
dash.run(action, update, debug);

Library details with usage examples

dashkey = new DashKey(name, field [, format_function ])
  k_agent = new DashKey("Switch/Router",
			agent,
			dash.format_agent_name);
dashval = new DashValue(units, field [, scale, format, color ])
  v_temp = new DashValue("Temp.",
			 temperature,
			 1,
			 "0.0",
			 "yellow");
dashcell = new DashCell(view, keys, values, filter)
  var dctemp = new DashCell("ifcounters",
			    [ k_agent ],
			    [ v_temp ],
			    "zone=DC");
  dash.addCell(dctemp);
Any unspecificed settings are copied from dash.common, an instance of DashCell that can be modified at any time.
dashcell2 = dashcell.clone()
  var temp2 = dctemp.clone();
  temp2.setFilter("zone!=DC");
  dash.addCell(temp2);
title = dashcell.getTitle()
dashcell.setTitle(title)
Title will be auto-generated if not set.
view = dashcell.getView()
dashcell.setView(view)
The database view (e.g. "rttraffic", "ifcounters", "host", "events").
keys = dashcell.getKeys()
dashcell.setKeys(keys)
Trst of DashKey objects.
values = dashcell.getValues()
dashcell.setValues(values)
Trst of DashValue objects. The last value will be adopted as the sort value. For charts cells only the sort value will be used, while table cells will display them all.
filter = dashcell.getFilter()
dashcell.setFilter(filter)
    cell1.setFilter("sourcezone=EXTERNAL");
minutes = dashcell.getMinutes()
dashcell.setMinutes(minutes)
This setting controls the query interval start, counting back from now.
interval = dashcell.getInterval()
dashcell.setInterval(interval)
Override query interval. Dashboard does not track/refresh when this is done.
group = dashcell.getGroup()
dashcell.setGroup(group)
Time grouping minutes for trend charts. Defaults to 1.
n = dashcell.getN()
dashcell.setN(n)
Number of legend keys or table rows.
bool = dashcell.getGlobalTruncate()
dashcell.setGlobalTruncate(bool)
Compute top-keys over whole interval, rather than separately for each group. With setGlobalTrucate(false) the legend keys and colors are chosen when a group is ctrcked on (as for the Traffic>TopN page) and incremental updates are enabled.
bool = dashcell.getIncludeOther()
dashcell.setIncludeOther(bool)
Include an extra category for keys not in top N.
bool = dashcell.getNullsInKeys()
dashcell.setNullsInKeys(bool)
Allow some keys to be missing.
bool = dashcell.getStack()
dashcell.setStack(bool)
Turn line chart into stacked-line chart.
val = dashcell.getThreshold()
dashcell.setThreshold(val)
Draw visual cue if threshold value is included on value axis of chart, or if value is above threshold in table output.
bool = dashcell.getTable()
dashcell.setTable(bool)
Select chart trend or table output. When the output is a table the group setting is ignored and the result is aggregeted over the whole interval of the query.
dashcell.setImageURL(url,resize) Insert an image into the dashboard cell. If the image changes it will be refreshed automatically. If resize is true then the URL will be given height and width parameters.
dash = new Dash(title, ncols, width, height)
   dash = new Dash("Data Center Dashboard A",
		   3, "700px", "150px");
dash.addCell(dashcell) Add cell to dashboard. Layout will depend on number of columns set when Dash created.
dash.run(action,update,debug) Run dashboard. See examples for use of action, update and debug parameters.

Example Operations Dashboard

Below is a more detailed example, which includes traffic, errors/discards and host-performance charts. A zone filter can be passed in as a URL parameter, so this script can serve a dashboard for every zone.

// author: Neil
// date: 2/1/2015
// version: 1.0
// description: Demo Dashboard 1
// inputs: action,update,interval,debug,zone
// resultFormat: html
// ttl: 60

// How to use this script.
// 1. Add authentication restrictions above (see REST API tutorial for examples).
// 2. Edit the Dashboard construction below.
// 3. Access the URL.  The dashboard should appear.  If not, try
//    troubleshooting steps:
//    (a) try ?action=spec - should dump the spec.
//    (b) try ?action=data  - this will query for the data.
//    (c) try ?action=data&update=true  - just the last 10 minutes of data.
//    (d) try ?action=data&debug=1 - results include "jobs" and debug "log"

// To find out what fields are accessible for each view below, see:
// Help > Top > Report > Script > 
// view=rttraffic fields :  /inmsf/help/en/report/api_view_rttraffic.shtml
// view=ifcounters fields :  /inmsf/help/en/report/api_view_ifcounters.shtml
// view=host fields :  /inmsf/help/en/report/api_view_host.shtml
// and so on.

var action = action || "dash";
var update = update || "no";
var interval = interval || "";
var debug = debug || 0;
var zone = zone || null;

debug = parseInt(debug);

include("dashboard-1.0.js");

var title = "Operations Dashboard 1";
if (zone) title += " for zone: " + zone;
var dash = new Dash(title, 3, "700px", "150px");

// values from view="rttraffic" or "rtfanout"
var bps = new DashVal("Bits/sec", "rate(bytes)", 8);
var fps = new DashVal("Packets Per Second", "rate(frames)");
var fanout = new DashVal("No. DestinationSAPs", "count(destinationsap)");

// values from view="ifcounters"
var c_bps = new DashVal("Bits/sec", "rate(ifinoctets)", 8);
var c_util = new DashVal("utilization %", "rate(inoututilsecs)");

var c_in_errors =  new DashVal("Errors In","ifinerrors");
var c_out_errors =  new DashVal("Errors Out","ifouterrors");
var c_sum_errors = new DashVal("Errors","sum(ifinerrors ifouterrors)");

var c_in_discards =  new DashVal("Discards In","ifindiscards");
var c_out_discards =  new DashVal("Discards Out","ifoutdiscards");
var c_sum_discards = new DashVal("Discards","sum(ifindiscards ifoutdiscards)");

var c_sym_errors = new DashVal("Sym Errors","symbolerrors", 1, "##.##");
var c_fcs_errors = new DashVal("FCS Errors","fcserrors", 1, "##.##");
var c_aln_errors = new DashVal("Align Errors","alignmenterrors", 1, "##.##");
var c_detail_errors = new DashVal("Errors",
				  "sum(symbolerrors fcserrors alignmenterrors)",
				  1, "##.##");

// env values -- also from view="ifcounters"
var temp = new DashVal("temp (C)","temperature", 1, "##.00");
var power = new DashVal("W","power", 1, "#");
var psus = new DashVal("PSUs","psus", 1, "#");
var psus_failed = new DashVal("PSUs Failed","psus_failed", 1, "#");
var fans = new DashVal("FANs","fans", 1, "#");
var fans_failed = new DashVal("FANs Failed","fans_failed", 1, "#");

// values from view="host"
var loadavg = new DashVal("Load Avg (1 min)","load_one", 1, "0.0");
var loadpercpu = new DashVal("Load/CPU (1 min)","loadpercpu_one", 1, "0.0");
var memutil = new DashVal("Memory %","mem_used_pc", 1, "0.0");
var read_time = new DashVal("I/O Read Time (mS)","read_time_mean", 1, "0.00");

// keys from view ="rttraffic" or "rtfanout"
var srcaddr = new DashKey("Source Addr", "sourceaddress",
			  dash.format_dns_name);
var dstaddr = new DashKey("Dest Addr", "destinationaddress",
			  dash.format_dns_name);
var service = new DashKey("Service", "serverport",
			  dash.format_protocol);

// keys that appear in most views
var agent = new DashKey("Agent", "agent",
			dash.format_agent_name);
var intf = new DashKey("I/F", "interface",
		       dash.format_interface_str);

// keys from view="host"
var host = new DashKey("host", "hostname",
		       dash.format_host);

function buildFilter(flt) {
    if(zone == null) return flt;
    if(flt) return "(zone=" + zone + ")&(" + flt + ")";
    else return "zone=" + zone;
}

dash.common.setGlobalTruncate(false);
dash.common.setIncludeOther(false);
dash.common.setNullsInKeys(false);
dash.common.setMinutes(30);

if(interval) {
    dash.common.setInterval(interval);
    dash.setRefreshTimeout(0);
}

// row 1 - sources, dests, flows
var sources = new DashCell("rttraffic", [ srcaddr ], [ bps ], buildFilter(""));
sources.setTitle("Top Sources");
dash.addCell(sources);

var dests = sources.clone();
dests.setKeys([ dstaddr ]);
dests.setTitle("Top Destinations");
dash.addCell(dests);

var flows = sources.clone();
flows.setKeys([ srcaddr, dstaddr, service ]);
flows.setTitle("Top Flows");
dash.addCell(flows);

// row 2 - services, multicasts, broadcasts
var services = sources.clone();
services.setKeys([ service ]);
services.setTitle("Top Protocols");
dash.addCell(services);

var mcasts = dests.clone();
mcasts.setFilter(buildFilter("ismulticast=1"));
mcasts.setTitle("Top Multicast Groups");
dash.addCell(mcasts);

var bcasts = sources.clone();
bcasts.setValues([ fps ]);
bcasts.setFilter(buildFilter("isbroadcast=1"));
bcasts.setTitle("Top Broadcasts");
dash.addCell(bcasts);

// switch the default to line charts
dash.common.setStack(false);

// row 3 - interface counters
var errors = new DashCell("ifcounters",
			  [ intf ],
			  [ c_sym_errors,
			    c_fcs_errors,
			    c_aln_errors,
			    c_detail_errors ],
			  buildFilter(""));
errors.setThreshold(1);
// make this one a table so we can see all the values
errors.setTable(true);
errors.setTitle("Errors Breakdown");
dash.addCell(errors);

var discards = new DashCell("ifcounters",
			    [ intf ],
			    [ c_in_discards,
			      c_out_discards,
			      c_sum_discards ],
			    buildFilter(""));
discards.setThreshold(100);
discards.setTitle("In/Out Discards");
dash.addCell(discards);

dash.addCell( new DashCell("ifcounters",
			   [ agent ],
			   [ temp ],
			   buildFilter("")));

// row 4 - host performance
var lpcpu =  new DashCell("host",
			  [ host ],
			  [ loadpercpu ],
			  buildFilter(""));
lpcpu.setThreshold(1);
dash.addCell(lpcpu);

var mem = lpcpu.clone();
mem.setValues([ memutil ]);
mem.setThreshold(95);
dash.addCell(mem);

var rtime = lpcpu.clone();
rtime.setValues([ read_time ]);
rtime.setThreshold(50);
dash.addCell(rtime);

// run the dashboard
dash.run(action, update, debug);

Related Topics