All Apps and Add-ons

Sideview Utils Pulldown - multiple selection

lukeh
Contributor

Hi Nick 🙂

I'm using Sideview Utils 2.2.10 and loving it!

I have written a dashboard to display charts of cisco switch interface usage and have added pulldowns with multiple selections. The user can choose multiple interfaces to chart inbound bps, outbound bps, inbound discards, and outbound discards.

The dashboard is working but there are a couple of things I'd like to be able to change:

1/ The charts are drawn automatically as there are auto populating drilldowns. How do I change it so that the user has to select an interface then click the submit button to initiate the underlying searches? Without this behaviour, all interfaces are drawn on the four charts upon initial load of the dashboard as no interface has been selected.

2/ There are four multiple selection pulldowns, ie. one pulldown for each chart. Is it possible to use just one multiple selection pulldown that feeds all four charts, noting that each chart is drawing a different metric?

Here is the dashboard:

<view autoCancelInterval="90" decomposeIntentions="false" isPersistable="true" isSticky="false" isVisible="true" objectMode="viewconf" onunloadCancelJobs="true" template="dashboard.html">
  <label>Interface Multiple Usage</label>

  <module name="AccountBar" layoutPanel="appHeader" />

  <module name="AppBar" layoutPanel="appHeader" />

  <module name="SideviewUtils" layoutPanel="appHeader" />

  <module name="Message" layoutPanel="messaging">
    <param name="maxSize">2</param>
    <param name="filter">*</param>
    <param name="clearOnJobDispatch">False</param>
  </module>

  <module name="Search" layoutPanel="panel_row1_col1" autoRun="True">
    <param name="search">
      | inputlookup mediacap_function.csv | dedup devicefunctioncategory | sort devicefunctioncategory
    </param>
    <param name="earliest">-5m</param>
    <param name="latest">now</param>

    <module name="Pulldown">
      <param name="name">selectedFunction</param>
      <param name="label">Function</param>
      <param name="float">left</param>
      <param name="staticOptions"/>
      <param name="valueField">devicefunctioncategory</param>

      <module name="Search">
        <param name="search">
          | inputlookup mediacap_function.csv | search devicefunctioncategory="$selectedFunction$" | stats count by hostname
        </param>
        <param name="earliest">-5m</param>
        <param name="latest">now</param>

        <module name="Pulldown">
          <param name="name">selectedHostname</param>
          <param name="label">Hostname</param>
          <param name="staticOptions"/>
          <param name="valueField">hostname</param>

          <module name="Search">
            <param name="search">hostname=$selectedHostname$ group="interface" metric="ifInOctets_*" | rex field=metric "_(?&lt;intname&gt;.*)" | dedup intname | sort intname</param>
            <param name="earliest">-1h</param>
            <param name="latest">now</param>

            <module name="Pulldown">
              <param name="name">selectedMetrictype</param>
              <param name="label">Inbound</param>
              <param name="float">left</param>
              <param name="staticOptions"/>
              <param name="size">5</param>
              <param name="template">metric="ifInOctets_$value$"</param>
              <param name="separator">+OR+</param>
              <param name="outerTemplate">( $value$ )</param>
              <param name="valueField">intname</param>

              <module name="Pulldown">
                <param name="name">selectedMetrictype2</param>
                <param name="label">Outbound</param>
                <param name="float">left</param>
                <param name="staticOptions"/>
                <param name="size">5</param>
                <param name="template">metric="ifOutOctets_$value$"</param>
                <param name="separator">+OR+</param>
                <param name="outerTemplate">( $value$ )</param>
                <param name="valueField">intname</param>

                <module name="Pulldown">
                  <param name="name">selectedMetrictype3</param>
                  <param name="label">In Discards</param>
                  <param name="float">left</param>
                  <param name="staticOptions"/>
                  <param name="size">5</param>
                  <param name="template">metric="ifInDiscards_$value$"</param>
                  <param name="separator">+OR+</param>
                  <param name="outerTemplate">( $value$ )</param>
                  <param name="valueField">intname</param>

                  <module name="Pulldown">
                    <param name="name">selectedMetrictype4</param>
                    <param name="label">Out Discards</param>
                    <param name="staticOptions"/>
                    <param name="size">5</param>
                    <param name="template">metric="ifOutDiscards_$value$"</param>
                    <param name="separator">+OR+</param>
                    <param name="outerTemplate">( $value$ )</param>
                    <param name="valueField">intname</param>

                    <module name="Pulldown">
                      <param name="name">selectedSpan</param>
                      <param name="label">Span Granularity</param>
                      <param name="float">left</param>
                      <param name="staticOptions">
                        <list>
                          <param name="label">5m</param>
                          <param name="value">5m</param>
                        </list>
                        <list>
                          <param name="label">10m</param>
                          <param name="value">10m</param>
                        </list>
                        <list>
                          <param name="label">15m</param>
                          <param name="value">15m</param>
                        </list>
                        <list>
                          <param name="label">30m</param>
                          <param name="value">30m</param>
                        </list>
                        <list>
                          <param name="label">1h</param>
                          <param name="value">1h</param>
                        </list>
                        <list>
                          <param name="label">2h</param>
                          <param name="value">2h</param>
                        </list>
                        <list>
                          <param name="label">4h</param>
                          <param name="value">4h</param>
                        </list>
                        <list>
                          <param name="label">1d</param>
                          <param name="value">1d</param>
                        </list>
                      </param>

                      <module name="Search">
                        <param name="earliest">-24h</param>
                        <param name="latest">now</param>

                        <module name="TimeRangePicker">
                          <param name="default">Last 24 hours</param>
                          <param name="searchWhenChanged">True</param>

                          <module name="Button">
                            <param name="allowSoftSubmit">True</param>

                            <module name="Search" layoutPanel="panel_row2_col1">
                              <param name="search">
                                index=mediacap hostname="$selectedHostname$" $selectedMetrictype$
                                | streamstats current=t global=f window=2 earliest(value) as curr latest(value) as next by metric
                                | eval delta=next-curr
                                | eval inkilobits=(delta*8/1000)
                                | timechart span=$selectedSpan$ per_second(inkilobits) as in_kbps by metric
                              </param>

                              <module name="HiddenChartFormatter">
                                <param name="chart">line</param>
                                <param name="charting.chart.nullValueMode">connect</param>
                                <param name="primaryAxisTitle.text">Time</param>
                                <param name="secondaryAxisTitle.text">kbps</param>

                                <module name="JobProgressIndicator" />

                                <module name="JSChart">
                                  <param name="width">100%</param>
                                  <param name="height">200px</param>
                                </module>

                                <module name="Search" layoutPanel="panel_row2_col2">
                                  <param name="search">index=mediacap hostname="$selectedHostname$" $selectedMetrictype2$
                                  | streamstats current=t global=f window=2 earliest(value) as curr latest(value) as next by metric
                                  | eval delta=next-curr
                                  | eval outkilobits=(delta*8/1000)
                                  | timechart span=$selectedSpan$ per_second(outkilobits) as out_kbps by metric
                                  </param>

                                  <module name="HiddenChartFormatter">
                                    <param name="chart">line</param>
                                    <param name="charting.chart.nullValueMode">connect</param>
                                    <param name="primaryAxisTitle.text">Time</param>
                                    <param name="secondaryAxisTitle.text">kbps</param>

                                    <module name="JobProgressIndicator" />

                                    <module name="JSChart">
                                      <param name="width">100%</param>
                                      <param name="height">200px</param>
                                    </module>

                                    <module name="Search" layoutPanel="panel_row3_col1">
                                      <param name="search">index=mediacap hostname="$selectedHostname$" $selectedMetrictype3$
                                      | timechart span=$selectedSpan$ avg(value) as indiscards by metric
                                      </param>

                                      <module name="HiddenChartFormatter">
                                        <param name="chart">line</param>
                                        <param name="charting.chart.nullValueMode">connect</param>
                                        <param name="primaryAxisTitle.text">Time</param>
                                        <param name="secondaryAxisTitle.text">Discards</param>

                                        <module name="JobProgressIndicator" />

                                        <module name="JSChart">
                                          <param name="width">100%</param>
                                          <param name="height">200px</param>
                                        </module>

                                        <module name="Search" layoutPanel="panel_row3_col2">
                                          <param name="search">index=mediacap hostname="$selectedHostname$" $selectedMetrictype4$
                                            | timechart span=$selectedSpan$ avg(value) as outdiscards by metric
                                          </param>

                                          <module name="HiddenChartFormatter">
                                            <param name="chart">line</param>
                                            <param name="charting.chart.nullValueMode">connect</param>
                                            <param name="primaryAxisTitle.text">Time</param>
                                            <param name="secondaryAxisTitle.text">Discards</param>

                                            <module name="JobProgressIndicator" />

                                            <module name="JSChart">
                                              <param name="width">100%</param>
                                              <param name="height">200px</param>
                                            </module>
                                          </module>
                                        </module>
                                      </module>
                                    </module>
                                  </module>
                                </module>
                              </module>
                            </module>
                          </module>
                        </module>
                      </module>
                    </module>
                  </module>
                </module>
              </module>
            </module>
          </module>
        </module>
      </module>
    </module>
  </module>
</view>

Thanks in advance,

Luke 🙂

1 Solution

sideview
SplunkTrust
SplunkTrust

1) I think the answer to your first question lies in the "allowAutoSubmit" param of the Button module. Let's break down the players here a bit.

  • autoRun="True" -- is an attribute that can live on any module. It tells the system "start a push from this point, once the page is ready". Searches get dispatched as a result of that push, but the primary effect of autoRun is simply to start the push from there. Here you've correctly put only one autoRun="True", way at the top.

  • <param name="allowSoftSubmit">True</param> -- is a param on the Sideview Button module (and also on Splunk's SubmitButton module). This determines whether the SubmitButton should propagate pushes downstream by default (True), or whether it should halt them there (False). When it's set to False, basically the user has to click the green button for the push to propagate and thus for the various downstream searches to be dispatched.

...However, as you'll find with both the Button and SubmitButton modules, setting allowSoftSubmit to False will not prevent the initial autoRun push from going through. It turns out that initial autoRun push is a little special. Which brings us to....

  • <param name="allowAutoSubmit">False</param> -- this is only a param on the Sideview Button module, and it serves to prevent that first autoRun push from passing through the Button. With this param you should be able to use autoRun to populate your Pulldown modules initially, but without the main searches downstream from the Button running.

2) For your second question, no there's not a clean way, and it's actually a gap that I should address in a future release. I should have given some module (probably ValueSetter), the ability to do just the outerTemplate/separator/template bits of what Pulldown does - ie just the parts where it goes from an array of N selected values, to outputting ( field="value1" OR field="value5" OR field="value17" ). Because only Pulldown can do that, and because you need the inner template param to be calculated differently, you kind of need 4 Pulldowns.

There are 2 messy ways. The first is to write a customBehavior to do basically what I outlined above - the outertemplate/separator/template bits, and then have 4 CustomBehavior modules, each passing a different arg.fieldName param (it's seldom used or discovered, but you can pass custom params to CustomBehavior modules). If you're already a Javascript whiz, you're familiar with Sideview CustomBehaviors and you're familiar with the Splunk module framework methods, this can be a very good direction. Otherwise not so much.

the other way I can think of is borderline insane, and that's to use the selectedMetricType.rawValue key on the Pulldown in a PostProcess search. the rawValue key will be an Array, but it'll get serialized as a comma-separated string into the PostProcess. then you can manipulate that string literal in the search language, split, append, join, mvexpand, collapse,etc your way to the string literal that you would want to use in your particular search for the particular chart, then use ResultsValueSetter module to pull that string literal back down from your postProcessed search results, back down to the client where it can be plugged into your search for the given chart to render. I'll admit it's a lot of moving parts and it's such a long way to go that it's probably not a net positive.

View solution in original post

sideview
SplunkTrust
SplunkTrust

Also note that in cleaning it up, I've made it a lot easier to see that you have some strange nesting here. 😃 Each of your chart blocks is nested inside the HiddenChartFormatter of the previous block. You can unwind quite a lot of that and it'll make the view easier to deal with.

0 Karma

sideview
SplunkTrust
SplunkTrust

Note - i cleaned up your XML by using the weird trick of putting it in Splunk, firing it up in the Sideview Editor, picking a random module to edit and submitting the form unchanged. That will serve to re-indent all the XML. The Editor is a little conservative in its reindenting, but it does all the hard parts and it can be a great way to quickly repair the XML indentation on a large and complex view.

0 Karma

sideview
SplunkTrust
SplunkTrust

1) I think the answer to your first question lies in the "allowAutoSubmit" param of the Button module. Let's break down the players here a bit.

  • autoRun="True" -- is an attribute that can live on any module. It tells the system "start a push from this point, once the page is ready". Searches get dispatched as a result of that push, but the primary effect of autoRun is simply to start the push from there. Here you've correctly put only one autoRun="True", way at the top.

  • <param name="allowSoftSubmit">True</param> -- is a param on the Sideview Button module (and also on Splunk's SubmitButton module). This determines whether the SubmitButton should propagate pushes downstream by default (True), or whether it should halt them there (False). When it's set to False, basically the user has to click the green button for the push to propagate and thus for the various downstream searches to be dispatched.

...However, as you'll find with both the Button and SubmitButton modules, setting allowSoftSubmit to False will not prevent the initial autoRun push from going through. It turns out that initial autoRun push is a little special. Which brings us to....

  • <param name="allowAutoSubmit">False</param> -- this is only a param on the Sideview Button module, and it serves to prevent that first autoRun push from passing through the Button. With this param you should be able to use autoRun to populate your Pulldown modules initially, but without the main searches downstream from the Button running.

2) For your second question, no there's not a clean way, and it's actually a gap that I should address in a future release. I should have given some module (probably ValueSetter), the ability to do just the outerTemplate/separator/template bits of what Pulldown does - ie just the parts where it goes from an array of N selected values, to outputting ( field="value1" OR field="value5" OR field="value17" ). Because only Pulldown can do that, and because you need the inner template param to be calculated differently, you kind of need 4 Pulldowns.

There are 2 messy ways. The first is to write a customBehavior to do basically what I outlined above - the outertemplate/separator/template bits, and then have 4 CustomBehavior modules, each passing a different arg.fieldName param (it's seldom used or discovered, but you can pass custom params to CustomBehavior modules). If you're already a Javascript whiz, you're familiar with Sideview CustomBehaviors and you're familiar with the Splunk module framework methods, this can be a very good direction. Otherwise not so much.

the other way I can think of is borderline insane, and that's to use the selectedMetricType.rawValue key on the Pulldown in a PostProcess search. the rawValue key will be an Array, but it'll get serialized as a comma-separated string into the PostProcess. then you can manipulate that string literal in the search language, split, append, join, mvexpand, collapse,etc your way to the string literal that you would want to use in your particular search for the particular chart, then use ResultsValueSetter module to pull that string literal back down from your postProcessed search results, back down to the client where it can be plugged into your search for the given chart to render. I'll admit it's a lot of moving parts and it's such a long way to go that it's probably not a net positive.

sideview
SplunkTrust
SplunkTrust

Thanks for bumping this - cause I see I forgot to come back and add - #2 has been implemented as of a few months ago. #2 now exists in the form of the ArrayValueSetter module. It is, as pontificated here, "the template/separator/outerTemplate part of Pulldown, without the Pulldown." And there is of course a full page of docs and examples for it. Actually in latest (2.4.8) which came out a few days ago, all 3 'ValueSetter' modules (ValueSetter/ResultsValueSetter/ArrayValueSetter) have their own section of docs and examples so check it out! http://sideviewapps.com/apps/sideview-utils

0 Karma

brettcave
Builder

How to identify a sideview utils user: Their posts start with "I'm using sideview utils and loving it... "

sideview
SplunkTrust
SplunkTrust

Absolutely. It's something that will come up rarely, but regularly. It's added to my queue and I'll get it into a future release in some form or another.

0 Karma

lukeh
Contributor

Thanks Nick! I fixed #1 and cleaned up the chart blocks too, thanks for the advice!

#2 is a nice to have so I'll make it a feature request if that is ok 🙂

0 Karma
Get Updates on the Splunk Community!

Introducing the 2024 SplunkTrust!

Hello, Splunk Community! We are beyond thrilled to announce our newest group of SplunkTrust members!  The ...

Introducing the 2024 Splunk MVPs!

We are excited to announce the 2024 cohort of the Splunk MVP program. Splunk MVPs are passionate members of ...

Splunk Custom Visualizations App End of Life

The Splunk Custom Visualizations apps End of Life for SimpleXML will reach end of support on Dec 21, 2024, ...