Ad Widget

Collapse

SVG in maps and graphs

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • limo
    Senior Member
    • Dec 2004
    • 192

    #1

    SVG in maps and graphs

    Hi to all,
    I already opened this some time ago but I think now it is time to realize this relative easily.

    SVG is pure xml, so easy to make templates with macros (see example).

    So creating svg map from php is really easy. Get template from DB, expand macros and embed it into html. Visualisation is on client so server does not need to hard work with bitmaps.

    This could be maybe totaly external thing to zabbix. It is enaught to use zabbix php function to expand macros.

    What do you thing ?

    Nice with this design is, that there are no limits in map. You can make box as big as some value. Or you can do some gauge showing percents. Everything is in xml code.

    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
    <!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
    <svg
       id="svg602"
       sodipodi:version="0.34"
       xmlns="http://www.w3.org/2000/svg"
       xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       width="210mm"
       height="297mm"
       xml:space="preserve"
       sodipodi:docbase="/tmp"
       sodipodi:docname="/tmp/test.svg"><defs
       id="defs604" /><sodipodi:namedview
       id="base" /><rect
       style="font-size:12;fill:#808080;fill-rule:evenodd;stroke-width:1;"
       id="rect605"
       width="123.404022"
       height="164.538742"
       x="106.264587"
       y="239.952286" /><rect
       style="font-size:12;fill:#808080;fill-rule:evenodd;stroke-width:1;"
       id="rect606"
       width="113.120392"
       height="195.389709"
       x="356.500549"
       y="555.318176" /><rect
       style="font-size:12;fill:#808080;fill-rule:evenodd;stroke-width:1;"
       id="rect607"
       width="75.4136047"
       height="78.8414001"
       x="503.899811"
       y="137.115601" /><text
       style="fill:black;stroke:none;font-family:helvetica;font-style:normal;font-weight:normal;font-size:12px;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
       x="123.404037"
       y="435.34198"
       id="text608"><tspan
       id="tspan609">host1 - {host1:item.last(0)}</tspan></text><text
       style="fill:black;stroke:none;font-family:helvetica;font-style:normal;font-weight:normal;font-size:12px;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
       x="534.750854"
       y="246.80806"
       id="text611"><tspan
       id="tspan612">host2 - {host2:item2.last(1)}</tspan></text><text
       style="fill:black;stroke:none;font-family:helvetica;font-style:normal;font-weight:normal;font-size:12px;fill-opacity:1;stroke-opacity:1;stroke-width:1pt;stroke-linejoin:miter;stroke-linecap:butt;"
       x="387.351562"
       y="774.703064"
       id="text614"><tspan
       id="tspan615">host3 - {host3:item2.last(1)}</tspan></text></svg>
  • Alexei
    Founder, CEO
    Zabbix Certified Trainer
    Zabbix Certified SpecialistZabbix Certified Professional
    • Sep 2004
    • 5654

    #2
    Do Firefox and MS Explorer support SVG out-of-the box?
    Alexei Vladishev
    Creator of Zabbix, Product manager
    New York | Tokyo | Riga
    My Twitter

    Comment

    • limo
      Senior Member
      • Dec 2004
      • 192

      #3
      Yes and no

      Mozilla SHOULD support native svg in windows and linux. Implementation is not full but it is really enaught for use with zabbix.

      IE6 and IE7 has support with adobe svg plugin (it SHOULD be automaticaly instaled when you install acrobat reader)

      Yes, support of svg can be limiting factor now. But I think most of admins has either mozilla or acrobat reader instaled

      Comment

      • Alexei
        Founder, CEO
        Zabbix Certified Trainer
        Zabbix Certified SpecialistZabbix Certified Professional
        • Sep 2004
        • 5654

        #4
        Mozilla I use (1.5.0.11) does not support SVG.

        I keep SVG in mind, I just cannot make a decision of switching everything to SVG due to a limited support of SVG.
        Alexei Vladishev
        Creator of Zabbix, Product manager
        New York | Tokyo | Riga
        My Twitter

        Comment

        • limo
          Senior Member
          • Dec 2004
          • 192

          #5
          As I said, SVG is supported in mozilla. 1.5 has native support already. It is missing only in 1.0.x versions. But you cannot look to pages which are made for svg plugin implementation from Adobe.. It looks like unsopported.

          Look here: http://developer.mozilla.org/en/docs/SVG_in_Firefox_1.5

          And here: http://www.croczilla.com/svg/samples/

          and you should see svg in action..

          Comment

          • Alexei
            Founder, CEO
            Zabbix Certified Trainer
            Zabbix Certified SpecialistZabbix Certified Professional
            • Sep 2004
            • 5654

            #6
            Indeed it works now. I must have been used wrong SVG samples.
            Alexei Vladishev
            Creator of Zabbix, Product manager
            New York | Tokyo | Riga
            My Twitter

            Comment

            • Vince2
              Member
              • Oct 2006
              • 40

              #7
              SVG could also be used for graphs :
              The Internet privacy company that empowers you to seamlessly take control of your personal information online, without any tradeoffs.

              Comment

              • quekky
                Junior Member
                • Nov 2004
                • 8

                #8
                agree on using SVG. I use pfsense (clone of mono) and it uses realtime SVG with some very simple scripting

                PHP Code:
                <?xml version="1.0" encoding="iso-8859-1"?>
                <svg width="100%" height="100%" viewBox="0 0 200 100" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
                  <g id="graph">
                .....
                  </g>
                  <script type="text/ecmascript">
                    <![CDATA[

                /**
                 * getURL is a proprietary Adobe function, but it's simplicity has made it very
                 * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
                 */
                if (typeof getURL == 'undefined') {
                  getURL = function(url, callback) {
                    if (!url)
                      throw 'No URL for getURL';

                    try {
                      if (typeof callback.operationComplete == 'function')
                        callback = callback.operationComplete;
                    } catch (e) {}
                    if (typeof callback != 'function')
                      throw 'No callback function for getURL';

                    var http_request = null;
                    if (typeof XMLHttpRequest != 'undefined') {
                      http_request = new XMLHttpRequest();
                    }
                    else if (typeof ActiveXObject != 'undefined') {
                      try {
                        http_request = new ActiveXObject('Msxml2.XMLHTTP');
                      } catch (e) {
                        try {
                          http_request = new ActiveXObject('Microsoft.XMLHTTP');
                        } catch (e) {}
                      }
                    }
                    if (!http_request)
                      throw 'Both getURL and XMLHttpRequest are undefined';

                    http_request.onreadystatechange = function() {
                      if (http_request.readyState == 4) {
                        callback( { success : true,
                                    content : http_request.responseText,
                                    contentType : http_request.getResponseHeader("Content-Type") } );
                      }
                    }
                    http_request.open('GET', url, true);
                    http_request.send(null);
                  }
                }

                var SVGDoc = null;
                var last_ifin = 0;
                var last_ifout = 0;
                var last_ugmt = 0;
                var max = 0;
                var plot_in = new Array();
                var plot_out = new Array();

                var max_num_points = 120;  // maximum number of plot data points
                var step = 200 / max_num_points ;
                var unit = 'bits';
                var scale_type = 'up';

                function init(evt) {
                  SVGDoc = evt.target.ownerDocument;
                  SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
                  SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);

                  fetch_data();
                }

                function switch_unit(event)
                {
                  SVGDoc.getElementById('switch_unit').firstChild.data = 'Switch to ' + unit + '/s';
                  unit = (unit == 'bits') ? 'bytes' : 'bits';
                }

                function switch_scale(event)
                {
                  scale_type = (scale_type == 'up') ? 'follow' : 'up';
                  SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')';
                }

                function fetch_data() {
                  getURL('ifstats.php?if=hme0', plot_data);
                }

                function plot_data(obj) {
                  // Show datetimelegend
                  var now = new Date();
                  var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + 
                    LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
                  SVGDoc.getElementById('datetime').firstChild.data = datetime;

                  if (!obj.success)
                    return handle_error();  // getURL failed to get data

                  var t = obj.content.split("|");
                  var ugmt = parseFloat(t[0]);  // ugmt is an unixtimestamp style
                  var ifin = parseInt(t[1]);    // number of bytes received by the interface
                  var ifout = parseInt(t[2]);   // number of bytes sent by the interface
                  var scale;

                  if (!isNumber(ifin) || !isNumber(ifout))
                    return handle_error();

                  var diff_ugmt  = ugmt - last_ugmt;
                  var diff_ifin  = ifin - last_ifin;
                  var diff_ifout = ifout - last_ifout;

                  if (diff_ugmt == 0)
                    diff_ugmt = 1;  /* avoid division by zero */

                  last_ugmt = ugmt;
                  last_ifin = ifin;
                  last_ifout = ifout;
                  
                  switch (plot_in.length) {
                      case 0:
                          SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
                        plot_in[0] = diff_ifin / diff_ugmt;
                        plot_out[0] = diff_ifout / diff_ugmt;
                        setTimeout('fetch_data()',1000);
                        return;
                    case 1:
                        SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
                        break;
                    case max_num_points:
                        // shift plot to left if the maximum number of plot points has been reached
                        var i = 0;
                        while (i < max_num_points) {
                          plot_in[i] = plot_in[i+1];
                          plot_out[i] = plot_out[++i];
                        }
                        plot_in.length--;
                        plot_out.length--;
                  }

                  plot_in[plot_in.length] = diff_ifin / diff_ugmt;
                  plot_out[plot_out.length]= diff_ifout / diff_ugmt;
                  var index_plot = plot_in.length - 1;

                  SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
                  SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);

                  /* determine peak for sensible scaling */
                  if (scale_type == 'up') {
                    if (plot_in[index_plot] > max)
                      max = plot_in[index_plot];
                    if (plot_out[index_plot] > max)
                      max = plot_out[index_plot];
                  }
                  else if (scale_type == 'follow') {
                    i = 0;
                    max = 0;
                    while (i < plot_in.length) {
                      if (plot_in[i] > max)
                        max = plot_in[i];
                      if (plot_out[i] > max)
                        max = plot_out[i];
                      i++;
                    }
                  }

                  var rmax;  // max, rounded up

                  if (unit == 'bits') {
                    /* round up max, such that
                         100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
                    rmax = 12500;
                    i = 0;
                    while (max > rmax) {
                      i++;
                      if (i && (i % 4 == 0))
                        rmax *= 1.25;
                      else
                        rmax *= 2;
                    }
                  } else {
                    /* round up max, such that
                         10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */
                    rmax = 10240;
                    i = 0;
                    while (max > rmax) {
                      i++;
                      if (i && (i % 4 == 0))
                        rmax *= 1.25;
                      else
                        rmax *= 2;
                      
                      if (i == 8)
                        rmax *= 1.024;
                    }
                  }

                  scale = 100 / rmax;

                  /* change labels accordingly */
                  SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit);
                  SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit);
                  SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit);

                  var path_in = "M 0 " + (100 - (plot_in[0] * scale));
                  var path_out = "M 0 " + (100 - (plot_out[0] * scale));
                  for (i = 1; i < plot_in.length; i++)
                  {
                    var x = step * i;
                    var y_in = 100 - (plot_in[i] * scale);
                    var y_out = 100 - (plot_out[i] * scale);
                    path_in += " L" + x + " " + y_in;
                    path_out += " L" + x + " " + y_out;
                  }

                  SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
                  SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
                  SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);

                  setTimeout('fetch_data()',1000);
                }

                function handle_error() {
                  SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
                  setTimeout('fetch_data()',1000);
                }

                function isNumber(a) {
                  return typeof a == 'number' && isFinite(a);
                }

                function formatSpeed(speed, unit) {
                  if (unit == 'bits')
                    return formatSpeedBits(speed);
                  if (unit == 'bytes')
                    return formatSpeedBytes(speed);
                }

                function formatSpeedBits(speed) {
                  // format speed in bits/sec, input: bytes/sec
                  if (speed < 125000)
                    return Math.round(speed / 125) + " Kbps";
                  if (speed < 125000000)
                    return Math.round(speed / 1250)/100 + " Mbps";
                  // else
                  return Math.round(speed / 1250000)/100 + " Gbps";  /* wow! */
                }

                function formatSpeedBytes(speed) {
                  // format speed in bytes/sec, input:  bytes/sec
                  if (speed < 1048576)
                    return Math.round(speed / 10.24)/100 + " KB/s";
                  if (speed < 1073741824)
                    return Math.round(speed / 10485.76)/100 + " MB/s";
                  // else
                  return Math.round(speed / 10737418.24)/100 + " GB/s";  /* wow! */
                }

                function LZ(x) {
                  return (x < 0 || x > 9 ? "" : "0") + x;
                }

                    ]]>
                  </script>
                </svg>
                Last edited by quekky; 12-05-2007, 07:07.

                Comment

                Working...