iframe-based dashboards don’t work in 2017

by Oliver on Thursday, January 5th, 2017.

At $current_employer (unlike $previous_employer where all these problems were sorted out), we have great huge TVs in every room but not consistently useful usage of them. I love seeing big, beautiful dashboards and KPIs visualised everywhere but right now, we just don’t have that in place. No matter, this is part of my mission to improve engineering practices here and I’m happy to tackle it.

The last time I felt I had to do this was back in about 2013. My team was fairly small at 2-3 people including myself, and there was no company-wide dashboarding solution in place. The list of commercial and open source solutions was much smaller than it is today. We ended up using a Mac Mini (initially with Safari, later Chrome) and some tab rotation extension to do the job of rotating between various hard-coded HTML pages I had crafted by hand, which aggregated numerous Graphite graphs into a fixed table structure. Hm.

While there are many solutions to displaying dashboards, collecting and storing the data, actually hosting the infrastructure and what drives the TV still seems a bit fiddly. You could try using the TV’s built-in web browser if it is a smart TV (low-powered, usually no saved settings if you turn the TV off, not enough memory, questionable HTML5 support), Chromecast (not independent from another computer), Raspberry Pi (low-powered, not enough memory), or some other small form-factor PC. The ultimate solution will probably require some common infrastructure to be deployed along the lines of Concerto, which I’ve used before but don’t want to wait for that to be set up yet.

The simplest possible solution is to host a small static HTML file on the machine, load it in the browser and have that page rotate through a hard-coded set of URLs by loading them in an iframe. I came up with this code in a few minutes and hoped it would work:

<body style="margin:0px">
  <iframe id="frame"></iframe>
  <script type="text/javascript">
    function rotateDashboard(urls, refreshPeriod) {
      var frame = document.getElementById("frame");
      frame.src = urls[0];

      // Put the current URL on the back of the queue and set the next refresh
      setTimeout(rotateDashboard, refreshPeriod * 1000, urls, refreshPeriod);

    // Set up iframe
    var frame = document.getElementById("frame");
    frame.height = screen.height;
    frame.width = screen.width;
    frame.style.border = "none";
    frame.seamless = true;

    // Set up metadata
    var xhr = new XMLHttpRequest();
    xhr.onload = function(e) {
      var json = JSON.parse(xhr.responseText);
      var refresh = json.refresh;
      var urls = json.urls;

      rotateDashboard(urls, refresh);

    xhr.open("GET", "https://gist.githubusercontent.com/ohookins/somegisthash/dashboards.json");

For the first couple of locally hosted dashboards and another static website for testing, it worked, but for the first Librato-based dashboard it immediately failed due to the X-Frame-Options header in the response being set to DENY. Not being a frontend-savvy person, I’d only vaguely known of this option but here it actually blocked the entire concept from working.

So, TL;DR – you can’t host rotating dashboards in an iframe, given the security settings most browsers and respectable websites obey in 2017. This is probably well-known to anyone who has done any reasonable amount of web coding in their lives, but to a primarily backend/infrastructure person it was a surprise. So, the Earliest Testable Product in this case needs to be with a tab rotation extension in the browser. You might argue this is simpler, but I was looking forward to maintaining configuration in a flexible manner as you can see in the script above. In any case, by the end of today I’ll have such a system running and the team will start to enjoy the benefits of immediate visibility of critical operational data and KPIs!

Tags: , ,

Thursday, January 5th, 2017 Tech No Comments