Building a CRUD Dashboard Utilizing a KV Store in Splunk: Part 1

This blog-screencast series will cover how to CRUD (create / read / update / delete) a KV Store collection in Splunk. By the end you'll be a KV Store master!



Introduction

This blog-screencast series will cover how to CRUD (create / read / update / delete) a KV Store collection in Splunk.

KV Stores are Mongo databases in Splunk. Learning how to CRUD data in a KV Store will help you to better understand how KV Store collections work. Following along in this tutorial will take you from KV Store novice to expert. We will also build a custom Splunk dashboard that will help to reinforce the concepts around CRUDing KV Store data. Our dashboard will be a sample project list that will provide information such as the project name, due date, and status (e.g. completed or on-hold).

Hopefully you'll follow along and by the end you'll be an unstoppable KV Store master.

Note: As with my other blog-screencast tutorials, feel free to follow along with the videos as well as the details included in the associated blog posts.

Quick Review

In the blog series ‘The Basics of Creating and CRUDing a KV Store in Splunk’, we covered how we can create and KV stores through config files, as well as through the Splunk UI (user interface). We also covered how to apply CRUD (Create / Read / Update / Delete) to our KV Store using the Splunk Query Language. If you’re starting from scratch, I recommend you start there -- especially if you're new to KV Stores.

Part 1

In this new series, we'll take those ideas we learned and apply them to a dashboard where users can easily create, update, and delete data, from a KV store through a custom web form.

Reading the Dashboard

Let’s use this as the base of the search in our dashboard (the Read portion):

| inputlookup task_lookup

Run the search in the search window. Then click on ‘Save As’ < ‘Dashboard Panel’. Then fill out all the appropriate information, click ‘Save’, and then ‘View Dashboard’.

Editing Our Dashboard

Click ‘Edit’ < ‘Edit Panels’. Then click the magnifying glass icon on the search panel and ‘Edit Search String’. Change your search so it looks like this:

| inputlookup task_lookup | eval Update="Update" | eval Delete="Delete" 
| table *, Update, Delete

Your table should now look like this:

Now, we’re going to add a form to our dashboard. Click ‘Edit’ < ‘Edit Source’.

First, add a reference to a new css file in the top: <dashboard stylesheet="crud_style.css"> (We haven’t created this yet but we will shortly).

After this, find the first <panel></panel> and below the closing </panel> tag add the following:

    <panel id="taskFormPanel">
      <html>
        <form>
          <div>
          	<label for="Estimated_Completion_Date">Estimated Completion Date</label>
          	<input style="width: 95%" type="text" name="Estimated_Completion_Date"/>
          </div>
          <div>
          	<label for="Notes">Notes</label>
          	<textarea style="width: 95%" name="Notes" rows="5"></textarea>
          </div>
          <div>
          	<label for="Status">Status</label>
          	<input style="width: 95%" type="text" name="Status"/>
          </div>
          <div>
          	<label for="Task_Name">Task Name</label>
            <input style="width: 95%" type="text" name="Task_Name" />
          </div>
          <div>
          	<label for="Task_Description">Task Description</label>
          	<textarea style="width: 95%" name="Task_Description" rows="5"></textarea>
          </div>
          <input type="hidden" name="_key"/>
          <div>
            <button id="submitButton">Submit</button>
          </div>
        </form>
      </html>
    </panel>

Before saving, in the top panel, add an id of taskCollectionPanel.

In the end, your Simple XML will look like this:

<dashboard stylesheet="crud_style.css">
  <label>CRUD</label>
  <row>
    <panel id="taskCollectionPanel">
      <table>
        <title>Task Collection</title>
        <search>
          <query>| inputlookup task_lookup | eval Update="Update" | eval Delete="Delete" | table *, Update, Delete</query>
          <earliest>0</earliest>
          <latest></latest>
        </search>
        <option name="wrap">true</option>
        <option name="rowNumbers">false</option>
        <option name="dataOverlayMode">none</option>
        <option name="drilldown">cell</option>
        <option name="count">10</option>
      </table>
    </panel>
    <panel id="taskFormPanel">
      <html>
        <form>
          <div>
          	<label for="Estimated_Completion_Date">Estimated Completion Date</label>
          	<input style="width: 95%" type="text" name="Estimated_Completion_Date"/>
          </div>
          <div>
          	<label for="Notes">Notes</label>
          	<textarea style="width: 95%" name="Notes" rows="5"></textarea>
          </div>
          <div>
          	<label for="Status">Status</label>
          	<input style="width: 95%" type="text" name="Status"/>
          </div>
          <div>
          	<label for="Task_Name">Task Name</label>
            <input style="width: 95%" type="text" name="Task_Name" />
          </div>
          <div>
          	<label for="Task_Description">Task Description</label>
          	<textarea style="width: 95%" name="Task_Description" rows="5"></textarea>
          </div>
          <input type="hidden" name="_key"/>
          <div>
            <button id="submitButton">Submit</button>
          </div>
        </form>
      </html>
  </row>
</dashboard>

The reason our table is getting cut off is because the width of the form panel is 50%. Let’s make some slight adjustments to the style using the crud_style.css we added earlier.

In crud_style.css add the following:

#taskCollectionPanel {
    width: 70% !important;
}
#taskFormPanel {
    width: 30% !important;
}

After making this style change your table should be taking up more space with your form now appearing more narrow. This helps to improve the readability of the table’s contents.

Updating the Data

When we click ‘Update’ in a table row, we'll need to populate our form with the values of the specific row we click on so that we can then modify the values and update them by clicking ‘Submit’.

To do this we’re going to write some JavaScript. First, go into your dashboard’s source and add a reference to our soon-to-be created JavaScript file. We also need to add an id to the table itself -- we will call the JavaScript file crud.js and apply an id of ‘taskCollectionTable’ to the table:

So, go into your app’s appserver/static directory. I'm working in the Search app so it would be in the search/appserver/static directory.

Once there, create a file called crud.js and add the following:

require([
    'underscore',
    'jquery',
    'splunkjs/mvc',
    'splunkjs/mvc/simplexml/ready!'
], function(_, $, mvc) {


    console.log('Hello World!');


});

Note: For development purposes, you may want to modify web.conf in $SPLUNK_HOME/etc/system/local/ to disable JavaScript caching:

[settings]
js_no_cache = True

If it doesn’t exist just create one.

Save the file and then restart Splunk. Once you restart go back to the dashboard and you should see ‘Hello World!’ output in the console. If you do not, go back and check to make sure your crud.js file matches what is above as well as making sure it is in your app’s appserver/static directory.

Pull the Table Cell Values

Now that we have our JavaScript hooked up, let’s work on pulling the values from the table so modify your JavaScript file:

require([
    'underscore',
    'jquery',
    'splunkjs/mvc',
    'splunkjs/mvc/simplexml/ready!'
], function(_, $, mvc) {


    var taskCollectionTable = mvc.Components.get('taskCollectionTable');


    taskCollectionTable.on('click', function(e) {


       e.preventDefault();
       console.log('e: ', e);


    });


});

First, we are creating a reference to our taskCollectionTable:

var taskCollectionTable = mvc.Components.get('taskCollectionTable');

Then we are registering a click event on the table and preventing its default drilldown behavior. We then log out the values of ‘e’:

    taskCollectionTable.on('click', function(e) {


       e.preventDefault();
       console.log('e: ', e);


    });

Save the file. If you turned off JavaScript caching all you will need to do is refresh the dashboard. Otherwise, you will need to run http://<your_splunk_address>/en-US/_bump

Now click on the table after refreshing and look in the console window -- you should see something similar to this:

As you can see, we have access to all of our table information. We can use this information to populate our form.

Populating the Form

First remove the console.log() and at the top of the file, inside the main function, add:

/* --- Define the form inputs --- */
var estimatedCompletionDate_Input = $('[name="Estimated_Completion_Date"]');
var notes_Input = $('[name="Notes"]');
var status_Input = $('[name="Status"]');
var taskName_Input = $('[name="Task_Name"]')
var taskDescription_Input = $('[name="Task_Description"]')
var _key_Input = $('[name="_key"]')

Then, below our Input variables, add a reference to the variables that will hold the value of our inputs:

/* --- Reference to the input values --- */
var estimatedCompletionDate_Val, notes_Val, taskName_Val, taskDescription_Val, _key_Val;

This will get each input element from our form.

Next, lets add an if statement to determine if we are clicking on the ‘Update’ field or not, as we only want this functionality to exist if we click ‘Update’:

if(e['field'] === 'Update') { }

Inside of the if statement add:

/* --- Pull values from the current table row --- */
estimatedCompletionDate_Val = e.data['row.Estimated_Completion_Date'];
notes_Val = e.data['row.Notes'];
status_Val = e.data['row.Status'];
taskName_Val = e.data['row.Task_Name'];
taskDescription_Val = e.data['row.Task_Description'];
 _key_Val = e.data['row._key'];

Above, we are setting our value variables to the values we are pulling out of the table. Next, we take those value variables and use them to set the value of the input fields using jQuery’s .val() method:

/* --- Insert values from rows into input fields --- */
estimatedCompletionDate_Input.val(estimatedCompletionDate_Val);
notes_Input.val(notes_Val);
status_Input.val(status_Val);
taskName_Input.val(taskName_Val);
taskDescription_Input.val(taskDescription_Val);
_key_Input.val(_key_Val);

Above, we are setting the value of each of input field to the values we pulled from our table earlier. This will populate our form.

Finally, let's log out each of the values from our form. This will allow us to also ensure our _key field is getting filled in as it is a hidden field.

$('form *').filter(':input').each(function(){
   var value = $(this).val();
   console.log(value);
});

Refresh your dashboard and click on the ‘Update’ column. It should fill in the entire form as well as log out the values of the form including the _key’s value in the console. If you click on any of the other columns it should drill down as expected.

In Part 2, we will cover how to CRUD our KV Store data.




Close off Canvas Menu