summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2015-02-06 12:44:49 +0000
committerKeith Bostic <keith@wiredtiger.com>2015-02-06 12:44:49 +0000
commitf499b8edcdaa71d9f5964b946f8aa443658664e6 (patch)
treed6c94c387cae20aeecd3fd09eb52af4924f73ffb /tools
parent850ef3b0333b446bc6cf2103bc0fc189e91b679e (diff)
downloadmongo-f499b8edcdaa71d9f5964b946f8aa443658664e6.tar.gz
Add wtperf_stats back into the tree.
Diffstat (limited to 'tools')
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS16
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt24
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py547
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/README.rst134
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README20
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/__init__.py30
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py118
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py96
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/lineChart.py111
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py125
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py153
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py101
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py93
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py104
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/pieChart.py125
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/scatterChart.py137
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py112
-rw-r--r--tools/wtperf_stats/3rdparty/nvd3/translator.py71
-rw-r--r--tools/wtperf_stats/wt_nvd3_util.py57
-rw-r--r--tools/wtperf_stats/wtperf_stats.py177
20 files changed, 2351 insertions, 0 deletions
diff --git a/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS b/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS
new file mode 100644
index 00000000000..17d06bec646
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/CONTRIBUTORS
@@ -0,0 +1,16 @@
+areski (Areski Belaid)
+shrenik (Shrenik Patel)
+DZPM (David Arcos)
+goulu (Philippe Guglielmetti)
+jordanvg
+RodrigoPrior (Rodrigo Prior)
+DanMeakin
+nzjrs (John Stowers)
+RaD (Ruslan Popov)
+cmorgan (Chris Morgan)
+imom0
+kbsali (Kevin Saliou)
+zebulon2
+bevanj
+frewie
+agorrod
diff --git a/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt b/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt
new file mode 100644
index 00000000000..1add6249e57
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/MIT-LICENSE.txt
@@ -0,0 +1,24 @@
+The MIT License (MIT)
+
+Python-nvd3
+
+Copyright (c) 2013 Arezqui Belaid <areski@gmail.com> and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py b/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py
new file mode 100644
index 00000000000..52cbf168ddc
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/NVD3Chart.py
@@ -0,0 +1,547 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from optparse import OptionParser
+from string import Template
+import json
+
+template_content_nvd3 = """
+$container
+$jschart
+"""
+
+template_page_nvd3 = """
+<!DOCTYPE html>
+<html lang="en">
+<head>
+$header
+</head>
+<body>
+%s
+</body>
+""" % template_content_nvd3
+
+
+def stab(tab=1):
+ """
+ create space tabulation
+ """
+ return ' ' * 4 * tab
+
+
+class NVD3Chart:
+ """
+ NVD3Chart Base class
+
+ **Attributes**:
+
+ * ``axislist`` - All X, Y axis list
+ * ``charttooltip_dateformat`` - date fromat for tooltip if x-axis is in date format
+ * ``charttooltip`` - Custom tooltip string
+ * ``color_category`` - Defien color category (eg. category10, category20, category20c)
+ * ``color_list`` - used by pieChart (eg. ['red', 'blue', 'orange'])
+ * ``container`` - Place for graph
+ * ``containerheader`` - Header for javascript code
+ * ``count`` - chart count
+ * ``custom_tooltip_flag`` - False / True
+ * ``d3_select_extra`` -
+ * ``date_flag`` - x-axis contain date format or not
+ * ``dateformat`` - see https://github.com/mbostock/d3/wiki/Time-Formatting
+ * ``header_css`` - False / True
+ * ``header_js`` - Custom tooltip string
+ * ``height`` - Set graph height
+ * ``htmlcontent`` - Contain the htmloutput
+ * ``htmlheader`` - Contain the html header
+ * ``jschart`` - Javascript code as string
+ * ``margin_bottom`` - set the bottom margin
+ * ``margin_left`` - set the left margin
+ * ``margin_right`` - set the right margin
+ * ``margin_top`` - set the top margin
+ * ``model`` - set the model (ex. pieChart, LineWithFocusChart, MultiBarChart)
+ * ``resize`` - False / True
+ * ``series`` - Series are list of data that will be plotted
+ * ``stacked`` - False / True
+ * ``style`` - Special style
+ * ``template_page_nvd3`` - template variable
+ * ``width`` - Set graph width
+ * ``x_axis_date`` - False / True
+ * ``show_legend`` - False / True
+ * ``show_labels`` - False / True
+ * ``assets_directory`` directory holding the assets (./bower_components/)
+ """
+ count = 0
+ dateformat = '%x'
+ series = []
+ axislist = {}
+ style = ''
+ htmlcontent = ''
+ htmlheader = ''
+ height = None
+ width = None
+ margin_bottom = None
+ margin_left = None
+ margin_right = None
+ margin_top = None
+ model = ''
+ d3_select_extra = ''
+ x_axis_date = False
+ resize = False
+ stacked = False
+ template_page_nvd3 = None
+ container = None
+ containerheader = ''
+ jschart = None
+ custom_tooltip_flag = False
+ date_flag = False
+ charttooltip = ''
+ tooltip_condition_string = ''
+ color_category = 'category10' # category10, category20, category20c
+ color_list = [] # for pie chart
+ tag_script_js = True
+ charttooltip_dateformat = None
+ x_axis_format = ''
+ show_legend = True
+ show_labels = True
+ assets_directory = './bower_components/'
+
+ def __init__(self, **kwargs):
+ """
+ Constructor
+ """
+ #set the model
+ self.model = self.__class__.__name__
+
+ #Init Data
+ self.series = []
+ self.axislist = {}
+ self.template_page_nvd3 = Template(template_page_nvd3)
+ self.template_content_nvd3 = Template(template_content_nvd3)
+ self.charttooltip_dateformat = '%d %b %Y'
+
+ self.name = kwargs.get('name', self.model)
+ self.jquery_on_ready = kwargs.get('jquery_on_ready', False)
+ self.color_category = kwargs.get('color_category', None)
+ self.color_list = kwargs.get('color_list', None)
+ self.margin_bottom = kwargs.get('margin_bottom', 20)
+ self.margin_left = kwargs.get('margin_left', 60)
+ self.margin_right = kwargs.get('margin_right', 60)
+ self.margin_top = kwargs.get('margin_top', 30)
+ self.stacked = kwargs.get('stacked', False)
+ self.resize = kwargs.get('resize', False)
+ self.show_legend = kwargs.get('show_legend', True)
+ self.show_labels = kwargs.get('show_labels', True)
+ self.tag_script_js = kwargs.get('tag_script_js', True)
+ self.chart_attr = kwargs.get("chart_attr", {})
+ self.assets_directory = kwargs.get('assets_directory', './bower_components/')
+
+ #CDN http://cdnjs.com/libraries/nvd3/ needs to make sure it's up to date
+ self.header_css = [
+ '<link href="%s" rel="stylesheet">\n' % h for h in
+ (
+ self.assets_directory + 'nvd3/src/nv.d3.css',
+ )
+ ]
+
+ self.header_js = [
+ '<script src="%s"></script>\n' % h for h in
+ (
+ self.assets_directory + 'd3/d3.min.js',
+ self.assets_directory + 'nvd3/nv.d3.min.js'
+ )
+ ]
+
+ def add_serie(self, y, x, name=None, extra={}, **kwargs):
+ """
+ add serie - Series are list of data that will be plotted
+ y {1, 2, 3, 4, 5} / x {1, 2, 3, 4, 5}
+
+ **Attributes**:
+
+ * ``name`` - set Serie name
+ * ``x`` - x-axis data
+ * ``y`` - y-axis data
+
+ kwargs:
+
+ * ``shape`` - for scatterChart, you can set different shapes (circle, triangle etc...)
+ * ``size`` - for scatterChart, you can set size of different shapes
+ * ``type`` - for multiChart, type should be bar
+ * ``bar`` - to display bars in Chart
+ * ``color_list`` - define list of colors which will be used by pieChart
+ * ``color`` - set axis color
+ * ``disabled`` -
+
+ extra:
+
+ * ``tooltip`` - set tooltip flag
+ * ``date_format`` - set date_format for tooltip if x-axis is in date format
+
+ """
+ if not name:
+ name = "Serie %d" % (len(self.series) + 1)
+
+ # For scatterChart shape & size fields are added in serie
+ if 'shape' in kwargs or 'size' in kwargs:
+ csize = kwargs.get('size', 1)
+ cshape = kwargs.get('shape', 'circle')
+
+ serie = [{
+ 'x': x[i],
+ 'y': y,
+ 'shape': cshape,
+ 'size': csize[i] if isinstance(csize, list) else csize
+ } for i, y in enumerate(y)]
+ else:
+ if self.model == 'pieChart':
+ serie = [{'label': x[i], 'value': y} for i, y in enumerate(y)]
+ elif self.model == 'linePlusBarWithFocusChart':
+ serie = [[x[i], y] for i, y in enumerate(y)]
+ else:
+ serie = [{'x': x[i], 'y': y} for i, y in enumerate(y)]
+
+ data_keyvalue = {'values': serie, 'key': name}
+
+ #multiChart
+ #Histogram type='bar' for the series
+ if 'type' in kwargs and kwargs['type']:
+ data_keyvalue['type'] = kwargs['type']
+
+ if self.model == 'pieChart':
+ if 'color_list' in extra and extra['color_list']:
+ self.color_list = extra['color_list']
+
+ #Define on which Y axis the serie is related
+ #a chart can have 2 Y axis, left and right, by default only one Y Axis is used
+ if 'yaxis' in kwargs and kwargs['yaxis']:
+ data_keyvalue['yAxis'] = kwargs['yaxis']
+ else:
+ if self.model != 'pieChart' and self.model != 'linePlusBarWithFocusChart':
+ data_keyvalue['yAxis'] = '1'
+
+ if 'bar' in kwargs and kwargs['bar']:
+ data_keyvalue['bar'] = 'true'
+
+ if 'disabled' in kwargs and kwargs['disabled']:
+ data_keyvalue['disabled'] = 'true'
+
+ if 'color' in extra and extra['color']:
+ data_keyvalue['color'] = extra['color']
+
+ if extra.get('date_format'):
+ self.charttooltip_dateformat = extra['date_format']
+
+ if extra.get('tooltip'):
+ self.custom_tooltip_flag = True
+
+ if self.model != 'pieChart':
+ _start = extra['tooltip']['y_start']
+ _end = extra['tooltip']['y_end']
+ _start = ("'" + str(_start) + "' + ") if _start else ''
+ _end = (" + '" + str(_end) + "'") if _end else ''
+
+ if self.model == 'linePlusBarChart' or self.model == 'linePlusBarWithFocusChart':
+ self.tooltip_condition_string += stab(3) + "if(key.indexOf('" + name + "') > -1 ){\n" +\
+ stab(4) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\
+ stab(3) + "}\n"
+ elif self.model == 'cumulativeLineChart':
+ self.tooltip_condition_string += stab(3) + "if(key == '" + name + "'){\n" +\
+ stab(4) + "var y = " + _start + " String(e) " + _end + ";\n" +\
+ stab(3) + "}\n"
+ else:
+ self.tooltip_condition_string += stab(3) + "if(key == '" + name + "'){\n" +\
+ stab(4) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\
+ stab(3) + "}\n"
+
+ if self.model == 'pieChart':
+ _start = extra['tooltip']['y_start']
+ _end = extra['tooltip']['y_end']
+ _start = ("'" + str(_start) + "' + ") if _start else ''
+ _end = (" + '" + str(_end) + "'") if _end else ''
+ self.tooltip_condition_string += \
+ "var y = " + _start + " String(y) " + _end + ";\n"
+
+ self.series.append(data_keyvalue)
+
+ def set_graph_height(self, height):
+ """Set Graph height"""
+ self.height = str(height)
+
+ def set_graph_width(self, width):
+ """Set Graph width"""
+ self.width = str(width)
+
+ def set_containerheader(self, containerheader):
+ """Set containerheader"""
+ self.containerheader = containerheader
+
+ def set_date_flag(self, date_flag=False):
+ """Set date falg"""
+ self.date_flag = date_flag
+
+ def set_custom_tooltip_flag(self, custom_tooltip_flag):
+ """Set custom_tooltip_flag & date_flag"""
+ self.custom_tooltip_flag = custom_tooltip_flag
+
+ def __str__(self):
+ """return htmlcontent"""
+ self.buildhtml()
+ return self.htmlcontent
+
+ def buildcontent(self):
+ """Build HTML content only, no header or body tags. To be useful this
+ will usually require the attribute `juqery_on_ready` to be set which
+ will wrap the js in $(function(){<regular_js>};)
+ """
+ self.buildcontainer()
+ self.buildjschart()
+ self.htmlcontent = self.template_content_nvd3.substitute(container=self.container,
+ jschart=self.jschart)
+
+ def buildhtml(self):
+ """Build the HTML page
+ Create the htmlheader with css / js
+ Create html page
+ Add Js code for nvd3
+ """
+ self.buildhtmlheader()
+ self.buildcontainer()
+ self.buildjschart()
+
+ self.htmlcontent = self.template_page_nvd3.substitute(header=self.htmlheader,
+ container=self.container,
+ jschart=self.jschart)
+
+ def buildhtmlheader(self):
+ """generate HTML header content"""
+ self.htmlheader = ''
+ for css in self.header_css:
+ self.htmlheader += css
+ for js in self.header_js:
+ self.htmlheader += js
+
+ def buildcontainer(self):
+ """generate HTML div"""
+ self.container = self.containerheader
+ #Create SVG div with style
+ if self.width:
+ if self.width[-1] != '%':
+ self.style += 'width:%spx;' % self.width
+ else:
+ self.style += 'width:%s;' % self.width
+ if self.height:
+ if self.height[-1] != '%':
+ self.style += 'height:%spx;' % self.height
+ else:
+ self.style += 'height:%s;' % self.height
+ if self.style:
+ self.style = 'style="%s"' % self.style
+
+ self.container += '<div id="%s"><svg %s></svg></div>\n' % (self.name, self.style)
+
+ def build_custom_tooltip(self):
+ """generate custom tooltip for the chart"""
+ if self.custom_tooltip_flag:
+ if not self.date_flag:
+ if self.model == 'pieChart':
+ self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \
+ stab(3) + "var x = String(key);\n" +\
+ stab(3) + self.tooltip_condition_string +\
+ stab(3) + "tooltip_str = '<center><b>'+x+'</b></center>' + y;\n" +\
+ stab(3) + "return tooltip_str;\n" + \
+ stab(2) + "});\n"
+ else:
+ self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \
+ stab(3) + "var x = String(graph.point.x);\n" +\
+ stab(3) + "var y = String(graph.point.y);\n" +\
+ self.tooltip_condition_string +\
+ stab(3) + "tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;\n" +\
+ stab(3) + "return tooltip_str;\n" + \
+ stab(2) + "});\n"
+ else:
+ self.charttooltip = stab(2) + "chart.tooltipContent(function(key, y, e, graph) {\n" + \
+ stab(3) + "var x = d3.time.format('%s')(new Date(parseInt(graph.point.x)));\n" \
+ % self.charttooltip_dateformat +\
+ stab(3) + "var y = String(graph.point.y);\n" +\
+ self.tooltip_condition_string +\
+ stab(3) + "tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;\n" +\
+ stab(3) + "return tooltip_str;\n" + \
+ stab(2) + "});\n"
+
+ def buildjschart(self):
+ """generate javascript code for the chart"""
+
+ self.jschart = ''
+ if self.tag_script_js:
+ self.jschart += '\n<script>\n'
+
+ self.jschart += stab()
+
+ if self.jquery_on_ready:
+ self.jschart += '$(function(){'
+
+ self.jschart += 'nv.addGraph(function() {\n'
+
+ self.jschart += stab(2) + 'var chart = nv.models.%s();\n' % self.model
+
+ if self.model != 'pieChart' and not self.color_list:
+ if self.color_category:
+ self.jschart += stab(2) + 'chart.color(d3.scale.%s().range());\n' % self.color_category
+
+ if self.stacked:
+ self.jschart += stab(2) + "chart.stacked(true);"
+
+ self.jschart += stab(2) + \
+ 'chart.margin({top: %s, right: %s, bottom: %s, left: %s})\n' % \
+ (self.margin_top, self.margin_right, \
+ self.margin_bottom, self.margin_left)
+
+ """
+ We want now to loop through all the defined Axis and add:
+ chart.y2Axis
+ .tickFormat(function(d) { return '$' + d3.format(',.2f')(d) });
+ """
+ if self.model != 'pieChart':
+ for axis_name, a in list(self.axislist.items()):
+ self.jschart += stab(2) + "chart.%s\n" % axis_name
+ for attr, value in list(a.items()):
+ self.jschart += stab(3) + ".%s(%s);\n" % (attr, value)
+
+ if self.width:
+ self.d3_select_extra += ".attr('width', %s)\n" % self.width
+ if self.height:
+ self.d3_select_extra += ".attr('height', %s)\n" % self.height
+
+ if self.model == 'pieChart':
+ datum = "data_%s[0].values" % self.name
+ else:
+ datum = "data_%s" % self.name
+
+ # add custom tooltip string in jschart
+ # default condition (if build_custom_tooltip is not called explicitly with date_flag=True)
+ if self.tooltip_condition_string == '':
+ self.tooltip_condition_string = 'var y = String(graph.point.y);\n'
+
+ self.build_custom_tooltip()
+ self.jschart += self.charttooltip
+
+ # the shape attribute in kwargs is not applied when
+ # not allowing other shapes to be rendered
+ if self.model == 'scatterChart':
+ self.jschart += 'chart.scatter.onlyCircles(false);'
+
+ if self.model != 'discreteBarChart':
+ if self.show_legend:
+ self.jschart += stab(2) + "chart.showLegend(true);\n"
+ else:
+ self.jschart += stab(2) + "chart.showLegend(false);\n"
+
+ #showLabels only supported in pieChart
+ if self.model == 'pieChart':
+ if self.show_labels:
+ self.jschart += stab(2) + "chart.showLabels(true);\n"
+ else:
+ self.jschart += stab(2) + "chart.showLabels(false);\n"
+
+ # add custom chart attributes
+ for attr, value in self.chart_attr.items():
+ self.jschart += stab(2) + "chart.%s(%s);\n" % (attr, value)
+
+ #Inject data to D3
+ self.jschart += stab(2) + "d3.select('#%s svg')\n" % self.name + \
+ stab(3) + ".datum(%s)\n" % datum + \
+ stab(3) + ".transition().duration(500)\n" + \
+ stab(3) + self.d3_select_extra + \
+ stab(3) + ".call(chart);\n\n"
+
+ if self.resize:
+ self.jschart += stab(1) + "nv.utils.windowResize(chart.update);\n"
+ self.jschart += stab(1) + "return chart;\n});"
+
+ if self.jquery_on_ready:
+ self.jschart += "\n});"
+
+ #Include data
+ series_js = json.dumps(self.series)
+
+ if self.model == 'linePlusBarWithFocusChart':
+ append_to_data = ".map(function(series) {" + \
+ "series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } });" + \
+ "return series; })"
+ self.jschart += """data_%s=%s%s;\n""" % (self.name, series_js, append_to_data)
+ else:
+ self.jschart += """data_%s=%s;\n""" % (self.name, series_js)
+
+ if self.tag_script_js:
+ self.jschart += "</script>"
+
+ def create_x_axis(self, name, label=None, format=None, date=False, custom_format=False):
+ """
+ Create X-axis
+ """
+ axis = {}
+ if custom_format and format:
+ axis['tickFormat'] = format
+ else:
+ if format:
+ if format == 'AM_PM':
+ axis['tickFormat'] = "function(d) { return get_am_pm(parseInt(d)); }"
+ else:
+ axis['tickFormat'] = "d3.format(',%s')" % format
+
+ if label:
+ axis['axisLabel'] = label
+
+ #date format : see https://github.com/mbostock/d3/wiki/Time-Formatting
+ if date:
+ self.dateformat = format
+ axis['tickFormat'] = "function(d) { return d3.time.format('%s')(new Date(parseInt(d))) }\n" % self.dateformat
+ #flag is the x Axis is a date
+ if name[0] == 'x':
+ self.x_axis_date = True
+
+ #Add new axis to list of axis
+ self.axislist[name] = axis
+
+ def create_y_axis(self, name, label=None, format=None, custom_format=False):
+ """
+ Create Y-axis
+ """
+ axis = {}
+
+ if custom_format and format:
+ axis['tickFormat'] = format
+ else:
+ if format:
+ axis['tickFormat'] = "d3.format(',%s')" % format
+
+ if label:
+ axis['axisLabel'] = label
+
+ #Add new axis to list of axis
+ self.axislist[name] = axis
+
+
+def _main():
+ """
+ Parse options and process commands
+ """
+ # Parse arguments
+ usage = "usage: nvd3.py [options]"
+ parser = OptionParser(usage=usage, version="python-nvd3 - Charts generator with nvd3.js and d3.js")
+ parser.add_option("-q", "--quiet",
+ action="store_false", dest="verbose", default=True,
+ help="don't print messages to stdout")
+
+ (options, args) = parser.parse_args()
+
+
+if __name__ == '__main__':
+ _main()
diff --git a/tools/wtperf_stats/3rdparty/nvd3/README.rst b/tools/wtperf_stats/3rdparty/nvd3/README.rst
new file mode 100644
index 00000000000..31a04d958cc
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/README.rst
@@ -0,0 +1,134 @@
+Python Wrapper for NVD3 - It's time for beautiful charts
+========================================================
+
+:Description: Python-nvd3 is a wrapper for NVD3 graph library
+:nvd3: NVD3 http://nvd3.org/
+:d3: Data-Driven Documents http://d3js.org/
+
+
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js offers you.
+
+
+.. image:: https://www.travis-ci.org/areski/python-nvd3.png?branch=master
+
+
+Installation
+------------
+
+Install, upgrade and uninstall python-nvd3 with these commands::
+
+ $ pip install python-nvd3
+ $ pip install --upgrade python-nvd3
+ $ pip uninstall python-nvd3
+
+
+Dependecies
+-----------
+
+D3 and NvD3 can be installed through bower (which itself can be installed through npm). See http://bower.io/ and https://npmjs.org for further information.
+To install bower globally execute::
+
+ $ npm install -g bower
+
+Note : you might prefer to save your npm dependencies locally in a ``package.json`` file.
+
+Then in the directory where you will use python-nvd3, just execute the following commands::
+
+ $ bower install d3#3.3.8
+ $ bower install nvd3#1.1.12-beta
+
+This will create a directory "bower_components" where d3 & nvd3 will be saved.
+
+Note : you might prefer to save your bower dependencies locally in a ``bower.json`` file. You can also configure the directory where your bower dependencies will be saved adding a ``.bowerrc`` file in your project root directory.
+
+
+Usage
+-----
+
+After installation use python-nvd3 as follows ::
+
+ from nvd3 import pieChart
+
+ #Open File to write the D3 Graph
+ output_file = open('test-nvd3.html', 'w')
+
+ type = 'pieChart'
+ chart = pieChart(name=type, color_category='category20c', height=450, width=450)
+ chart.set_containerheader("\n\n<h2>" + type + "</h2>\n\n")
+
+ #Create the keys
+ xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"]
+ ydata = [3, 4, 0, 1, 5, 7, 3]
+
+ #Add the serie
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}}
+ chart.add_serie(y=ydata, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+ output_file.write(chart.htmlcontent)
+
+ #close Html file
+ output_file.close()
+
+
+See the file examples.py for more samples.
+
+
+Live demo of NVD3
+-----------------
+
+See a live demo on jsfiddle : http://jsfiddle.net/areski/z4zuH/3/
+
+
+Supported nvd3 charts
+---------------------
+
+Charts list:
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/lineWithFocusChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/lineChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/multiBarChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/pieChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/stackedAreaChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/multiBarHorizontalChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/linePlusBarChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/cumulativeLineChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/discreteBarChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/scatterChart.png
+
+.. image:: https://raw.github.com/areski/python-nvd3/master/docs/source/_static/screenshot/linePlusBarWithFocusChart.png
+
+
+Documentation
+-------------
+
+Documentation is available on 'Read the Docs':
+http://python-nvd3.readthedocs.org
+
+
+Changelog
+---------
+
+Changelog summary : https://github.com/areski/python-nvd3/blob/master/CHANGELOG.rst
+
+
+Do you like Django?
+-------------------
+
+There is also a django wrapper for nvd3 available:
+https://github.com/areski/django-nvd3
+
+
+License
+-------
+
+Python-nvd3 is licensed under MIT, see `MIT-LICENSE.txt`.
diff --git a/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README b/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README
new file mode 100644
index 00000000000..e9eb0a8b081
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/WIREDTIGER_README
@@ -0,0 +1,20 @@
+This is a pre-build python-nvd3 library. It was built from the
+Git repository:
+https://github.com/areski/python-nvd3
+
+Based on revision:
+commit deb12255fa61f0ff3fa4b41699e0ef8e62fbd4a6
+Author: Areski Belaid <areski@gmail.com>
+Date: Mon Feb 10 15:27:20 2014 +0100
+
+Using Python 2.7.5
+
+To reproduce run:
+
+$ cd wiredtiger/tools/third_party
+$ git clone https://github.com/areski/python-nvd3
+$ cd python-nvd3
+$ git checkout deb12255
+$ python27 setup.py build
+$ cp build/lib/nvd3/* nvd3/
+
diff --git a/tools/wtperf_stats/3rdparty/nvd3/__init__.py b/tools/wtperf_stats/3rdparty/nvd3/__init__.py
new file mode 100644
index 00000000000..72bb4608230
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/__init__.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+__version__ = '0.11.0' # edit also docs/source/conf.py
+__all__ = ['lineChart', 'pieChart', 'lineWithFocusChart',
+ 'stackedAreaChart', 'multiBarHorizontalChart',
+ 'linePlusBarChart', 'cumulativeLineChart',
+ 'scatterChart', 'discreteBarChart', 'multiBarChart',
+ 'linePlusBarWithFocusChart']
+
+
+from .lineChart import lineChart
+from .pieChart import pieChart
+from .lineWithFocusChart import lineWithFocusChart
+from .stackedAreaChart import stackedAreaChart
+from .multiBarHorizontalChart import multiBarHorizontalChart
+from .linePlusBarChart import linePlusBarChart
+from .cumulativeLineChart import cumulativeLineChart
+from .scatterChart import scatterChart
+from .discreteBarChart import discreteBarChart
+from .multiBarChart import multiBarChart
+from .linePlusBarWithFocusChart import linePlusBarWithFocusChart
diff --git a/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py b/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py
new file mode 100644
index 00000000000..3ffbc66127c
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/cumulativeLineChart.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class cumulativeLineChart(NVD3Chart):
+ """
+ A cumulative line chart is used when you have one important grouping representing
+ an ordered set of data and one value to show, summed over time.
+
+ .. image:: ../_static/screenshot/cumulativeLineChart.png
+
+ Python example::
+
+ from nvd3 import cumulativeLineChart
+ chart = cumulativeLineChart(name='cumulativeLineChart', x_is_date=True)
+ xdata = [1365026400000000, 1365026500000000, 1365026600000000]
+ ydata = [-6, 5, -1]
+ y2data = [36, 55, 11]
+
+ extra_serie = {"tooltip": {"y_start": "There are ", "y_end": " calls"}}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " mins"}}
+ chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_lineWithFocusChart = [
+ {
+ "key" : "Serie 1",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : -6
+ },
+ { "x" : "1365026500000000",
+ "y" : -5
+ },
+ { "x" : "1365026600000000",
+ "y" : -1
+ },
+ ],
+ },
+ {
+ "key" : "Serie 2",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : 34
+ },
+ { "x" : "1365026500000000",
+ "y" : 56
+ },
+ { "x" : "1365026600000000",
+ "y" : 32
+ },
+ ],
+ }
+ ]
+
+ nv.addGraph(function() {
+ var chart = nv.models.cumulativeLineChart();
+
+ chart.xAxis
+ .tickFormat(function(d) { return d3.time.format('%d %b %Y')(new Date(d)) });
+ chart.y1Axis
+ .tickFormat(d3.format('.1%'));
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = d3.time.format('%d %b %Y')(new Date(parseInt(graph.point.x)));
+ var y = String(graph.point.y);
+ if(key == 'Serie 1'){
+ var y = 'There are ' + String(e) + ' calls';
+ }
+ if(key == 'Serie 2'){
+ var y = String(e) + ' mins';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;
+ return tooltip_str;
+ });
+ d3.select('#cumulativeLineChart svg')
+ .datum(data_linePlusBarChart)
+ .transition().duration(500)
+ .attr('height', 350)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', '%d %b %Y'),
+ date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.1%'))
+
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py
new file mode 100644
index 00000000000..a16c32a9265
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/discreteBarChart.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class discreteBarChart(NVD3Chart):
+ """
+ A discrete bar chart or bar graph is a chart with rectangular bars with
+ lengths proportional to the values that they represent.
+
+ .. image:: ../_static/screenshot/discreteBarChart.png
+
+ Python example::
+
+ from nvd3 import discreteBarChart
+ chart = discreteBarChart(name='discreteBarChart', height=400, width=400)
+
+ xdata = ["A", "B", "C", "D", "E"]
+ ydata = [3, 4, 0, -3, 5, 7]
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}}
+ chart.add_serie(y=ydata, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data = [{ key: "Cumulative Return",
+ values: [
+ {
+ "label": "A",
+ "value" : 10
+ },
+ {
+ "label": "B",
+ "value" : 0
+ },
+ {
+ "label": "C",
+ "value" : -3
+ },
+ ]
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.discreteBarChart()
+ .x(function(d) { return d.label })
+ .y(function(d) { return d.value })
+ .showLabels(true);
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(graph.point.x);
+ var y = String(graph.point.y);
+ if(key == 'Serie 1'){
+ var y = String(graph.point.y) + ' balls';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;
+ return tooltip_str;
+ });
+ d3.select("#div_id")
+ .datum(data)
+ .transition()
+ .duration(1200)
+ .call(chart);
+
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ self.name = kwargs.get('name', 'discreteBarChart')
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', "%d %b %Y %H %S"),
+ date=True)
+ else:
+ self.create_x_axis('xAxis', format=None)
+
+ self.set_custom_tooltip_flag(True)
+
+ # must have a specified height, otherwise it superimposes both charts
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/lineChart.py b/tools/wtperf_stats/3rdparty/nvd3/lineChart.py
new file mode 100644
index 00000000000..b0dc1796863
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/lineChart.py
@@ -0,0 +1,111 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart, stab
+
+
+class lineChart(NVD3Chart):
+ """
+ A line chart or line graph is a type of chart which displays information
+ as a series of data points connected by straight line segments.
+
+ .. image:: ../_static/screenshot/lineChart.png
+
+ Python example::
+
+ from nvd3 import lineChart
+ chart = lineChart(name='lineChart', height=400, width=400, x_is_date=True, x_axis_format="%d %b %Y %H")
+ xdata = [1365026400000000, 1365026500000000, 1365026600000000]
+ ydata = [-6, 5, -1]
+
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"},
+ "date_format": "%d %b %Y %H:%S"}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_lineChart = [{
+ "key" : "Serie 1",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : -6
+ },
+ { "x" : "1365026500000000",
+ "y" : -5
+ },
+ { "x" : "1365026600000000",
+ "y" : -1
+ },
+ ],
+ "yAxis" : "1"
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.lineChart();
+ chart.xAxis
+ .tickFormat(function(d) { return d3.time.format('%d %b %y %H')(new Date(d)) });
+ chart.yAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = d3.time.format('%d %b %Y %H:%S')(new Date(parseInt(graph.point.x)));
+ var y = String(graph.point.y);
+ if(key == 'Serie 1'){
+ var y = 'There is ' + String(graph.point.y) + ' calls';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;
+ return tooltip_str;
+ });
+ d3.select('#lineChart svg')
+ .datum(data_lineChart)
+ .transition()
+ .duration(500)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', '%d %b %Y'),
+ date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ if kwargs.get('x_axis_format') == 'AM_PM':
+ self.x_axis_format = format = 'AM_PM'
+ else:
+ format = kwargs.get('x_axis_format', 'r')
+ self.create_x_axis('xAxis', format=format)
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.02f'))
+
+ # must have a specified height, otherwise it superimposes both chars
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
+
+ def buildjschart(self):
+ NVD3Chart.buildjschart(self)
+ am_pm_js = ''
+ if self.x_axis_format == 'AM_PM':
+ am_pm_js += stab(2) + "function get_am_pm(d){\n"
+ am_pm_js += stab(3) + "if(d > 12){ d = d - 12; return (String(d) + 'PM');}\n"
+ am_pm_js += stab(3) + "else{ return (String(d) + 'AM');}\n"
+ am_pm_js += stab(2) + "};\n"
+
+ start_js = self.jschart.find('nv.addGraph')
+ replace_index = start_js
+ if start_js > 0:
+ self.jschart = self.jschart[:replace_index] + am_pm_js + self.jschart[replace_index:]
diff --git a/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py
new file mode 100644
index 00000000000..b4b3ca139b0
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarChart.py
@@ -0,0 +1,125 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class linePlusBarChart(NVD3Chart):
+ """
+ A linePlusBarChart Chart is a type of chart which displays information
+ as a series of data points connected by straight line segments
+ and with some series with rectangular bars with lengths proportional
+ to the values that they represent
+
+ .. image:: ../_static/screenshot/linePlusBarChart.png
+
+ Python example::
+
+ from nvd3 import linePlusBarChart
+ chart = linePlusBarChart(name='linePlusBarChart', x_is_date=True, x_axis_format="%d %b %Y")
+
+ xdata = [1365026400000000, 1365026500000000, 1365026600000000]
+ ydata = [-6, 5, -1]
+ y2data = [36, 55, 11]
+
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"},
+ "date_format": "%d %b %Y %H:%S" }
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}}
+ chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_lineWithFocusChart = [
+ {
+ "key" : "Serie 1",
+ "bar": "true",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : -6
+ },
+ { "x" : "1365026500000000",
+ "y" : -5
+ },
+ { "x" : "1365026600000000",
+ "y" : -1
+ },
+ ],
+ },
+ {
+ "key" : "Serie 2",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : 34
+ },
+ { "x" : "1365026500000000",
+ "y" : 56
+ },
+ { "x" : "1365026600000000",
+ "y" : 32
+ },
+ ],
+ }
+ ]
+
+ nv.addGraph(function() {
+ var chart = nv.models.linePlusBarChart();
+
+ chart.xAxis
+ .tickFormat(function(d) { return d3.time.format('%d %b %Y')(new Date(d)) });
+ chart.y1Axis
+ .tickFormat(d3.format(',f'));
+ chart.y2Axis
+ .tickFormat(function(d) { return '$' + d3.format(',f')(d) });
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = d3.time.format('%d %b %Y %H:%S')(new Date(parseInt(graph.point.x)));
+ var y = String(graph.point.y);
+ if(key.indexOf('Serie 1') > -1 ){
+ var y = '$ ' + String(graph.point.y) ;
+ }
+ if(key.indexOf('Serie 2') > -1 ){
+ var y = String(graph.point.y) + ' min';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;
+ return tooltip_str;
+ });
+ d3.select('#linePlusBarChart svg')
+ .datum(data_linePlusBarChart)
+ .transition().duration(500)
+ .attr('height', 350)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', '%d %b %Y %H %S'),
+ date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+
+ self.create_y_axis('y1Axis', format="f")
+ self.create_y_axis('y2Axis', format="function(d) { return d3.format(',f')(d) }", custom_format=True)
+
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py
new file mode 100644
index 00000000000..6067b7a5bbb
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/linePlusBarWithFocusChart.py
@@ -0,0 +1,153 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart, stab
+
+
+class linePlusBarWithFocusChart(NVD3Chart):
+ """
+ A linePlusBarWithFocusChart Chart is a type of chart which displays information
+ as a series of data points connected by straight line segments
+ and with some series with rectangular bars with lengths proportional
+ to the values that they represent
+
+ .. image:: ../_static/screenshot/linePlusBarWithFocusChart.png
+
+ Python example::
+
+ from nvd3 import linePlusBarWithFocusChart
+ chart = linePlusBarWithFocusChart(name='linePlusBarChart', x_is_date=True, x_axis_format="%d %b %Y")
+
+ xdata = [1365026400000000, 1365026500000000, 1365026600000000]
+ ydata = [-6, 5, -1]
+ y2data = [36, 55, 11]
+ kwargs = {}
+ kwargs['bar'] = True
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"},
+ "date_format": "%d %b %Y %H:%S" }
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie, **kwargs)
+
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}}
+ chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_linePlusBarWithFocusChart = [
+ {
+ "key" : "Quantity" ,
+ "bar": true,
+ "values" : [ [ 1136005200000 , 1271000.0] , [ 1138683600000 , 1271000.0] , ]
+ },
+ {
+ "key" : "Price" ,
+ "values" : [ [ 1136005200000 , 71.89] , [ 1138683600000 , 75.51]]
+ }
+ ].map(function(series) {
+ series.values = series.values.map(function(d) { return {x: d[0], y: d[1] } });
+ return series;
+ });
+
+ nv.addGraph(function() {
+ var chart = nv.models.linePlusBarWithFocusChart()
+ .margin({top: 30, right: 60, bottom: 50, left: 70})
+ .x(function(d,i) { return i })
+ .color(d3.scale.category10().range());
+
+ chart.xAxis.tickFormat(function(d) {
+
+ var dx = testdata[0].values[d] && testdata[0].values[d].x || 0;
+ if (dx > 0) {
+ return d3.time.format('%x')(new Date(dx))
+ }
+ return null;
+ });
+
+ chart.x2Axis.tickFormat(function(d) {
+ var dx = testdata[0].values[d] && testdata[0].values[d].x || 0;
+ return d3.time.format('%x')(new Date(dx))
+ });
+
+ chart.y1Axis.tickFormat(d3.format(',f'));
+
+ chart.y3Axis.tickFormat(d3.format(',f'));
+
+ chart.y2Axis.tickFormat(function(d) { return '$' + d3.format(',.2f')(d) });
+
+ chart.y4Axis.tickFormat(function(d) { return '$' + d3.format(',.2f')(d) });
+
+ chart.bars.forceY([0]);
+ chart.bars2.forceY([0]);
+ //chart.lines.forceY([0]);
+ nv.log(testdata);
+ d3.select('#linePlusBarWithFocusChart svg')
+ .datum(testdata)
+ .call(chart);
+
+ nv.utils.windowResize(chart.update);
+
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+
+ with_focus_chart_1 = """function(d) {
+ var dx = data_%s[0].values[d] && data_%s[0].values[d].x || 0;
+ if (dx > 0) { return d3.time.format('%s')(new Date(dx)) }
+ return null;
+ }""" % (self.name, self.name, kwargs.get('x_axis_format', '%d %b %Y %H %S'))
+ self.create_x_axis('xAxis', format=with_focus_chart_1, date=False, custom_format=True)
+
+ with_focus_chart_2 = """function(d) {
+ var dx = data_%s[0].values[d] && data_%s[0].values[d].x || 0;
+ return d3.time.format('%s')(new Date(dx));
+ }""" % (self.name, self.name, kwargs.get('x_axis_format', '%d %b %Y %H %S'))
+
+ self.create_x_axis('x2Axis', format=with_focus_chart_2, date=False, custom_format=True)
+
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=".2f")
+
+ self.create_y_axis('y1Axis', format="f")
+ self.create_y_axis('y3Axis', format="f")
+
+ self.create_y_axis('y2Axis', format="function(d) { return d3.format(',.2f')(d) }", custom_format=True)
+
+ self.create_y_axis('y4Axis', format="function(d) { return d3.format(',.2f')(d) }", custom_format=True)
+
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
+
+ def buildjschart(self):
+ NVD3Chart.buildjschart(self)
+
+ string_jschart = '\n' + stab(2) + 'chart.margin({top: 30, right: 60, bottom: 50, left: 70})\n' + \
+ stab(3) + '.x(function(d,i) { return i });\n'
+ if self.width:
+ string_jschart += stab(2) + 'chart.width(%s);\n' % self.width
+ if self.height:
+ string_jschart += stab(2) + 'chart.height(%s);\n' % self.height
+
+ start_index = self.jschart.find('.linePlusBarWithFocusChart();')
+ string_len = len('.linePlusBarWithFocusChart();')
+ replace_index = start_index + string_len
+ if start_index > 0:
+ self.jschart = self.jschart[:replace_index] + string_jschart + self.jschart[replace_index:]
diff --git a/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py b/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py
new file mode 100644
index 00000000000..4a6cd778551
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/lineWithFocusChart.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class lineWithFocusChart(NVD3Chart):
+ """
+ A lineWithFocusChart or line graph is a type of chart which displays information
+ as a series of data points connected by straight line segments.
+ The lineWithFocusChart provide a smaller chart that act as a selector,
+ this is very useful if you want to zoom on a specific time period.
+
+ .. image:: ../_static/screenshot/lineWithFocusChart.png
+
+ Python example::
+
+ from nvd3 import lineWithFocusChart
+ chart = lineWithFocusChart(name='lineWithFocusChart', x_is_date=True, x_axis_format="%d %b %Y")
+ xdata = [1365026400000000, 1365026500000000, 1365026600000000]
+ ydata = [-6, 5, -1]
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " ext"},
+ "date_format": "%d %b %Y"}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_lineWithFocusChart = [{ "key" : "Serie 1",
+ "values" : [
+ { "x" : "1365026400000000",
+ "y" : -6
+ },
+ { "x" : "1365026500000000",
+ "y" : -5
+ },
+ { "x" : "1365026600000000",
+ "y" : -1
+ },
+ ],
+ "yAxis" : "1"
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.lineWithFocusChart();
+ chart.yAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.y2Axis
+ .tickFormat(d3.format(',.2f'));
+ chart.xAxis
+ .tickFormat(function(d) { return d3.time.format('%d %b %y')(new Date(d)) });
+ chart.x2Axis
+ .tickFormat(function(d) { return d3.time.format('%d %b %y')(new Date(d)) });
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = d3.time.format('%d %b %Y')(new Date(parseInt(graph.point.x)));
+ var y = String(graph.point.y);
+ if(key == 'serie 1'){
+ var y = 'There is ' + String(graph.point.y) + ' calls';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' on ' + x;
+ return tooltip_str;
+ });
+ d3.select('#lineWithFocusChart svg')
+ .datum(data_lineWithFocusChart)
+ .transition()
+ .duration(500)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '%d %b %Y %H %S'), date=True)
+ self.create_x_axis('x2Axis', format=kwargs.get('x_axis_format', '%d %b %Y %H %S'), date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+ self.create_x_axis('x2Axis', format=kwargs.get('x_axis_format', '.2f'))
+
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f'))
+ self.create_y_axis('y2Axis', format=kwargs.get('y_axis_format', '.2f'))
+
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py b/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py
new file mode 100644
index 00000000000..991f0f48174
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/multiBarChart.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class multiBarChart(NVD3Chart):
+ """
+ A multiple bar graph contains comparisons of two or more categories or bars.
+ One axis represents a quantity and the other axis identifies a specific feature
+ about the categories. Reading a multiple bar graph includes looking at extremes
+ (tallest/longest vs. shortest) in each grouping.
+
+ .. image:: ../_static/screenshot/multiBarChart.png
+
+ Python example::
+
+ from nvd3 import multiBarChart
+ chart = multiBarChart(name='multiBarChart', height=400, width=400)
+ xdata = [0, 1, 3, 4]
+ ydata = [6, 12, 9, 16]
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_MultiBarChart = [{ "key" : "Serie 1",
+ "values" : [
+ { "x" : 0
+ "y" : 6
+ },
+ { "x" : 1,
+ "y" : 12
+ },
+ { "x" : 3,
+ "y" : 9
+ },
+ ],
+ "yAxis" : "1"
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.multiBarChart();
+ chart.xAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.yAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(graph.point.x);
+ var y = String(graph.point.y);
+ if(key == 'Serie 1'){
+ var y = String(graph.point.y) + ' balls';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;
+ return tooltip_str;
+ });
+ d3.select('#MultiBarChart svg')
+ .datum(data_MultiBarChart)
+ .transition()
+ .duration(500)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', '%d %b %Y'),
+ date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f'))
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py b/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py
new file mode 100644
index 00000000000..8f2c8dbaaee
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/multiBarHorizontalChart.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class multiBarHorizontalChart(NVD3Chart):
+ """
+ A multiple horizontal bar graph contains comparisons of two or more categories or bars.
+
+ .. image:: ../_static/screenshot/multiBarHorizontalChart.png
+
+ Python example::
+
+ from nvd3 import multiBarHorizontalChart
+ chart = multiBarHorizontalChart(name='multiBarHorizontalChart', height=400, width=400)
+ xdata = [-14, -7, 7, 14]
+ ydata = [-6, 5, -1, 9]
+ y2data = [-23, -6, -32, 9]
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " balls"}}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " calls"}}
+ chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_lineChart = [ { "key" : "Serie 1",
+ "values" : [ { "x" : 0,
+ "y" : -2
+ },
+ { "x" : 1,
+ "y" : 4
+ },
+ { "x" : 2,
+ "y" : -7
+ },
+ ],
+ "yAxis" : "1"
+ },
+ { "key" : "Serie 2",
+ "values" : [ { "x" : 0,
+ "y" : -4
+ },
+ { "x" : 1,
+ "y" : 8
+ },
+ { "x" : 2,
+ "y" : -14
+ },
+ ],
+ "yAxis" : "1"
+ }
+ ]
+
+ nv.addGraph(function() {
+ var chart = nv.models.multiBarHorizontalChart();
+ chart.xAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.yAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(graph.point.x);
+ var y = String(graph.point.y);
+ if(key == 'Serie 1'){
+ var y = String(graph.point.y) + ' balls';
+ }
+ if(key == 'Serie 2'){
+ var y = String(graph.point.y) + ' calls';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;
+ return tooltip_str;
+ });
+ d3.select('#multiBarHorizontalChart svg')
+ .datum(data_multiBarHorizontalChart)
+ .transition().duration(500)
+ .attr('height', 350)
+ .call(chart);
+
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f'))
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/pieChart.py b/tools/wtperf_stats/3rdparty/nvd3/pieChart.py
new file mode 100644
index 00000000000..5c542bd8d3c
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/pieChart.py
@@ -0,0 +1,125 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart, stab
+
+
+class pieChart(NVD3Chart):
+ """
+ A pie chart (or a circle graph) is a circular chart divided into sectors,
+ illustrating numerical proportion. In chart, the arc length of each sector
+ is proportional to the quantity it represents.
+
+ .. image:: ../_static/screenshot/pieChart.png
+
+ Python example::
+
+ from nvd3 import pieChart
+ chart = pieChart(name='pieChart', color_category='category20c', height=400, width=400)
+
+ xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"]
+ ydata = [3, 4, 0, 1, 5, 7, 3]
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}}
+ chart.add_serie(y=ydata, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data = [{ key: "Cumulative Return",
+ values: [
+ {
+ "label": "One",
+ "value" : 29.765957771107
+ },
+ {
+ "label": "Two",
+ "value" : 0
+ },
+ {
+ "label": "Three",
+ "value" : 32.807804682612
+ },
+ ]
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.pieChart()
+ .x(function(d) { return d.label })
+ .y(function(d) { return d.value })
+ .showLabels(true);
+
+ chart.color(d3.scale.category20c().range());
+
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(key);
+ var y = String(y) + ' cal';
+ tooltip_str = '<center><b>'+x+'</b></center>' + y;
+ return tooltip_str;
+ });
+
+ d3.select("#div_id")
+ .datum(data)
+ .transition()
+ .duration(1200)
+ .call(chart);
+
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ self.create_x_axis('xAxis', format=None)
+ self.create_y_axis('yAxis', format=None)
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
+
+ def buildjschart(self):
+ NVD3Chart.buildjschart(self)
+
+ color_js = ''
+ if self.color_list:
+ color_js += "var mycolor = new Array();\n"
+ color_count = 0
+ for i in self.color_list:
+ color_js += stab(2) + "mycolor[" + str(color_count) + "] = '" + i + "';\n"
+ color_count = int(color_count) + 1
+
+ # add mycolor var in js before nv.addGraph starts
+ if self.color_list:
+ start_js = self.jschart.find('nv.addGraph')
+ #start_js_len = len('nv.addGraph')
+ replace_index = start_js
+ if start_js > 0:
+ self.jschart = self.jschart[:replace_index] + color_js + self.jschart[replace_index:]
+
+ pie_jschart = '\n' + stab(2) + 'chart.x(function(d) { return d.label })\n' + \
+ stab(3) + '.y(function(d) { return d.value });\n'
+ if self.width:
+ pie_jschart += stab(2) + 'chart.width(%s);\n' % self.width
+ if self.height:
+ pie_jschart += stab(2) + 'chart.height(%s);\n' % self.height
+
+ # add custom colors for pieChart
+ if self.color_list and color_js:
+ pie_jschart += stab(2) + 'chart.color(mycolor);\n'
+
+ start_index = self.jschart.find('.pieChart();')
+ string_len = len('.pieChart();')
+ replace_index = start_index + string_len
+ if start_index > 0:
+ self.jschart = self.jschart[:replace_index] + pie_jschart + self.jschart[replace_index:]
diff --git a/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py b/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py
new file mode 100644
index 00000000000..74e1e08475f
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/scatterChart.py
@@ -0,0 +1,137 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart, stab
+
+
+class scatterChart(NVD3Chart):
+ """
+ A scatter plot or scattergraph is a type of mathematical diagram using Cartesian
+ coordinates to display values for two variables for a set of data.
+ The data is displayed as a collection of points, each having the value of one variable
+ determining the position on the horizontal axis and the value of the other variable
+ determining the position on the vertical axis.
+
+ .. image:: ../_static/screenshot/scatterChart.png
+
+ Python example::
+
+ from nvd3 import scatterChart
+ chart = scatterChart(name='scatterChart', height=400, width=400)
+ xdata = [3, 4, 0, -3, 5, 7]
+ ydata = [-1, 2, 3, 3, 15, 2]
+ ydata = [1, -2, 4, 7, -5, 3]
+
+ kwargs1 = {'shape': 'circle', 'size': '1'}
+ kwargs2 = {'shape': 'cross', 'size': '10'}
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " call"}}
+ chart.add_serie(name="series 1", y=ydata, x=xdata, extra=extra_serie, **kwargs1)
+
+ extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}}
+ chart.add_serie(name="series 2", y=ydata, x=xdata, extra=extra_serie, **kwargs2)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data = [{ key: "series 1",
+ values: [
+ {
+ "x": 2,
+ "y": 10,
+ "shape": "circle"
+ },
+ {
+ "x": -2,
+ "y" : 0,
+ "shape": "circle"
+ },
+ {
+ "x": 5,
+ "y" : -3,
+ "shape": "circle"
+ },
+ ]
+ },
+ { key: "series 2",
+ values: [
+ {
+ "x": 4,
+ "y": 10,
+ "shape": "cross"
+ },
+ {
+ "x": 4,
+ "y" : 0,
+ "shape": "cross"
+ },
+ {
+ "x": 3,
+ "y" : -3,
+ "shape": "cross"
+ },
+ ]
+ }]
+
+ nv.addGraph(function() {
+ var chart = nv.models.scatterChart()
+ .showLabels(true);
+
+ chart.showDistX(true);
+ chart.showDistY(true);
+
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(graph.point.x);
+ var y = String(graph.point.y);
+ if(key == 'serie 1'){
+ var y = String(graph.point.y) + ' calls';
+ }
+ if(key == 'serie 2'){
+ var y = String(graph.point.y) + ' min';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;
+ return tooltip_str;
+ });
+
+ d3.select("#div_id")
+ .datum(data)
+ .transition()
+ .duration(1200)
+ .call(chart);
+
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.02f'))
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.02f'))
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
+
+ def buildjschart(self):
+ NVD3Chart.buildjschart(self)
+
+ scatter_jschart = '\n' + stab(3) + '.showDistX(true)\n' + \
+ stab(3) + '.showDistY(true)\n' + \
+ stab(3) + '.color(d3.scale.category10().range())'
+
+ start_index = self.jschart.find('.scatterChart()')
+ string_len = len('.scatterChart()')
+ replace_index = start_index + string_len
+ if start_index > 0:
+ self.jschart = self.jschart[:replace_index] + scatter_jschart + self.jschart[replace_index:]
diff --git a/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py b/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py
new file mode 100644
index 00000000000..9913929f4cf
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/stackedAreaChart.py
@@ -0,0 +1,112 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Python-nvd3 is a Python wrapper for NVD3 graph library.
+NVD3 is an attempt to build re-usable charts and chart components
+for d3.js without taking away the power that d3.js gives you.
+
+Project location : https://github.com/areski/python-nvd3
+"""
+
+from .NVD3Chart import NVD3Chart
+
+
+class stackedAreaChart(NVD3Chart):
+ """
+ The stacked area chart is identical to the area chart, except the areas are stacked
+ on top of each other, rather than overlapping. This can make the chart much easier to read.
+
+ .. image:: ../_static/screenshot/stackedAreaChart.png
+
+ Python example::
+
+ from nvd3 import stackedAreaChart
+ chart = stackedAreaChart(name='stackedAreaChart', height=400, width=400)
+
+ xdata = [100, 101, 102, 103, 104, 105, 106,]
+ ydata = [6, 11, 12, 7, 11, 10, 11]
+ ydata2 = [8, 20, 16, 12, 20, 28, 28]
+
+ extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " min"}}
+ chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie)
+ chart.add_serie(name="Serie 2", y=ydata2, x=xdata, extra=extra_serie)
+ chart.buildhtml()
+
+ Javascript generated::
+
+ data_stackedAreaChart = [{
+ "values":[
+ {
+ "y":9,
+ "x":100
+ },
+ {
+ "y":5,
+ "x":101
+ },
+ ],
+ "key":"Serie 1",
+ "yAxis":"1"
+ },
+ {
+ "values":[
+ {
+ "y":18,
+ "x":100
+ },
+ {
+ "y":10,
+ "x":101
+ },
+ ],
+ "key":"Serie 2",
+ "yAxis":"1"
+ }
+ ]
+
+ nv.addGraph(function() {
+ var chart = nv.models.stackedAreaChart();
+ chart.xAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.yAxis
+ .tickFormat(d3.format(',.2f'));
+ chart.tooltipContent(function(key, y, e, graph) {
+ var x = String(graph.point.x);
+ var y = String(graph.point.y);
+ if(key == 'serie 1'){
+ var y = 'There is ' + String(graph.point.y) + ' min';
+ }
+ if(key == 'serie 2'){
+ var y = 'There is ' + String(graph.point.y) + ' min';
+ }
+ tooltip_str = '<center><b>'+key+'</b></center>' + y + ' at ' + x;
+ return tooltip_str;
+ });
+ d3.select('#stackedAreaChart svg')
+ .datum(data_stackedAreaChart)
+ .transition()
+ .duration(500)
+ .call(chart);
+ return chart;
+ });
+ """
+ def __init__(self, **kwargs):
+ NVD3Chart.__init__(self, **kwargs)
+ height = kwargs.get('height', 450)
+ width = kwargs.get('width', None)
+
+ if kwargs.get('x_is_date', False):
+ self.set_date_flag(True)
+ self.create_x_axis('xAxis',
+ format=kwargs.get('x_axis_format', '%d %b %Y'),
+ date=True)
+ self.set_custom_tooltip_flag(True)
+ else:
+ self.create_x_axis('xAxis', format=kwargs.get('x_axis_format', '.2f'))
+ self.create_y_axis('yAxis', format=kwargs.get('y_axis_format', '.2f'))
+ # must have a specified height, otherwise it superimposes both chars
+ if height:
+ self.set_graph_height(height)
+ if width:
+ self.set_graph_width(width)
diff --git a/tools/wtperf_stats/3rdparty/nvd3/translator.py b/tools/wtperf_stats/3rdparty/nvd3/translator.py
new file mode 100644
index 00000000000..ffde2c2a1ce
--- /dev/null
+++ b/tools/wtperf_stats/3rdparty/nvd3/translator.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+
+class Tag(object):
+ """Tag class"""
+
+ def __init__(self, content=None):
+ self.content = content
+ self.attrs = ' '.join(['%s="%s"' % (attr, value)
+ for attr, value in self.attrs])
+
+ def __str__(self):
+ return '<%s%s>\n %s\n</%s>' % (self.name,
+ ' ' + self.attrs if self.attrs else '',
+ self.content,
+ self.name)
+
+
+class ScriptTag(Tag):
+ name = 'script'
+ attrs = (('type', 'text/javascript'),)
+
+
+class AnonymousFunction(object):
+ def __init__(self, arguments, content):
+ self.arguments = arguments
+ self.content = content
+
+ def __str__(self):
+ return 'function(%s) { %s }' % (self.arguments, self.content)
+
+
+class Function(object):
+
+ def __init__(self, name):
+ self.name = name
+ self._calls = []
+
+ def __str__(self):
+ operations = [self.name]
+ operations.extend(str(call) for call in self._calls)
+ return '%s' % ('.'.join(operations),)
+
+ def __getattr__(self, attr):
+ self._calls.append(attr)
+ return self
+
+ def __call__(self, *args):
+ if not args:
+ self._calls[-1] = self._calls[-1] + '()'
+ else:
+ arguments = ','.join([str(arg) for arg in args])
+ self._calls[-1] = self._calls[-1] + '(%s)' % (arguments,)
+ return self
+
+
+class Assignment(object):
+
+ def __init__(self, key, value, scoped=True):
+ self.key = key
+ self.value = value
+ self.scoped = scoped
+
+ def __str__(self):
+ return '%s%s = %s;' % ('var ' if self.scoped else '', self.key, self.value)
+
+
+def indent(func):
+ # TODO: Add indents to function str
+ return str(func)
diff --git a/tools/wtperf_stats/wt_nvd3_util.py b/tools/wtperf_stats/wt_nvd3_util.py
new file mode 100644
index 00000000000..fe058d25c1d
--- /dev/null
+++ b/tools/wtperf_stats/wt_nvd3_util.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+#
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+import os, sys
+from datetime import datetime
+
+tool_dir = os.path.split(sys.argv[0])[0]
+# Make sure Python finds the NVD3 in our third party directory, to
+# avoid compatability issues
+sys.path.append(os.path.join(tool_dir, "3rdparty"))
+
+try:
+ from nvd3 import lineChart
+except ImportError:
+ print >>sys.stderr, "Could not import nvd3. It should be installed locally."
+ sys.exit(-1)
+
+# Add a multiChart type so we can overlay line graphs
+class multiChart(lineChart):
+ def __init__(self, **kwargs):
+ lineChart.__init__(self, **kwargs)
+
+ # Fix the axes
+ del self.axislist['yAxis']
+ self.create_y_axis('yAxis1', format=kwargs.get('y_axis_format', '.02f'))
+ self.create_y_axis('yAxis2', format=kwargs.get('y_axis_format', '.02f'))
+
+TIMEFMT = "%b %d %H:%M:%S"
+
+thisyear = datetime.today().year
+def parsetime(s):
+ return datetime.strptime(s, TIMEFMT).replace(year=thisyear)
+
diff --git a/tools/wtperf_stats/wtperf_stats.py b/tools/wtperf_stats/wtperf_stats.py
new file mode 100644
index 00000000000..f87ca2d3254
--- /dev/null
+++ b/tools/wtperf_stats/wtperf_stats.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+#
+# Public Domain 2008-2014 WiredTiger, Inc.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+
+import os, csv, operator, sys
+from time import mktime
+
+tool_dir = os.path.split(sys.argv[0])[0]
+sys.path.append(tool_dir)
+
+try:
+ from wt_nvd3_util import multiChart, parsetime
+except ImportError:
+ print >>sys.stderr, "Could not import wt_nvd3_util.py, it should be\
+ in the same directory as %s" % sys.argv[0]
+ sys.exit(-1)
+
+def timesort(s):
+ # Sort the timestr via its parsetime() value so that the year gets
+ # added and it properly sorts. Times are only %b %d %H:%M:%S and
+ # may improperly sort if the data crosses a month boundary.
+ t = operator.itemgetter('#time')
+ timestr = t(s)
+ return parsetime(timestr)
+
+# Fixup the names and values in a dictionary read in from a csv file. One
+# field must be "#time" - which is used to calculate the interval.
+# Input is a dictionary, output is a list of dictionaries with a single entry.
+def munge_dict(values_dict, abstime):
+ sorted_values = sorted(values_dict, key=timesort)
+ start_time = parsetime(sorted_values[0]['#time'])
+
+ ret = []
+ for v in sorted_values:
+ if abstime:
+ # Build the time series, milliseconds since the epoch
+ v['#time'] = int(mktime(parsetime(v['#time']).timetuple())) * 1000
+ else:
+ # Build the time series as seconds since the start of the data
+ v['#time'] = (parsetime(v['#time']) - start_time).seconds
+ next_val = {}
+ for title, value in v.items():
+ if title.find('uS') != -1:
+ title = title.replace('uS', 'ms')
+ value = float(value) / 1000
+ if title == 'totalsec':
+ value = 0
+ if title == 'checkpoints' and value == 'N':
+ value = 0
+ elif title.find('time') != -1:
+ title = 'time'
+ elif title.find('latency') == -1 and \
+ title.find('checkpoints') == -1:
+ title = title + ' (thousands)'
+ value = float(value) / 1000
+ next_val[title] = value
+ ret.append(next_val)
+
+ # After building the series, eliminate constants
+ d0 = ret[0]
+ for t0, v0 in d0.items():
+ skip = True
+ for d in ret:
+ v = d[t0]
+ if v != v0:
+ skip = False
+ break
+ if skip:
+ for dicts in ret:
+ del dicts[t0]
+
+ return ret
+
+def addPlotsToChart(chart, graph_data, wtstat_chart = False):
+ # Extract the times - they are the same for all lines.
+ times = []
+ for v in graph_data:
+ times.append(v['time'])
+
+ # Add a line to the graph for each field in the CSV file in alphabetical
+ # order, so the key is sorted.
+ for field in sorted(graph_data[0].keys()):
+ if field == 'time':
+ continue
+ # Split the latency and non-latency measurements onto different scales
+ axis = "1"
+ if not wtstat_chart and field.find('latency') == -1:
+ axis="2"
+ ydata = []
+ for v in graph_data:
+ ydata.append(v[field])
+ chart.add_serie(x=times, y=ydata, name=field, type="line", yaxis=axis)
+
+# Input parameters are a chart populated with WiredTiger statistics and
+# the directory where the wtperf monitor file can be found.
+def addPlotsToStatsChart(chart, dirname, abstime):
+ fname = os.path.join(dirname, 'monitor')
+ try:
+ with open(fname, 'rb') as csvfile:
+ reader = csv.DictReader(csvfile)
+ # Transform the data into something NVD3 can digest
+ graph_data = munge_dict(reader, abstime)
+ except IOError:
+ print >>sys.stderr, "Could not open wtperf monitor file."
+ sys.exit(-1)
+ addPlotsToChart(chart, graph_data, 1)
+
+def main():
+ # Parse the command line
+ import argparse
+
+ parser = argparse.ArgumentParser(description='Create graphs from WiredTiger statistics.')
+ parser.add_argument('--abstime', action='store_true',
+ help='use absolute time on the x axis')
+ parser.add_argument('--output', '-o', metavar='file',
+ default='wtperf_stats.html', help='HTML output file')
+ parser.add_argument('files', metavar='file', nargs='+',
+ help='input monitor file generated by WiredTiger wtperf application')
+ args = parser.parse_args()
+
+ output_file = open(args.output, 'w')
+
+ if len(args.files) != 1:
+ print 'Script currently only supports a single monitor file'
+ exit (1)
+
+ chart_extra = {}
+ # Add in the x axis if the user wants time.
+ if args.abstime:
+ chart_extra['x_axis_format'] = '%H:%M:%S'
+
+ for f in args.files:
+ with open(f, 'rb') as csvfile:
+ reader = csv.DictReader(csvfile)
+ # Transform the data into something NVD3 can digest
+ graph_data = munge_dict(reader, args.abstime)
+
+ chart = multiChart(name='wtperf',
+ height=450 + 10*len(graph_data[0].keys()),
+ resize=True,
+ x_is_date=args.abstime,
+ assets_directory='http://source.wiredtiger.com/graphs/',
+ **chart_extra)
+
+ addPlotsToChart(chart, graph_data)
+
+ chart.buildhtml()
+ output_file.write(chart.htmlcontent)
+ output_file.close()
+
+if __name__ == '__main__':
+ main()
+