GIG: Building tables for fun and format

I was building out the Sumo Logic integration and ran into an interesting issue. The results from Sumo Logic come out as an array of JSON objects and I needed a good way to display these in a readable fashion. These are the raw values from Sumo Logic:

{
  "SearchName": "Cookies - Webhook",
  "SearchDescription": "The cookies are coming!!",
  "SearchQuery": "cookies*",
  "SearchQueryUrl": "https:\/\/service.us2.sumologic.com\/ui\/index.html#section\/search\/MTljAvmwMA970Cy6bC5Nt2FTCmCfKXIncjx33Ly37BxxH4rnlbQkkTLaAkbF3eTWfgyACUDA0BR7lbeP1Z3cx6ZmKwpC9fapAdf3jkxQMGRpnYbIU73l1Y4JwQwCFZC8",
  "TimeRange": "2016-06-27 16:21:30 PDT - 2016-06-27 16:24:30 PDT",
  "FireTime": "2016-06-27 16:25:17 PDT",
  "AggregateResultsJson": "",
  "RawResultsJson": "[{\"Message\":\"Jun 27 16:23:40 The cookies are on fire. Save the butter\",\"Time\":1467069820000,\"Host\":\"cookienix\",\"Category\":\"linux_apps_logs\",\"Name\":\"\/var\/log\/mysumo.log\",\"Collector\":\"cookienix\"},{\"Message\":\"Jun 27 16:23:37 The cookies are on fire. Save the butter\",\"Time\":1467069817000,\"Host\":\"cookienix\",\"Category\":\"linux_apps_logs\",\"Name\":\"\/var\/log\/mysumo.log\",\"Collector\":\"cookienix\"},{\"Message\":\"Jun 27 16:23:37 The cookies are on fire. Save the butter\",\"Time\":1467069817000,\"Host\":\"cookienix\",\"Category\":\"linux_apps_logs\",\"Name\":\"\/var\/log\/mysumo.log\",\"Collector\":\"cookienix\"}]",
  "NumRawResults": "3"
}

As you can see, the RawResultsJSON has a string value that is an encoded array of JSON objects. If I pull that out and format it, this is the data:

[
  {
    "Message": "Jun 27 16:23:40 The cookies are on fire. Save the butter",
    "Time": 1467069820000,
    "Host": "cookienix",
    "Category": "linux_apps_logs",
    "Name": "/var/log/mysumo.log",
    "Collector": "cookienix"
  },
  {
    "Message": "Jun 27 16:23:37 The cookies are on fire. Save the butter",
    "Time": 1467069817000,
    "Host": "cookienix",
    "Category": "linux_apps_logs",
    "Name": "/var/log/mysumo.log",
    "Collector": "cookienix"
  },
  {
    "Message": "Jun 27 16:23:37 The cookies are on fire. Save the butter",
    "Time": 1467069817000,
    "Host": "cookienix",
    "Category": "linux_apps_logs",
    "Name": "/var/log/mysumo.log",
    "Collector": "cookienix"
  }
]

Great. Now how would I display that in an email? Well, since it is an array with several items, a table with rows and columns to match comes to mind - and I know I can use the Integration Builder to generate the HTML needed to display a table, then we can pass the raw HTML as a property!

After some tinkering and hair pulling, I put together this function:


function generateTable( array ) {

// Skeleton HTML table with three columns
var table = '<table>';
table += '<tr>';
table += '<th align="left">#</th>';
table += '<th align="left">Time</th>';
table += '<th align="left">Message</th>';
table += '</tr>';
table += '';
table += 'TABLEHERE'; // We'll generate the table and replace this value
table += '';
table += '</table>';

var str = '';
var i = 1;

// Loop through and build the table
for( var r in array ) {

str += '<tr>';
str += '<td align="left">' + i + '</td>';
str += '<td align="left">' + getDate( array[r].Time ) + '</td>';
str += '<td align="left">' + array[r].Message + '<br />' +
'Host: ' + array[r].Host + '<br />' +
'Name: ' + array[r].Name + '<br />' +
'Category: ' + array[r].Category +
'</td>';
str += '</tr>';

i++;
}

// Make the replacement
table = table.replace( /TABLEHERE/, str );

return table;

}

 

Great! So what's it look like?

 

Hey! Not bad. Except the centeredness of the Message column makes it rather hard to read. I tinkered with it and Google tells me adding align="left" to the td tag should left-align these columns, which you can see in the function above. When I inspected the source of the email sent out, I found the align attribute was removed from my tags! How rude! I played with adding a class, id and various other attributes but to no avail. Nothing I could do would get my columns to line up like I wanted them.  

Fortunately, our very own Sandra came up with this great piece of work that explains how to use colors in your emails based on an incoming property. The relevant part for us is the use of embedding a <style> tag in the html source. This is actually very powerful as it allows me to override the styling that is sent out from xMod. 

So, I'll just use Sandra's trick, but instead of colors, I'll override the <td> styling. Like so: 

<style> table td, th {
padding-right: 10px;
vertical-align: text-top;
text-align: left;
}
</style>

 

Now, when my email comes in, my log lines are aligned to the left!

This approach is not without its drawbacks. Since the class and id attributes are wiped out we don't have a whole lot of fine control of the formatting, so we have to override the entire <td> tag. Which means it's up to us to then determine the formatting. Also, this means we couldn't style table cells individually; they are all the same. 

 

 

Have more questions? Submit a request

3 Comments

  • 0
    Avatar
    Jeff Mcgroary

    I found this article helpful for generating a dynamic HTML table.   Like you, I found that the generated HTML code was stripped of attributes. i see that you included in your post a CSS style to override the xMatters table defaults.  Where did you place the <style></style> block?   I tried placing it in the generated code, but it appears in the body of the message.  I ended up putting my style overrides in the message design panel using the Source view.  But, I have to do it for each form which uses the code in the shared library which contains our function for generating the dynamic HTML table which kind of defeats the purpose of the using shared code.  I'm looking for a better way to handle this situation.

    Thank you,

    -Jeff.

  • 0
    Avatar
    Travis DePuy

    Hey Jeff! Glad you found it useful. We don't have a mechanism today to do that kind of CSS manipulation, but I'll see about getting a PM created for it. 

    In the mean time, you could have a shared library that would export some CSS like so:

    exports.getCustomCSS = function() {

    return '<style> table td, th { \
    padding-right: 10px; \
    vertical-align: text-top; \
    text-align: left; \
    } \
    </style>';
    }

     

    Then in your scripts:

    var myCSS = require( 'MyLibrary' ).getCustomCSS();

    But yea, you'd need to get that myCSS value into a property, then have that property on the form. Not pretty. 

    I created PM-6505 to track this. 

  • 0
    Avatar
    Jeff Mcgroary

    Hi Travis,

    Thanks for responding to my post.

    I like your idea for handling CSS styles.  As you said, not the prettiest solution but it beats copying and pasting the same styles into half a dozen forms.

     

    Hopefully, there's a more elegant solution somewhere down the road.

     

    Thanks again,

     

    -Jeff

     

Please sign in to leave a comment.
Powered by Zendesk