Dashboards & Visualizations

Issue with css, html, js Formatting Search Output

genesiusj
Builder

Hello,
I'm starting this post with a shoutout to @niketn because I used one of his post as the basis for my dashboard. However, input from any/all Splunkers out there is appreciated.

Here is my code, modified from niketnilay's post. How to show table result in one page/ table modification

   <row>
    <panel>
      <title>Show Table Results in One Page</title>
      <table>
        <search>
          <query> index=oit_printer_monitoring AND type=Printer 
    | eval timeConvDate=strftime(_time,"%a %m-%d-%Y") 
    | eval timeConvTime=strftime(_time,"%H:%M:%S") 
    | eval statusNum=case(status="printing,deleting,error",4,status="error,toner low",4,status="printing,error",4,status="paper jam",4,status="no toner",4,status="error,offline",4,status="error",4,
        status="door open,error",3,status="spooling,paused",3,status="paused",3,status="out of paper",3,status="error,out of paper",3,status="offline",3,status="door open",3,
        status="toner low",2,status="restarted",2,
        status="printing,deleting",1,status="printed,deleting",1,status="printing,printed,deleting",1,status="error,warming up",1,status="spooling,printing",1,status="warming up",1,status="spooling",1,status="printing",1,status="normal",1) 
    | sort - statusNum, status 
    | fields printer, status, statusNum, timeConvDate, timeConvTime 
    | dedup printer 
    | eval printer="#".printer 
    | eval component=mvzip(printer,mvzip(status,mvzip(timeConvDate,timeConvTime,"..."),"..."),"...") 
    | stats values(component) as component 
    | nomv component 
    | eval component="<div>".replace(component,"#","</div><div>")."</div>" 
    | makemv delim="..." component 
    | table component</query>......

Explanation.
Create two new fields for time and date. | eval timeConvDate=strftime(_time,"%a %m-%d-%Y") | eval timeConvTime=strftime(_time,"%H:%M:%S")
Create a new field to represent the status as a number that can be sorted later. | eval statusNum=case(status="printing,deleting,error",4,status="error,toner low",4,....
Append a "#" in front of my first field, printer, to establish the beginning of a new field component. | eval printer="#".printer
The field **component
* will be concatenation of several other fields: printer, status, and the timeConvDate and timeConvTime fields as one. | eval component=mvzip(printer,mvzip(status,mvzip(timeConvDate,timeConvTime,"..."),"..."),"...") I used "..." instead of "|" between each of the concatenated fields.
The next two lines are from niketnilay's code unchanged. | stats values(component) as component | nomv component '
Modified niketnilay's eval/replace code as follows:
| eval component="<div>".replace(component,"#","</div><div>")."</div>"By using the "..." all 4 fields stay associated to each other, and the "#" indicates of the start of the field **component**.
Replaced the "..." within the field component with a carriage return/newline.
| makemv delim="..." component `

Before continuing, I have a question about the field named *component. When I substituted ***component* with my field name, printerResult, it did not work. I had substituted in the js code as well. Therefore, I used component instead. My question is, in the js code, the word Components is used (plural and upper case C). Is this a special variable name for js and that is why it was used?*

I am using display_token_with_html_content.js as written.

 require([
     "jquery",
     "splunkjs/mvc",
     "splunkjs/mvc/simplexml/ready!"
 ], function (
     $,
     mvc
 ) {
         var defaultTokenModel = mvc.Components.get("default");
         defaultTokenModel.on("change:tokResultsInHTML", function (model, tokResultsInHTML, options) {
             if (tokResultsInHTML !== undefined) {
                 $("#htmlTokenContainer").html(tokResultsInHTML);
             }
         });
     });

I used niketnilay's css in a panel

<panel>
  <title>Applying HTML Style</title>
  <html>
     <style>
       #htmlTokenContainer{
         display:flex;
         flex-wrap:wrap;
       }
       #htmlTokenContainer div{
         width: 260px;
       }
     </style>
     $tokResultsInHTML$
   </html>....

Lastly, I created another panel with just the token value assigned earlier per the niketnilay example.

<panel>
  <title>Format Data as desired output and show as html</title>
  <html>       
       <div id="htmlTokenContainer">      
       </div>
     </html>....

Here is a screenshot of my results.

Printer Dashboard Issue

What I am trying to accomplish is placing each value of component into individual cells. The formatting would be all centered. As the final requirement click the printer name in any one of the cells would set a token, which displays another panel (depends="token" ) and populates the panel with data specific to the printer clicked.

Thanks and God bless,
Genesius

0 Karma
1 Solution

niketn
Legend

@genesiusj @vinothn

Turns out this is purely Simple XML problem (with CSS override if required). No <html> table and JS Extension required.

I used the following approach:

  1. Build a Splunk table with Multi-value cells (You can arrange as single Row or single column). For each Printer multiple values are Printer Name, Status, Status Type, Date and Time.
  2. Apply color to table cell using expression color palette based on regex match for Status Type. Since case() is not available nested if() can be applied for setting more than two color ranges. Refer to answer. Refer to older answer: https://answers.splunk.com/answers/668588/how-to-add-custom-color-to-blank-cell.html
  3. Enable table drilldown. $click.value$ gives all values in the multi-value cell clicked with each value separated by comma and $click.value2$ gives specific value in the multi-valued cell clicked.
  4. Apply custom CSS to format Table cell look as a tile as per the requirement.

alt text

Following is the Simple XML code required.
PS: Supports drilldown and requires no JS. Also supports sorting by Printer Name by default table sorting property :)

 <dashboard>
  <label>Table with Color and Format</label>
  <row>
    <panel>
      <html>
        <style>
          #table_tile table tbody{
            display:flex;
            flex-wrap: wrap;
          }
          #table_tile table tbody tr{
            margin-right:10px;
            margin-bottom:10px;
          }
          #table_tile table tbody tr td{
            width: 180px;
            text-align: center;
          }
        </style>
        <div>
          <div>Clicked Value in Cell (click.value):$click.value$</div>
          <div>Clicked Cell Values (click.value2):$click.value2$</div>
        </div>
      </html>
      <table id="table_tile">
        <search>
          <query>| makeresults 
| eval status="printing,deleting,error;printing,error;door open,error;restarted;printed,deleting;error,offline;error,offline;spooling,paused" 
| makemv status delim=";" 
| mvexpand status 
| eval delta=500 
| streamstats count as sno 
| eval printer="printer".sno 
| eval delta=delta*sno 
| eval _time=_time-delta 
| fields - delta sno 
| eval timeConvDate=strftime(_time,"%a %m-%d-%Y") 
| eval timeConvTime=strftime(_time,"%H:%M:%S") 
| eval statusClass=case(status="printing,deleting,error","status_fatal",status="error,toner low","status_fatal",status="printing,error","status_fatal",status="paper jam","status_fatal",status="no toner","status_fatal",status="error,offline","status_fatal",status="error","status_fatal",
    status="door open,error","status_critical",status="spooling,paused","status_critical",status="paused","status_critical",status="out of paper","status_critical",status="error,out of paper","status_critical",status="offline","status_critical",status="door open","status_critical",
    status="toner low","status_low",status="restarted","status_low",
    status="printing,deleting","status_info",status="printed,deleting","status_info",status="printing,printed,deleting","status_info",status="error,warming up","status_info",status="spooling,printing","status_info",status="error,offline","status_info",status="spooling","status_info",status="printing","status_info",status="normal","status_info") 
| sort - statusClass, status 
| table printer, status, statusClass, timeConvDate, timeConvTime
| eval "Printer Info"=printer."###".status."###".statusClass."###".timeConvDate."###".timeConvTime
| fields "Printer Info"
| makemv "Printer Info" delim="###"</query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
          <sampleRatio>1</sampleRatio>
        </search>
        <option name="count">20</option>
        <option name="dataOverlayMode">none</option>
        <option name="drilldown">cell</option>
        <option name="percentagesRow">false</option>
        <option name="refresh.display">progressbar</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
        <format type="color" field="Printer Info">
          <colorPalette type="expression">if (match(value,"status_fatal"), "#DC4E41", if(match(value,"^status_critical"),"#F8BE34", if(match(value,"status_low"),"#62B3B2","#B6C75A")))</colorPalette>
        </format>
        <drilldown>
          <set token="click.value">$click.value$</set>
          <set token="click.value2">$click.value2$</set>
        </drilldown>
      </table>
    </panel>
  </row>
</dashboard>
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

Get Updates on the Splunk Community!

Why You Can't Miss .conf25: Unleashing the Power of Agentic AI with Splunk & Cisco

The Defining Technology Movement of Our Lifetime The advent of agentic AI is arguably the defining technology ...

Deep Dive into Federated Analytics: Unlocking the Full Power of Your Security Data

In today’s complex digital landscape, security teams face increasing pressure to protect sprawling data across ...

Your summer travels continue with new course releases

Summer in the Northern hemisphere is in full swing, and is often a time to travel and explore. If your summer ...