flot
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>
<?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 [edit section]
The base url for Jenkins as configured by Fuego is: http://localhost:8080/fuegoThe URL for a job page is: http://localhost:8080/fuego/job/bbb.default.Benchmark.Dhrystone/
flot base [edit section]
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 [edit section]
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 [edit section]
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.)
- sets up all kinds of variables
- 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 [edit section]
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
- for each metric: do
- 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:
{ "Dhrystone": ["Dhrystone"] }
Benchmark.Dhrystone.info.json
- has metadata about each run
- has an entry for each 'device' (board)
[ {"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
[ {"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 [edit section]
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
- row per build_number, with
- each table has header, then:
- 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
- json_updated
Here are some example files:
results.json (Fuego 1.1-pre-April)
{"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)
{ "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 [edit section]
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]
- series = a raw_data or an object (dictionary with series attributes)
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