Skip to main content
Blog

Controlling a Kibana dashboard with a custom form

By 22 september 2014januari 30th, 2017No Comments

At First8 we wanted to see if Kibana dashboards could be used to assist customer support. Currently our target customer support uses a number of a grep commands to analyse the logs, but they are not trained unix administrators and only work through a short list of commands. We were looking for a solution that would allow customer support to query log files of different services and analyse them in a graphical way.

Kibana natively supports many elements to view log files, however the build-in query capabilities were deemed too complicated for our target users. Thus we investigated how we could generate queries from a form and show those in the dashboard.

The log documents we use have been enhanced using a custom Logstash plug-in, such that we have special fields to (incompletely) capture user ids. Customer support has to be able to search for those special fields and drill up and down to find out what happened with the customer. Drilling down would mean selecting a timespan, region (ip-based), involved customer id or involved merchant id. Drilling up would be selecting all logs in or around the timespan of a filtered selection.

We will use forms to enter user input, client side javascript to convert that input into a special url and a dashboard to capture the parameters from that url and create the queries accordingly.

Design Choices

We had to choose how we integrated with Kibana, which boiled down to 2 options:

  1. We could edit the index.html that comes with Kibana
  2. We could make an external file and load Kibana’s index.html in an iframe.

In order to avoid issues associated with javascript and iframes we decided not to use iframes. For our proof of concept we chose to edit the index.html which comes with Kibana. This means we reload the entire page upon form submit.

Kibana dashboards come in 2 flavors, a templated (configured in json) dashboard and a so called scripted dashboard. The latter category is a javascript file that returns a object representing a dashboard. http://www.elasticsearch.org/guide/en/kibana/current/templated-and-scripted-dashboards.html We choose not to use scripted dashboard, because the json templated dashboards seemed easier to make (remember this is a proof of concept) and the mustache notation should provide the dynamics we need. http://mustache.github.io/mustache.5.html https://github.com/elasticsearch/kibana/issues/448#issuecomment-23756785

Technical issues

Require.js
Since Kibana uses jquery itself, we decided to use jquery to set events and query the DOM. Kibana uses require.js as a dependency resolver framework. Require.js loads dependencies asynchronously (see Snippet 1). That means that to use jquery (i.e. to execute our code after jquery has been loaded) we have to put our jquery dependent code in a callback supplied as argument to the require function.

require(['app'], function () {});

Snippet 1 – from a standard kibana index.html, callback is empty now

This provides us with a way to write javascript using jquery.

Limited Mustache support
After creating a dashboard document and testing some urls, it became apparent that Mustache was not fully implemented in Kibana, only a very simple form of variable tags with default values are supported: {{ some.arg || “*” }}.

At this point we could either switch from a templated dashboards to scripted dashboards, or put slightly more logic in the url generation. To meet our time constraints we chose the latter option. The url now contains not just queries, but also which queries should be enabled. This way the dashboard did not have to compute anything, it just takes its variables directly from the url, see Snippet 2.

"query": {
	     "list": {
	        …
	        "3": {
	          ...
	          "query": "@timestamp:[{{ARGS.minTimeStamp || '0'}} TO {{ARGS.maxTimeStamp || '0'}}]"
	        }
	      },
	      "ids": [
	        {{ARGS.queries || '0'}}
	      ]
	    },

Snippet 2 – from json dashboard document

Kibana urls
The url format Kibana uses starts with a hash sign after the actual file path and has the question mark only after specifying the dashboard: index.html#some/dashboard?paramKey=paramValue. This means that changing parameters does not change the location according to browsers. And we have to tell the browser to reload the page after updating window.location.

For now we are using window.location.reload(true), which tells the browser to clear the cache and reload all components. For our proof of concept this should be good enough, for a production version it would be much nicer to only reload the components that need reloading. This will enable a much smoother user experience.

Querying the dashboard
As a ‘drill up’ option we wanted to select all log documents that are within the timespan of the log documents currently selected. This would help customer support get a more complete picture when required. We implemented this by including a min and max time stamp in our dashboard and then use jquery to retrieve this information from the DOM. In theory we could also have queried the Elasticsearch server directly via javascript.

User friendliness

Persisting input fields
Because we are hiding the actual queries from the user we need to make sure the information the user has typed in the input fields is persisted over multiple requests. Since we are already parsing the url to make sure we can merge parameters, this is only a small extra step implemented by the code in snippet 3.

var input = ['shopperId', 'merchantId'];
	var query = queryFromUrl();

	for (var i = 0; i < input.length; i++) {
		key = input[i];
		if (query[key])	$('#' + key).val(query[key].split(':')[1]);
	}

Snippet 3 – putting back values from the url into the input boxes

The javascript in Snippet 3 assumes the following things:

  • An input element with an id attribute corresponding to the url parameter key it represents.
  • Input value is stored after “field:”.
  • Strings contained in the input variable are such fields.

Styling

Styling our proof of concept was very easy. Kibana uses bootstrap css throughout the interface and using bootstrap to style forms and form elements is very straightforward and immediately looks reasonably integrated.

Final result

Recap
We made an HTML form and javascript to control an url, we made a dashboard to extract information from that url, such that a customer support worker can input known information and view logfiles, and view matching log lines.
1st8psp3 Usage
In this form customer support can filter logs by a ‘shopper id’ and by a ‘merchant id’. When too little log documents show up, customer support can ‘drill up’ by pressing ‘Select all within time frame’. This results in all log files in the time frame of the current result.