FrontPage 

Fuego wiki

Login or create account

flot in 'raw' format

Fuego uses the Javascript 'flot' package to plot data in the Jenkins 
interface. See [[Jenkins Visualization]]

Cogent originally wrote the flot plugin for Jenkins, by adding
the Java wrapper code and javascript in mod.js and CSS in my.css
for the code for plots.

flot is written using jQuery.

The flot plugin consists of:
 * meta-data for building the plugin in maven
 * java classes:
   * "ChartAction" that implements "Action", and
   * "FlotPublisher" that extends the "Recorder" class.
 * 'jelly' code that integrates the flot jquery code into the Jenkins job page HTML output
 * the flot jquery code
 * mod.js and my.css - Fuego's customization to flot to do Fuego's plots

The source for this is in:
 * fuego/frontend-install/plugins/flot-plotter-plugin/src
   * java/flotile/FlotPublisher.java
   * java/flottile/ChartAction.java
   * resources/index.jelly
   * resources/ChartAction/floatingBox.jelly
   * webapp/flot/<flot jquery files>

This is used to create a flot.hpi, which is installed into Jenkins during
the docker container build for Fuego.

Inside the container, this stuff lives in /var/lib/jenkins/plugins/flot:
 * META_INF - maven package infomration
 * WEB_INF/lib/flot.jar - java and resources jar (java archive) file
 * flot/<flot jquery files>



{{{#!YellowBox
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:local="local">

<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/jquery.min.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/jquery.flot.min.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/jquery.flot.navigate.min.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/jquery.flot.symbol.min.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/jquery.flot.selection.min.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/canvas2image.js"></script>
<script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/base64.js"></script>

<link type="text/css" href="${rootURL}/plugin/flot/flot/my.css" rel="stylesheet" />

<div>
  <div id="mod">
    <script language="javascript" type="text/javascript" src="${rootURL}/plugin/flot/flot/mod.js"></script>
  </div>
  <div class="plots"></div>
</div>

</j:jelly>
}}}

The floatingBox.jelly file looks like this:

== Jenkins url notes ==
The base url for Jenkins as configured by Fuego is:
http://localhost:8080/fuego

The URL for a job page is:
http://localhost:8080/fuego/job/bbb.default.Benchmark.Dhrystone/

= flot base =
Here are the files in the flot base:
 * API.TXT - described the jQuery interface to flot for drawing plots
 * FAQ.TXT - answers to frequently asked questions
 * base64.js
 * canvas2image.js
 * excanvas.min.js - min-ified ...
 * jquery.colorhelper.min.js
 * jquery.flot.crosshair.min.js
 * jquery.flot.fillbetween.min.js
 * jquery.flot.image.min.js
 * jquery.flot.navigate.min.js
 * jquery.flot.pie.min.js
 * jquery.flot.resize.min.js
 * jquery.flot.selection.min.js
 * jquery.flot.stack.min.js
 * jquery.flot.symbol.min.js
 * jquery.flot.threshold.min.js
 * jquery.min.js
 * LICENSE.TXT
 * mod.js - Fuego-specific file for drawing Fuego test plots
 * my.css - Fuego-specific file with CSS for Fuego test plots
 * PLUGINS.TXT - describes how to use plugins to flot
 * README.TXT

= Fuego extension =
The HTML on the job page has:
{{{
<div style="float:right">
    <script src="/fuego/plugin/flot/flot/jquery.min.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/jquery.flot.min.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/jquery.flot.navigate.min.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/jquery.flot.symbol.min.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/jquery.flot.selection.min.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/canvas2image.js" language="javascript" type="text/javascript"></script>
    <script src="/fuego/plugin/flot/flot/base64.js" language="javascript" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="/fuego/plugin/flot/flot/my.css" />
    <div>
        <div id="mod">
            <script src="/fuego/plugin/flot/flot/mod.js" language="javascript" type="text/javascript"></script>
        </div>
    <div class="plots">
    </div>
</div>
}}}

This is put there by ChartAction.java using the following "jelly" file:
The source is:
 * fuego/frontend-install/plugins/flot-plotter-plugin/src/main/resources/flotile/ChartAction/floatingBox.jelly

(In general, Jenkins interface glue pieces are described as "jelly")

The mod.js code will populate the <div> that is of class "plots" with the output for this job.


== mod.js - JTA ==
Here are teh functions in mod.js script for JTA:

 * jQuery(document).ready(function () {
     * sets up all kinds of variables
        * testname, testinfo, tests, plots, fws, devices, ...
        * options (plot options: legend, colors, etc.)
        * options_f (plot options: legend, grid, colors, etc.)
 * getSuitesInfo(series)
 * getBuildsInfo(series)
 * jQuery.ajax
 * jQuery.ajax
 * (main:)
 * MoreInfo_PopUp
 * hand_o
 * drawChoices
 * showTooltip()
 * plotGraphs()
 * onDataReceived(series)

Data files used:
 * tests.info - global list of all metrics
 * testname.info.json - list of data, by firmware

== mod.js - 1.1 ==
Here are the functions in the mod.js script for Fuego 1.0

 * jQuery(document).ready(function () {
     * sets up all kinds of variables
 * getSuitesInfo(series)
   * read from the metric.json file
   * populate the <div class="plots"> with the placeholder plot divs for each metric in the file
 * getBuildsInfo(series)
   * read from the <testname>.info.json file
   * build a set of parallel data structures for plotting
 * jQuery.ajax - load metrics.json data from the log directory
 * jQuery.ajax - load the <testname>.info.json data from the log directory
 * (main:)
   * for each metric: do
     * get the placeholder DOM object for this metric/plot
     jQuery.ajax - load the <testname>.<metric>.json file
 * MoreInfo_PopUp
 * hand_o
 * drawChoices
 * showTooltip()
 * plotGraphs()
 * onDataReceived(series)
   * read from <testname>.<metric>.json file
   * add checkbox for each device, for this metric's plot
   * add checkbox for each firmware, for this metric's plot

Here are the files used by mod.js to get the plot data:
 * <testname>.<metric>.json (ex: Benchmark.Dhrystone.Dhrystone.json)
   * this has the metadata for the "Dhrystone" metric for all tests that have been run
     * 
 * <testname>.info.json (ex: Benchmark.Dhryston.info.json)
   * this has the actual data for all metrics, for all tests that have been run
   * the data is in flot data format
     * the fields are pre-formatted to pass to the flot plot() function, in mod.js

Here's are some example files used:
metrics.json (for Benchmark.Dhrystone):
 * is a List of metrics for this test:

{{{#!YellowBox
{
	"Dhrystone": ["Dhrystone"]
}
}}}

Benchmark.Dhrystone.info.json
 * has metadata about each run
 * has an entry for each 'device' (board)

{{{#!YellowBox
[
  {"device": "beaglebone",
   "info": [
      ["1", "1", "2", "3", "5", "6", "7"],
      ["3.8.13-bone50", "3.8.13-bone50", "3.8.13-bone50", "3.8.13-bone50", "3.8.13-bone50", "3.8.13-bone50", "3.8.13-bone50"],
      ["fake", "fake", "fake", "fake", "fake", "fake", "fake"]
   ]
  }
]
}}}
 * info seems to consist of parallel arrays of: build_number, firmware, and ?? per run

Benchmark.Dhrystone.Dhrystone.json
 * has data for each run, for this metric
 * this is in 'flot' format

{{{#!YellowBox
[
  {"data": [
       ["5", 1111111.1], ["6", 1111111.1], ["7", 1000000.0]
    ],
   "label": "beaglebone-default-Dhrystone.Dhrystone",
   "points": {"symbol": "circle"}
  },
  {"data": [
       ["5", 1.0], ["6", 1.0], ["7", 1.0]
    ],
   "label": "beaglebone-default-Dhrystone.Dhrystone.ref",
   "points": {"symbol": "cross"}},

  {"data": [
       ["1", 1098901.1], ["2", 1111111.1], ["3", 1111111.1]
    ],
   "label": "beaglebone-100M-Dhrystone.Dhrystone",
   "points": {"symbol": "circle"}
  },
  {"data": [
       ["1", 1.0], ["2", 1.0], ["3", 1.0]
    ], 
   "label": "beaglebone-100M-Dhrystone.Dhrystone.ref",
   "points": {"symbol": "cross"}
  },

  {"data": [
       ["1", 11111111.0]
    ],
   "label": "docker-100M-Dhrystone.Dhrystone",
   "points": {"symbol": "circle"}},
  {"data": [
       ["1", 1.0]
     ], 
    "label": "docker-100M-Dhrystone.Dhrystone.ref",
    "points": {"symbol": "cross"}
  }
]
}}}








= mod.js - 1.2 ==
Here are the files used by the mod.js to get the plot data:
 * results.json

jQuery(location) URL parts is put into array localurl
and testtype (e.g. Functional or Benchmark) and testsuite (e.g. Dhrystone)
are extracted from it.

A hidden tooltip object is created and added to the page body.

Functions:
 * jQuery(document).ready(function () {
   * does lots of variable setup
   * note that everything in the file is inside this anonymous function
 * jQuery - div tooltip css(...).appendTo("body".fadeIn(200)
   * add some parameters for tooltip divs
 * show_upperplot_tooltip()
   * handle logic for making tooltips appear and disapper
 * handle_lowerplot_zoom()
   * handle zooming in lowerplot (presumably)
 * replot_test_set()
   * redraw a plot (set as the click handler for a label referencing that plot)
 * plot_test_set()
   * 
 * json_updated(series)
   * decide what kind of output to show (tables, plots, etc.)
 * display_table(series)
   * append stuff to ".plot'
   * generate a table per (board, spec, kernel, test_set, test_case)
     * each table has header, then:
       * row per build_number, with
           * build number, status, start time, duration
 * plot_all_test_sets(series)
   * create parallel arrays of results data
   * add a container div for each test_set
     * with upper and lower plots, with test_set ids to match
     * with a legend_container
       * for each label, add a checkbox
     * add callbacks for tooltips on upper plot, zoom on lower plot, and test replot on label checkbox click
     * plot that test_set (both lower and upper)
     * add upper_plot to a list of plots
 * jQuery.ajax(... /results.json ... success: json_updated)
   * load the results.json file, and call json_updated

Thread of execution:
 * document.ready
   * jQuery tooltip css append to body
   * jQuery.ajax results.json ...
     * json_updated
       * display_table
       * plot_all_test_sets
          * plot_test_set


Here are some example files:

results.json (Fuego 1.1-pre-April)
{{{#!YellowBox
{"docker-default-3.19.0-47-generic-Whetstone-Whetstone":
    {"groupname": "Whetstone",
        "platform": "fake",
        "board": "docker",
        "timestamp": ["2017-05-02_00-31-17"],
        "test": "Whetstone",
        "ref": ["20"],
        "data": ["5000.0"],
        "spec": "default",
        "fwver": "3.19.0-47-generic"
    },
  "bbb-default-3.8.13-bone50-Whetstone-Whetstone":
  {"groupname": "Whetstone",
      "platform": "fake",
      "board": "bbb",
      "timestamp": ["2017-05-02_00-14-59", "2017-05-02_19-50-06"],
      "test": "Whetstone",
      "ref": ["20", "20"],
      "data": ["153.8", "153.8"],
      "spec": "default",
      "fwver": "3.8.13-bone50"
  }
}
}}}


Benchmark.Dhrystone results.json (Fuego 1.2-pre-August)
{{{#!YellowBox
{
    "bbb-default-3.8.13-bone50-default-Dhrystone": {
        "board": "bbb",
        "build_number": [
            "3",
            "4"
        ],
        "duration_ms": [
            18179,
            19179
        ],
        "kernel_version": "3.8.13-bone50",
        "measurements": {
            "Score": {
                "measure": [
                    1111111.1,
                    1111111.1
                ],
                "status": [
                    "PASS",
                    "PASS"
                ]
            }
        },
        "start_time": [
            "1503951135821",
            "1503951195821"
        ],
        "status": [
            "PASS",
            "PASS"
        ],
        "test_case": "Dhrystone",
        "test_plan": "none",
        "test_set": "default",
        "test_spec": "default",
        "toolchain": "emdebian-armhf"
    },
    "min1-100M-4.4.0-92-generic-default-Dhrystone": {
        "board": "min1",
        "build_number": [
            "2"
        ],
        "duration_ms": [
            59990
        ],
        "kernel_version": "4.4.0-92-generic",
        "measurements": {
            "Score": {
                "measure": [
                    2325581.5
                ],
                "status": [
                    "PASS"
                ]
            }
        },
        "start_time": [
            "1503598154010"
        ],
        "status": [
            "PASS"
        ],
        "test_case": "Dhrystone",
        "test_plan": "none",
        "test_set": "default",
        "test_spec": "100M",
        "toolchain": "x86_64"
    },
    "test_name": "Benchmark.Dhrystone"
}
}}}

= flot API =
Per plot, flot expects:
 * data = a list of series
   * series = a raw_data or an object (dictionary with series attributes)
     * series attributes = label, points, data
     * series data = list of tuples
       * tuples = [x,y]

example:
{{{
[ { label: "Foo", data: [ [10, 1], [17, -14], [30, 5] ] },
  { label: "Bar", data: [ [11, 13], [19, 11], [30, -7] ] }
]
}}}

Also, you can specify a config per plot, with lots of details about
how to draw the plot.  See https://github.com/flot/flot/blob/master/API.md



TBWiki engine 1.8.3 by Tim Bird