Splunk users that deal with timecharts likely run into the issue of wanting to customize the dynamic time span feature. A quick search of Splunk Answers will discover such inquiries, including this one with a suitable answer (we use it in our Layer8Insight App for Splunk).

Now, it is tempting to make a macro like the following and use it in various dashboards. The problem with that approach is it will either limit you in terms of the available span ranges, or you have to make variations of the macro to match each use case.

[dynamic_span]
description = Return dynamic time span setting based on search time period
iseval      = 0
definition  = [stats count | addinfo | eval range = info_max_time - info_min_time | eval span = "span=" . case(range < 24*3600+3600, "5m", range < 3*24*3600+3600, "15m", range < 14*24*3600+3600, "1h", range < 31*24*3600+3600, "4h", 1=1, "1d") | return $span]

Instead of using a set of macros, the following will walk you through turning this approach into a flexible input in a dashboard.

Let us turn the macro into a search in our dashboard. This can be done in two ways,

  1. A global search at the top of the dashboard, or
  2. A hidden table with a search (see previous post).

Either of the preceding options will work. The following is an example based on the first one.

We will first define a global base search that calculates the desired time span based on the dashboard search period, use a form input element to enforce the dynamic span token in the dashboard, and add a small snippet of JavaScript to stitch the two together.

In my experience, using the JavaScript improves reliability of the dashboard. One could define the search directly in the XML of the dropdown input element; however, past observations have made me skeptical of the dependability of this approach.

Because we are defining the dynamic time span in the Simple XML with a search and an input element, adjustments can be made in the XML based on the use case / end-user, i.e., isolating the changes. There is the added benefit that the user can manually change the span on the live dashboard using the dropdown input element.

    <form script="app.js">
      ...
      <search id="span_calc">
        <query>
          | gentimes start=-1
          | addinfo
          | eval range = info_max_time-info_min_time
          | eval span = "span=" . case(range &lt; 24*3600+3600, "5m", range &lt; 3*24*3600+3600, "15m", range &lt; 14*24*3600+3600, "1h", range &lt; 31*24*3600+3600, "4h", 1=1, "1d")
          | fields span
        </query>
      </search>
      ...
      <fieldset align="center" autoRun="true" submitButton="false">
        <input type="time" searchWhenChanged="true">
          <label>Search Period</label>
          <default>
            <earliest>-8h</earliest>
            <latest>now</latest>
          </default>
          <change>
            <condition label="*">
              <unset token="form.dynamic_span"/>
            </condition>
          </change>
        </input>  
        <input id="dynamic_span" searchWhenChanged="true" token="dynamic_span" type="dropdown">
          <label>Charting Span</label>
          <choice value="span=5m">5 Minutes</choice>
          <choice value="span=10m">10 Minutes</choice>
          <choice value="span=15m">15 Minutes</choice>
          <choice value="span=1h">1 Hour</choice>
          <choice value="span=2h">2 Hour</choice>
          <choice value="span=4h">4 Hours</choice>
          <choice value="span=12h">12 Hours</choice>
          <choice value="span=1d">1 Day</choice>
          <choice value="span=1w">1 Week</choice>
          <default>span=5m</default>
          <selectFirstChoice>false</selectFirstChoice>
          <showClearButton>false</showClearButton>
          <allowCustomValues>true</allowCustomValues>
        </input>
      </fieldset>
      ...
      <row>
      ....
      </row>
    </form>



Note the dropdown input labeled "dynamic_span" lists a bunch of possible span definitions. The value of the dropdown gets set automatically by the following JavaScript found in the "appsever/static/app.js" file referenced in the form element line.

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

      // Sets token 'name' to 'value' in defaultTokenModel.
      // Only sets token 'name' to 'value' in submittedTokenModel if 'submit' argument is true
      function setToken(name, value, submit) {
        if (typeof name === 'undefined') {
          return;
        }
        var defaultTokens = mvc.Components.get('default');
        if (defaultTokens) {
          defaultTokens.set(name, value);
        }
        if (!!submit) {
          submitTokens();
        }
      }

      // Copy defaultTokenModel values into submittedTokenModels
      function submitTokens() {
        var submittedTokens = mvc.Components.get('submitted');
        var defaultTokens = mvc.Components.get('default');
        if (submittedTokens && defaultTokens) {
          submittedTokens.set(defaultTokens.toJSON());
        }
      }   

      // Find the dynamic span search and setup a listener to 
      // parse the data whenever the search has results
      var spanSearch = mvc.Components.getInstance("span_calc");
      var spanResults = spanSearch.data('results', { output_mode: 'json_rows', count: 0 });

      // set the 'dynamic_span' input element to the calculated span 
      // string by extracting the first result of the search
      spanResults.on("data", function() {
        if (!spanResults.hasData()) {
          setToken('form.dynamic_span', 'span=5m');
        } else {
          setToken('form.dynamic_span', spanResults.data().rows[0][0], true);
        }
        submitTokens();
      });
    });