flot in split format
Fuego uses the Javascript 'flot' package to plot data in the Jenkins
interface. See Jenkins Visualization
|
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.
|
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.
|
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 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>
|
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.
|
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>
|
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>
|
<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" />
|
<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>
|
<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>
}}}
|
</j:jelly>
}}}
|
The floatingBox.jelly file looks like this:
|
The floatingBox.jelly file looks like this:
|
http://localhost:8080/fuego
|
== 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/
|
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
|
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")
|
(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.
|
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)
|
* 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
|
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
|
* 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 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:
|
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)
|
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
|
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", 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"}
}
]
}}}
|
{"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.
|
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.
|
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
|
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
|
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:
|
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"
}
}
}}}
|
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"
}
}}}
|
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] ] }
]
}}}
|
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
|
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
|
|