Refine your search:

5
10

Is it possible to refresh a single module on a dashboard?

A client is interested in having a single dashboard with half static, backward looking charts, and half real-time, forward looking charts. They want to refresh the static ones every so often without losing the real-time graphs' history.

asked 30 Jun '10, 20:52

Jason's gravatar image

Jason
3.6k71074
accept rate: 43%

edited 05 May '11, 14:41

jlaw's gravatar image

jlaw ♦
73138

Note that this was only really needed before Splunk 4.3 introduced realtime charts' backfill functionality in this particular case.

(14 Nov '12, 03:19) Jason

3 Answers:

Another option is to add a custom module to splunk that can refresh periodically. Let's call the module AutoRefresh. To do this you have to create the following directory structure (in an app, eg. search or better a custom one):

$SPLUNK_HOME/etc/apps/someapp
| - appserver
   | - modules
      |- AutoRefresh
        | - AutoRefresh.conf
        | - AutoRefresh.css
        | - AutoRefresh.js

AutoRefresh.conf:

[module]
className = Splunk.Module.AutoRefresh
superClass = Splunk.Module
description = This module refreshes it's descending modules periodically.

[param:invervalInSeconds]
required = True
label = This parameters defines the inverval in seconds in which the descending search modules should be reloaded.

AutoRefresh.css:

div.SplunkModule.AutoRefresh { display: none; margin: 0; padding: 0; }

AutoRefresh.js:

Splunk.namespace("Module");
Splunk.Module.AutoRefresh = $.klass(Splunk.Module, {
    initialize: function($super, container) {
        $super(container);
        var interval = (+this._params['invervalInSeconds'])*1000;
        this._timer = setInterval(this.refresh.bind(this), interval);
    },
    refresh: function() {
        this.pushContextToChildren();
    }
});

Once you've added those folders and files you have to restart Splunk. Then you'll be able to use the module in your advanced xml views like this:

... truncated ...

<module name="GenericHeader" layoutPanel="panel_row1_col1">
    <param name="label">Status</param>
    <module name="AutoRefresh">
        <param name="invervalInSeconds">10</param>
        <module name="HiddenSearch" layoutPanel="panel_row1_col1_grp1" autoRun="True">
                    ...
        </module>
    </module>
</module>
...

In this example all (search-)descendants of the AutoRefresh module would be refresh every 10 seconds.

link

answered 30 Jun '10, 22:38

ziegfried's gravatar image

ziegfried ♦
10.1k1618
accept rate: 52%

1

Any chance such a module will be built-in in the future?

(01 Jul '10, 14:21) Lowell ♦

If an AutoRefresh modules contains another AutoRefresh module, is there a way so that parent auto refresh module does not refresh any module under a child AutoRefresh module?

Very useful module though.

(27 Apr '12, 11:02) asingla

thanks @ziegfried for your premade module.

(19 Jul '12, 00:54) crt89

Excellent! thank you.

(17 Aug '12, 07:53) sbrant_splunk

Yep, it can be done if you're using the advanced XML.

I cant think of an app offhand that does it but im sure there is one. You just put a SubmitButton module into the XML as follows:

Example:
1) an ordinary dashboard panel in the Advanced XML, with no SubmitButton

<module name="HiddenSearch" layoutPanel="panel_row1_col1" group="No SubmitButton.. :(" autoRun="True">
  <param name="search">* | top sourcetype | fields - percent</param>
  <param name="earliest">-30s</param>
  <module name="HiddenChartFormatter">
    <param name="charting.chart">bar</param>
    <param name="charting.primaryAxisTitle.text">Sourcetype</param>
    <param name="charting.secondaryAxisTitle.text">## of events</param>

    <module name="FlashChart">
    </module>

  </module>
</module>

2) same panel, but with a SubmitButton

<module name="HiddenSearch" layoutPanel="panel_row1_col1" group="with the SubmitButton :)" autoRun="True">
  <param name="search">* | top sourcetype | fields - percent</param>
  <param name="earliest">-30s</param>
  <module name="HiddenChartFormatter">
    <param name="charting.chart">bar</param>
    <param name="charting.primaryAxisTitle.text">Sourcetype</param>
    <param name="charting.secondaryAxisTitle.text">## of events</param>

    <module name="SubmitButton">
      <param name="label">Refresh</param>

      <module name="FlashChart">
      </module>
    </module>
  </module>
</module>

Make sure that the module tag for the SubmitButton encloses the FlashChart module and also that it encloses any other modules that will be displaying data for this particular job -- most typically headers. As is always the case with the containment of module tags, if someone isnt enclosed by a module, then they know nothing about that module. So in this example if a SimpleResultsHeader is not enclosed by the SubmitButton, then it wont be refreshed when users click on it.

link

answered 30 Jun '10, 22:04

sideview's gravatar image

sideview ♦
25.6k4543
accept rate: 46%

edited 30 Jun '10, 22:11

This seems like the most obvious place to post this.

HiddenSavedSearches are not refreshed by AutoRefresh, this is because the search is defined when the page loads, and isn't changed by pushContextToChildren().

This cobbled together Module, when used in place of HiddenSavedSearch works around that problem. Obviously you still need AutoRefresh upstream.

Credit goes to sideview for the pointers along the way

The controller module is a straight copy of HiddenSearchSwapper, as is the ajax call in the js file

DynamicHiddenSavedSearch.conf

[module]
className = Splunk.Module.DynamicHiddenSavedSearch
superClass = Splunk.Module
description = Given a saved search name, finds the last run search for that saved search. It will update its context with the latest latest instance of the saved search when refreshed.

[param:savedSearch]
required = True
label = This is the name of the saved search to use when looking up a searches from the saved search's history or when dispatching a new search.

DynamicHiddenSavedSearch.css

div.SplunkModule.HiddenSavedSearch {
    display: none;
    padding: 0;
    margin: 0;
}

DynamicHiddenSavedSearch.html

<%page args="module"/>
<%namespace name="lib" file="//lib.html" import="*"/>
% if module['params'].get('savedSearch'):
${lib.getSavedSearch(module, module['params'].get('savedSearch'), module['params'].get('useHistory'), APP['id'], cherrypy.session['user'].get('name'), VIEW['nativeObjectMode'])}
% endif

DynamicHiddenSavedSearch.js

Splunk.Module.DynamicHiddenSavedSearch = $.klass(Splunk.Module, {

  savedSearch: null,
  initialize: function($super, container) {
    $super(container);
    this.childEnforcement = Splunk.Module.ALWAYS_REQUIRE;

    this.messenger = Splunk.Messenger.System.getInstance();
    this.hide(this.HIDDEN_MODULE_KEY);

    this._params['boundingGroup']   = this.getGroupName();
    this.sid = null;

    var hashParams = Splunk.util.queryStringToProp(Splunk.util.getHash());
    var meta = this.container.closest('.dashboardCell').find('.paneledit').attr("data-sequence");
    var key = 'panel_' + meta + '.sid';
    if (meta && hashParams.hasOwnProperty(key)) {
       this.sid = hashParams[key];
       this.logger.info('Soft refresh; reuse job sid', this.sid);
       delete hashParams[key];
       window.location.hash = Splunk.util.propToQueryString(hashParams);
    }

  },

  getModifiedContext: function() {

    var context           = this.getContext();
    var jsonSearch        = this._getSavedSearch(this._params["savedSearch"]);
    jsonSearch["group"]   = this._params['boundingGroup'];
    var resurrectedSearch = Splunk.Search.resurrect(jsonSearch);

    if ( this._params['savedSearch'] != resurrectedSearch.getSavedSearchName() ) {
      this.messenger.send('error', 'splunk.search', _('Error resurrecting latest results for saved search ' + this._params["savedSearch"]));
      this.logger.debug('Failed to resurrect search object for ' + this._params["savedSearch"]);
      return context;
    } else {
      context.set("search",Splunk.Search.resurrect(jsonSearch));
      return context; 
    }

  },

  _getSavedSearch: function(savedSearchName) {

    var newSearch;

    var targetURL  = Splunk.util.make_url(
                     'module',
                      Splunk.util.getConfigValue('SYSTEM_NAMESPACE'),
                      this.moduleType,
                      'render?savedSearchName=' + savedSearchName + '&client_app=search'
                    );

    $.ajax({

           async: false,
            type: 'GET',
             url: targetURL,
      beforeSend: function(xhr) {
                    xhr.setRequestHeader('X-Splunk-Module', this.moduleType);
                  },

        complete: function(data) {
                    this.logger.debug('response OK from server');
                    newSearch = JSON.parse(data.responseText);
                  }.bind(this),

           error: function() {
                    this.messenger.send('error', 'splunk.search', _('Unable to get saved search from controller')); 
                    this.logger.debug('response ERROR from server');
                    return null;
                  }.bind(this)

    });   // end ajax requet

    return newSearch;

  }

});

DynamicHiddenSavedSearch.py

import cherrypy
import json
import logging
import splunk
import time
import controllers.module as module

logger = logging.getLogger('splunk.module.DynamicHiddenSavedSearch')

class DynamicHiddenSavedSearch(module.ModuleHandler):

    def generateResults(self, host_app=None, client_app=None, savedSearchName=None, useHistory=None):

        if savedSearchName: 
            jsonSearch = None
        owner = 'nobody'
            try: 
                savedSearchObject = splunk.search.getSavedSearch(label = savedSearchName, namespace = client_app, owner = owner)

                jsonSearch = splunk.appserver.mrsparkle.util.resurrectFromSavedSearch(
                    savedSearchObject = savedSearchObject,
                    hostPath = splunk.mergeHostPath(),
                    namespace = client_app,
                    owner = owner)

                job = splunk.search.getJobForSavedSearch(
                    savedSearchName,
                    useHistory="True", 
                    namespace=client_app,
                    owner=owner,
                    search='name=scheduler*')

                if (job):
                    jsonSearch["job"] = job.toJsonable(timeFormat='unix')

                return json.dumps(jsonSearch)

            except Exception, e:
                logger.exception(e)
                return ""
        else:
            logger.warn('savedSearchName was not passed from the caller')
            return ""
link

answered 23 Aug '12, 13:46

jonuwz's gravatar image

jonuwz
5.0k37
accept rate: 40%

edited 23 Aug '12, 13:48

Post your answer
toggle preview

Follow this question

Log In to enable email subscriptions

RSS:

Answers

Answers + Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×471
×274
×56

Asked: 30 Jun '10, 20:52

Seen: 2,452 times

Last updated: 14 Nov '12, 03:19

Copyright © 2005-2012 Splunk Inc. All rights reserved.