mirror of https://github.com/apache/jmeter.git
				
				
				
			
		
			
	
	
		
			1429 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			1429 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
|  | /* | ||
|  |    Licensed to the Apache Software Foundation (ASF) under one or more | ||
|  |    contributor license agreements.  See the NOTICE file distributed with | ||
|  |    this work for additional information regarding copyright ownership. | ||
|  |    The ASF licenses this file to You under the Apache License, Version 2.0 | ||
|  |    (the "License"); you may not use this file except in compliance with | ||
|  |    the License.  You may obtain a copy of the License at | ||
|  | 
 | ||
|  |        http://www.apache.org/licenses/LICENSE-2.0 | ||
|  | 
 | ||
|  |    Unless required by applicable law or agreed to in writing, software | ||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  |    See the License for the specific language governing permissions and | ||
|  |    limitations under the License. | ||
|  | */ | ||
|  | $(document).ready(function() { | ||
|  |      | ||
|  | 	$(".click-title").mouseenter( function(	e){ | ||
|  | 		e.preventDefault(); | ||
|  | 		this.style.cursor="pointer"; | ||
|  | 	}); | ||
|  | 	$(".click-title").mousedown( function(event){ | ||
|  | 		event.preventDefault(); | ||
|  | 	}); | ||
|  | 	 | ||
|  | 	// Ugly code while this script is shared among several pages | ||
|  | 	try{ | ||
|  | 		refreshHitsPerSecond(); | ||
|  | 	} catch(e){} | ||
|  | 	try{ | ||
|  | 		refreshBytesThroughputOverTime(); | ||
|  | 	} catch(e){} | ||
|  | 	try{ | ||
|  | 		refreshResponseTimePercentiles(); | ||
|  | 	} catch(e){} | ||
|  | 	$(".portlet-header").css("cursor", "auto"); | ||
|  | }); | ||
|  | 
 | ||
|  | var percentileThreshold = 0; | ||
|  | var showControllersOnly = ${showControllersOnly?c!"false"}; | ||
|  | var seriesFilter = ${seriesFilter!"undefined"}; | ||
|  | var filtersOnlySampleSeries = ${filtersOnlySampleSeries?c!"false"}; | ||
|  | 
 | ||
|  | // Fixes time stamps | ||
|  | function fixTimeStamps(series, offset){ | ||
|  | 	$.each(series, function(index, item) { | ||
|  | 		$.each(item.data, function(index, coord) { | ||
|  | 			coord[0] += offset; | ||
|  | 		}); | ||
|  | 	}); | ||
|  | } | ||
|  | 
 | ||
|  | // Check if the specified jquery object is a graph | ||
|  | function isGraph(object){ | ||
|  | 	return object.data('plot') !== undefined; | ||
|  | } | ||
|  | 
 | ||
|  | // Override the specified graph options to fit the requirements of an overview | ||
|  | function prepareOverviewOptions(graphOptions){ | ||
|  | 	var overviewOptions = { | ||
|  | 		series: { | ||
|  | 			shadowSize: 0, | ||
|  | 			lines: { | ||
|  | 				lineWidth: 1 | ||
|  | 			}, | ||
|  | 			points: { | ||
|  | 				// Show points on overview only when linked graph does not show | ||
|  | 				// lines | ||
|  |                 show: getProperty('series.lines.show', graphOptions) == false, | ||
|  |                 radius : 1 | ||
|  |             } | ||
|  | 		}, | ||
|  | 		xaxis: { | ||
|  | 			ticks: 2, | ||
|  | 			axisLabel: null | ||
|  | 		}, | ||
|  | 		yaxis: { | ||
|  | 			ticks: 2, | ||
|  | 			axisLabel: null | ||
|  | 		}, | ||
|  | 		legend: { | ||
|  | 			show: false, | ||
|  | 			container: null | ||
|  | 		}, | ||
|  | 		grid: { | ||
|  |             hoverable: false | ||
|  |         }, | ||
|  |         tooltip: false | ||
|  | 	}; | ||
|  | 	return $.extend(true, {}, graphOptions, overviewOptions); | ||
|  | } | ||
|  | 
 | ||
|  | // Force axes boundaries using graph extra options  | ||
|  | function prepareOptions(options, data){ | ||
|  | 	var extraOptions = data.extraOptions; | ||
|  | 	if(extraOptions !== undefined){ | ||
|  | 		var xOffset = options.xaxis.mode === "time" ? ${(timeZoneOffset?c)!0} : 0; | ||
|  | 		var yOffset = options.yaxis.mode === "time" ? ${(timeZoneOffset?c)!0} : 0; | ||
|  | 		 | ||
|  | 		var minX = extraOptions.minX; | ||
|  | 		if(minX !== undefined) | ||
|  | 			options.xaxis.min = minX + xOffset; | ||
|  | 		 | ||
|  | 		var maxX = extraOptions.maxX; | ||
|  | 		if(maxX !== undefined) | ||
|  | 			options.xaxis.max = maxX + xOffset; | ||
|  | 		 | ||
|  | 		var minY = extraOptions.minY; | ||
|  | 		if(minY !== undefined) | ||
|  | 			options.yaxis.min = minY + yOffset; | ||
|  | 		 | ||
|  | 		var maxY = extraOptions.maxY; | ||
|  | 		if(maxY !== undefined) | ||
|  | 			options.yaxis.max = maxY + yOffset; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // Filter, mark series and sort data | ||
|  | function prepareSeries(data){ | ||
|  | 	var result = data.result; | ||
|  | 	 | ||
|  | 	// Keep only series when needed | ||
|  | 	if(seriesFilter && (!filtersOnlySampleSeries || result.supportsControllersDiscrimination)){ | ||
|  | 		// Insensitive case matching | ||
|  | 		var regexp = new RegExp(seriesFilter, 'i'); | ||
|  | 		result.series = $.grep(result.series, function(series, index){ | ||
|  | 			return regexp.test(series.label); | ||
|  | 		}); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	// Keep only controllers series when supported and needed | ||
|  | 	if(result.supportsControllersDiscrimination && showControllersOnly){ | ||
|  | 		result.series = $.grep(result.series, function(series, index){ | ||
|  | 			return series.isController; | ||
|  | 		}); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	// Sort data and mark series | ||
|  | 	$.each(result.series, function(index, series) { | ||
|  | 		series.data.sort(compareByXCoordinate); | ||
|  |         series.color = index; | ||
|  |     }); | ||
|  | } | ||
|  | 
 | ||
|  | // Set the zoom on the specified plot object | ||
|  | function zoomPlot(plot, xmin, xmax, ymin, ymax){ | ||
|  | 	var axes = plot.getAxes(); | ||
|  | 	// Override axes min and max options | ||
|  | 	$.extend(true, axes, { | ||
|  | 		xaxis: {  | ||
|  | 			options : { min: xmin, max: xmax } | ||
|  | 		}, | ||
|  | 		yaxis: {  | ||
|  | 			options : { min: ymin, max: ymax } | ||
|  | 		} | ||
|  | 	}); | ||
|  | 	 | ||
|  | 	// Redraw the plot | ||
|  | 	plot.setupGrid(); | ||
|  | 	plot.draw(); | ||
|  | } | ||
|  | 
 | ||
|  | // Prepares DOM items to add zoom function on the specified graph | ||
|  | function setGraphZoomable(graphSelector, overviewSelector){ | ||
|  | 	var graph = $(graphSelector); | ||
|  | 	var overview = $(overviewSelector); | ||
|  | 	  | ||
|  | 	// Ignore mouse down event | ||
|  | 	graph.bind("mousedown", function() { return false; }); | ||
|  | 	overview.bind("mousedown", function() { return false; }); | ||
|  | 	 | ||
|  | 	// Zoom on selection | ||
|  | 	graph.bind("plotselected", function (event, ranges) { | ||
|  | 		// clamp the zooming to prevent infinite zoom | ||
|  | 		if (ranges.xaxis.to - ranges.xaxis.from < 0.00001) { | ||
|  | 			ranges.xaxis.to = ranges.xaxis.from + 0.00001; | ||
|  | 		} | ||
|  | 		if (ranges.yaxis.to - ranges.yaxis.from < 0.00001) { | ||
|  | 			ranges.yaxis.to = ranges.yaxis.from + 0.00001; | ||
|  | 		} | ||
|  | 		 | ||
|  | 		// Do the zooming | ||
|  | 		var plot = graph.data('plot'); | ||
|  | 		zoomPlot(plot, ranges.xaxis.from, ranges.xaxis.to, ranges.yaxis.from, ranges.yaxis.to); | ||
|  | 		plot.clearSelection(); | ||
|  | 		 | ||
|  | 		// Synchronize overview selection | ||
|  | 		overview.data('plot').setSelection(ranges, true); | ||
|  | 	}); | ||
|  | 	 | ||
|  | 	// Zoom linked graph on overview selection | ||
|  | 	overview.bind("plotselected", function (event, ranges) { | ||
|  | 		graph.data('plot').setSelection(ranges); | ||
|  | 	}); | ||
|  | 	 | ||
|  | 	// Reset linked graph zoom when reseting overview selection | ||
|  | 	overview.bind("plotunselected", function () { | ||
|  | 		var overviewAxes = overview.data('plot').getAxes(); | ||
|  | 		zoomPlot(graph.data('plot'), overviewAxes.xaxis.min, overviewAxes.xaxis.max, overviewAxes.yaxis.min, overviewAxes.yaxis.max); | ||
|  | 	}); | ||
|  | } | ||
|  | 
 | ||
|  | var responseTimePercentilesInfos = { | ||
|  | 		data: ${responseTimePercentiles!"{}"}, | ||
|  | 	    getOptions: function() { | ||
|  | 	    	return { | ||
|  | 	    		series: { | ||
|  | 	    			points: { show: false } | ||
|  | 	    		}, | ||
|  | 	    		legend: { | ||
|  | 	    			noColumns: 2, | ||
|  | 	    			show: true, | ||
|  | 	    			container: '#legendResponseTimePercentiles' | ||
|  | 	    		}, | ||
|  | 	    		xaxis: { | ||
|  | 	    			tickDecimals: 1, | ||
|  | 	    			axisLabel: "Percentiles", | ||
|  | 	    			axisLabelUseCanvas: true, | ||
|  | 	    			axisLabelFontSizePixels: 12, | ||
|  | 	    			axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	    			axisLabelPadding: 20, | ||
|  | 	    		}, | ||
|  | 	    		yaxis: {  | ||
|  | 	    			axisLabel: "Percentile value in ms", | ||
|  | 	    			axisLabelUseCanvas: true, | ||
|  | 	    			axisLabelFontSizePixels: 12, | ||
|  | 	    			axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	    			axisLabelPadding: 20 | ||
|  | 	    		}, | ||
|  | 	    		grid: { | ||
|  | 	    			hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 	    		}, | ||
|  | 	    		tooltip: true, | ||
|  | 	    		tooltipOpts: { | ||
|  | 	    			content: "%s for %x.2 was %y" | ||
|  | 	    		}, | ||
|  | 	    		selection: { mode: "xy" }, | ||
|  | 	    	}; | ||
|  | 	    }, | ||
|  | 	    createGraph: function() { | ||
|  | 	    	var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesResponseTimePercentiles"), function(series){ | ||
|  | 				series.curvedLines = {apply: true, tension: 1}; | ||
|  | 				series.threshold = {  | ||
|  | 						below: percentileThreshold,  | ||
|  | 						color: $("#slider-vertical").children("div").css("background-color") | ||
|  | 				}; | ||
|  | 			}); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotResponseTimesPercentiles"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewResponseTimesPercentiles"), dataset, prepareOverviewOptions(options)); | ||
|  | 		} | ||
|  | }; | ||
|  | 	 | ||
|  | // Response times percentiles | ||
|  | function refreshResponseTimePercentiles() { | ||
|  | 	var infos = responseTimePercentilesInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	if (isGraph($("#flotResponseTimesPercentiles"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	} else { | ||
|  | 		var choiceContainer = $("#choicesResponseTimePercentiles"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotResponseTimesPercentiles", "#overviewResponseTimesPercentiles"); | ||
|  | 		$('#bodyResponseTimePercentiles .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | var responseTimeDistributionInfos = { | ||
|  | 		data: ${responseTimeDistribution!"{}"}, | ||
|  | 		getOptions: function() { | ||
|  | 			var granularity = this.data.result.granularity; | ||
|  | 			return { | ||
|  | 				legend: {  | ||
|  | 					noColumns: 2, | ||
|  | 					show: true,  | ||
|  | 					container: '#legendResponseTimeDistribution'  | ||
|  | 				}, | ||
|  | 				xaxis:{ | ||
|  | 					axisLabel: "Response times in ms", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: { | ||
|  | 					axisLabel: "Number of responses", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				bars : { | ||
|  | 					show: true, | ||
|  | 					barWidth: this.data.result.granularity | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: function(label, xval, yval, flotItem){ | ||
|  | 						return yval + " responses for " + label + " were between " + xval + " and " + (xval + granularity) + " ms"; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			}; | ||
|  | 	    }, | ||
|  | 		createGraph: function() { | ||
|  | 			var data = this.data; | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotResponseTimeDistribution"), prepareData(data.result.series, $("#choicesResponseTimeDistribution")), options); | ||
|  | 		} | ||
|  | 	 | ||
|  | }; | ||
|  | 
 | ||
|  | // Response time distribution | ||
|  | function refreshResponseTimeDistribution() { | ||
|  | 	var infos = responseTimeDistributionInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	if (isGraph($("#flotResponseTimeDistribution"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesResponseTimeDistribution"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		$('#footerResponseTimeDistribution .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var activeThreadsOverTimeInfos = { | ||
|  | 		data: ${activeThreadsOverTime!"{}"}, | ||
|  | 		getOptions: function() { | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					lines: { | ||
|  | 						show: true | ||
|  | 					}, | ||
|  | 					points: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					mode: "time", | ||
|  | 					timeformat: "%H:%M:%S", | ||
|  | 					axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: {  | ||
|  | 					axisLabel: "Number of active threads", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20 | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 6, | ||
|  | 					show: true, | ||
|  | 					container: '#legendActiveThreadsOverTime' | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				selection: { | ||
|  | 					mode: 'xy' | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: "%s for %x was %y" | ||
|  | 				} | ||
|  | 			}; | ||
|  | 	    }, | ||
|  | 	    createGraph: function() { | ||
|  | 	    	var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesActiveThreadsOverTime")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotActiveThreadsOverTime"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewActiveThreadsOverTime"), dataset, prepareOverviewOptions(options)); | ||
|  | 		} | ||
|  | }; | ||
|  | 
 | ||
|  | // Active Threads Over Time | ||
|  | function refreshActiveThreadsOverTime() { | ||
|  | 	var infos = activeThreadsOverTimeInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if(isGraph($("#flotActiveThreadsOverTime"))) { | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesActiveThreadsOverTime"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotActiveThreadsOverTime", "#overviewActiveThreadsOverTime"); | ||
|  | 		$('#footerActiveThreadsOverTime .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var responseTimePerSampleInfos = { | ||
|  | 		data: ${responseTimePerSample!"{}"}, | ||
|  | 	    getOptions: function() { | ||
|  | 	    	var ticks = []; | ||
|  | 	    	$.each(this.data.result.sampleNames, function(index, item){ | ||
|  | 	    		ticks.push([index, item]); | ||
|  | 	    	}); | ||
|  | 	    	 | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					bars: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				bars: { | ||
|  | 					align: "center", | ||
|  | 					barWidth: 0.5, | ||
|  | 					horizontal: true, | ||
|  | 					fillColor: { colors: [{ opacity: 0.5 }, { opacity: 1}] }, | ||
|  | 					lineWidth: 1 | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					axisLabel: "Response Time in ms", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 					tickColor: "white", | ||
|  | 					tickFormatter: function (v, axis) { | ||
|  | 						return $.formatNumber(v, { format: "#,###", locale: "us" }); | ||
|  | 					}, | ||
|  | 					color: "black" | ||
|  | 				}, | ||
|  | 				yaxis: { | ||
|  | 					tickColor: "white", | ||
|  | 					ticks: ticks, | ||
|  | 					color: "black" | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 0, | ||
|  | 					labelBoxBorderColor: "#858585", | ||
|  | 					container: '#legendHorizontalBar' | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true, | ||
|  | 					borderWidth: 2, | ||
|  | 					backgroundColor: { colors: ["white", "white"] } | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 	    createGraph: function() { | ||
|  | 	    	var data = this.data; | ||
|  | 	    	var options = this.getOptions(); | ||
|  | 	    	prepareOptions(options, data); | ||
|  | 			$.plot($("#flotResponseTimePerSample"), prepareData(data.result.series, $("#choicesResponseTimePerSample")), options); | ||
|  | 		} | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | // Response Time Per Sample | ||
|  | function refreshResponseTimePerSample() { | ||
|  | 	var infos = responseTimePerSampleInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	if (isGraph($("#flotResponseTimePerSample"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	} else { | ||
|  | 		var choiceContainer = $("#choicesResponseTimePerSample"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		$('#footerResponseTimePerSample .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | 
 | ||
|  |     var previousPoint = null, previousLabel = null; | ||
|  |   | ||
|  | 	$.fn.UseTooltip = function () { | ||
|  | 		$(this).bind("plothover", function (event, pos, item) { | ||
|  | 			if (item) { | ||
|  | 				if ((previousLabel != item.series.label) || | ||
|  | 					(previousPoint != item.dataIndex)) { | ||
|  | 					previousPoint = item.dataIndex; | ||
|  | 					previousLabel = item.series.label; | ||
|  | 					$("#tooltip").remove(); | ||
|  |   | ||
|  | 					var x = item.datapoint[0]; | ||
|  | 					var y = item.datapoint[1]; | ||
|  |   | ||
|  | 					var color = item.series.color; | ||
|  |   | ||
|  | 					showTooltip(item.pageX, | ||
|  | 						item.pageY, | ||
|  |                         color, | ||
|  |                         "<strong>" + item.series.label + "</strong><br>" + item.series.yaxis.ticks[y].label + | ||
|  |                         " : <strong>" + $.formatNumber(x, { format: "#,###", locale: "us" }) + "</strong> ms"); | ||
|  | 				} | ||
|  | 			} else { | ||
|  | 				$("#tooltip").remove(); | ||
|  | 				previousPoint = null; | ||
|  | 			} | ||
|  | 		}); | ||
|  | 	}; | ||
|  |   | ||
|  | 	function showTooltip(x, y, color, contents) { | ||
|  | 		$('<div id="tooltip">' + contents + '</div>').css({ | ||
|  | 			position: 'absolute', | ||
|  | 			display: 'none', | ||
|  | 			top: y - 10, | ||
|  | 			left: x + 10, | ||
|  | 			border: '2px solid ' + color, | ||
|  | 			padding: '3px', | ||
|  | 			'font-size': '9px', | ||
|  | 			'border-radius': '5px', | ||
|  | 			'background-color': '#fff', | ||
|  | 			'font-family': 'Verdana, Arial, Helvetica, Tahoma, sans-serif', | ||
|  | 			opacity: 0.9 | ||
|  | 		}).appendTo("body").fadeIn(200); | ||
|  | 	} | ||
|  | 	 | ||
|  | 	$("#flotResponseTimePerSample").UseTooltip(); | ||
|  | }; | ||
|  | 
 | ||
|  | var timeVsThreadsInfos = { | ||
|  | 		data: ${timeVsThreads!"{}"}, | ||
|  |         getOptions: function() { | ||
|  |         	return { | ||
|  |         		series: { | ||
|  |         			lines: { | ||
|  |         				show: true | ||
|  |         			}, | ||
|  |         			points: { | ||
|  |         				show: true | ||
|  |         			} | ||
|  |         		}, | ||
|  |         		xaxis: { | ||
|  |         			axisLabel: "Number of active threads", | ||
|  |         			axisLabelUseCanvas: true, | ||
|  |         			axisLabelFontSizePixels: 12, | ||
|  |         			axisLabelFontFamily: 'Verdana, Arial', | ||
|  |         			axisLabelPadding: 20, | ||
|  |         		}, | ||
|  |         		yaxis: { | ||
|  |         			axisLabel: "Average response times in ms", | ||
|  |         			axisLabelUseCanvas: true, | ||
|  |         			axisLabelFontSizePixels: 12, | ||
|  |         			axisLabelFontFamily: 'Verdana, Arial', | ||
|  |         			axisLabelPadding: 20 | ||
|  |         		}, | ||
|  |         		legend: { noColumns: 2,show: true, container: '#legendTimeVsThreads' }, | ||
|  |         		selection: { | ||
|  |         			mode: 'xy' | ||
|  |         		}, | ||
|  |         		grid: { | ||
|  |         			hoverable: true // IMPORTANT! this is needed for tooltip to work | ||
|  |         		}, | ||
|  |         		tooltip: true, | ||
|  |         		tooltipOpts: { | ||
|  |         			content: "%s for %x.2 was %y.2" | ||
|  |         		} | ||
|  |         	}; | ||
|  |         }, | ||
|  | 		createGraph: function() { | ||
|  | 			var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesTimeVsThreads")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotTimesVsThreads"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewTimesVsThreads"), dataset, prepareOverviewOptions(options)); | ||
|  | 		}	 | ||
|  | }; | ||
|  | 
 | ||
|  | // Time vs threads | ||
|  | function refreshTimeVsThreads(){ | ||
|  | 	var infos = timeVsThreadsInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	if(isGraph($("#flotTimesVsThreads"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesTimeVsThreads"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotTimesVsThreads", "#overviewTimesVsThreads"); | ||
|  | 		$('#footerTimeVsThreads .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var bytesThroughputOverTimeInfos = { | ||
|  | 		data : ${bytesThroughputOverTime!"{}"}, | ||
|  | 		getOptions : function(){ | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					lines: { | ||
|  | 						show: true | ||
|  | 					}, | ||
|  | 					points: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					mode: "time", | ||
|  | 					timeformat: "%H:%M:%S", | ||
|  | 					axisLabel: getElapsedTimeLabel(this.data.result.granularity) , | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: {  | ||
|  | 					axisLabel: "Bytes/sec", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20,			 | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 2, | ||
|  | 					show: true, | ||
|  | 					container: '#legendBytesThroughputOverTime' | ||
|  | 				}, | ||
|  | 				selection: {  | ||
|  | 					mode: "xy" | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: "%s for %x was %y" | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 		createGraph : function() { | ||
|  | 			var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesBytesThroughputOverTime")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotBytesThroughputOverTime"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewBytesThroughputOverTime"), dataset, prepareOverviewOptions(options)); | ||
|  | 		} | ||
|  | }; | ||
|  | 
 | ||
|  | // Bytes throughput Over Time | ||
|  | function refreshBytesThroughputOverTime() { | ||
|  | 	var infos = bytesThroughputOverTimeInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if(isGraph($("#flotBytesThroughputOverTime"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesBytesThroughputOverTime"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotBytesThroughputOverTime", "#overviewBytesThroughputOverTime"); | ||
|  | 		$('#footerBytesThroughputOverTime .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | var responseTimesOverTimeInfos = { | ||
|  | 		data: ${responseTimesOverTime!"{}"}, | ||
|  | 		getOptions: function(){ | ||
|  | 	        return { | ||
|  | 	        	series: { | ||
|  | 	        		lines: { | ||
|  | 	        			show: true | ||
|  | 	        		}, | ||
|  | 	        		points: { | ||
|  | 	        			show: true | ||
|  | 	        		} | ||
|  | 	        	}, | ||
|  | 	        	xaxis: { | ||
|  | 	        		mode: "time", | ||
|  | 	        		timeformat: "%H:%M:%S", | ||
|  | 	        		axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 	        		axisLabelUseCanvas: true, | ||
|  | 	        		axisLabelFontSizePixels: 12, | ||
|  | 	        		axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	        		axisLabelPadding: 20, | ||
|  | 	        	}, | ||
|  | 	        	yaxis: {  | ||
|  | 	        		axisLabel: "Response time in ms", | ||
|  | 	        		axisLabelUseCanvas: true, | ||
|  | 	        		axisLabelFontSizePixels: 12, | ||
|  | 	        		axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	        		axisLabelPadding: 20, | ||
|  | 	        	}, | ||
|  | 	        	legend: { | ||
|  | 	        		noColumns: 2, | ||
|  | 	        		show: true, | ||
|  | 	        		container: '#legendResponseTimesOverTime' | ||
|  | 	        	}, | ||
|  | 	        	selection: { | ||
|  | 	        		mode: 'xy' | ||
|  | 	        	}, | ||
|  | 	        	grid: { | ||
|  | 	        		hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 	        	}, | ||
|  | 	        	tooltip: true, | ||
|  | 	        	tooltipOpts: { | ||
|  | 	        		content: "%s for %x was %y" | ||
|  | 	        	} | ||
|  | 	        }; | ||
|  | 		}, | ||
|  | 	    createGraph: function() { | ||
|  | 	    	var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesResponseTimesOverTime")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotResponseTimesOverTime"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewResponseTimesOverTime"), dataset, prepareOverviewOptions(options)); | ||
|  | 		} | ||
|  | }; | ||
|  | 
 | ||
|  | // Response Times Over Time | ||
|  | function refreshResponseTimeOverTime() { | ||
|  | 	var infos = responseTimesOverTimeInfos; | ||
|  |     prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if(isGraph($("#flotResponseTimesOverTime"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesResponseTimesOverTime"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotResponseTimesOverTime", "#overviewResponseTimesOverTime"); | ||
|  | 		$('#footerResponseTimesOverTime .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var latenciesOverTimeInfos = { | ||
|  | 		data: ${latenciesOverTime!"{}"}, | ||
|  | 		getOptions: function() { | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					lines: { | ||
|  | 						show: true | ||
|  | 					}, | ||
|  | 					points: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					mode: "time", | ||
|  | 					timeformat: "%H:%M:%S", | ||
|  | 					axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: { | ||
|  | 					axisLabel: "Response latencies in ms", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 2, | ||
|  | 					show: true, | ||
|  | 					container: '#legendLatenciesOverTime' | ||
|  | 				}, | ||
|  | 				selection: { | ||
|  | 					mode: 'xy' | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: "%s for %x was %y" | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 		createGraph: function () { | ||
|  | 			var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesLatenciesOverTime")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotLatenciesOverTime"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewLatenciesOverTime"), dataset, prepareOverviewOptions(options)); | ||
|  | 		}	 | ||
|  | }; | ||
|  | 
 | ||
|  | // Latencies Over Time | ||
|  | function refreshLatenciesOverTime() { | ||
|  | 	var infos = latenciesOverTimeInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if(isGraph($("#flotLatenciesOverTime"))) { | ||
|  | 		infos.createGraph(); | ||
|  | 	}else { | ||
|  | 		var choiceContainer = $("#choicesLatenciesOverTime"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotLatenciesOverTime", "#overviewLatenciesOverTime"); | ||
|  | 		$('#footerLatenciesOverTime .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var responseTimeVsRequestInfos = { | ||
|  | 	data: ${responseTimeVsRequest!"{}"}, | ||
|  | 	getOptions: function() { | ||
|  | 		return { | ||
|  | 			series: { | ||
|  | 				lines: { | ||
|  | 					show: false | ||
|  | 				}, | ||
|  | 				points: { | ||
|  | 					show: true | ||
|  | 				} | ||
|  | 			}, | ||
|  | 			xaxis: { | ||
|  | 				axisLabel: "Global number of requests per second", | ||
|  | 				axisLabelUseCanvas: true, | ||
|  | 				axisLabelFontSizePixels: 12, | ||
|  | 				axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 				axisLabelPadding: 20, | ||
|  | 			}, | ||
|  | 			yaxis: { | ||
|  | 				axisLabel: "Median Response Time", | ||
|  | 				axisLabelUseCanvas: true, | ||
|  | 				axisLabelFontSizePixels: 12, | ||
|  | 				axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 				axisLabelPadding: 20, | ||
|  | 			}, | ||
|  | 			legend: { | ||
|  | 				noColumns: 2, | ||
|  | 				show: true, | ||
|  | 				container: '#legendResponseTimeVsRequest' | ||
|  | 			}, | ||
|  | 			selection: { | ||
|  | 				mode: 'xy' | ||
|  | 			}, | ||
|  | 			grid: { | ||
|  | 				hoverable: true // IMPORTANT! this is needed for tooltip to work | ||
|  | 			}, | ||
|  | 			tooltip: true, | ||
|  | 			tooltipOpts: { | ||
|  | 				content: "%s for %x was %y" | ||
|  | 			} | ||
|  | 		}; | ||
|  | 	}, | ||
|  |     createGraph: function () { | ||
|  |     	var data = this.data; | ||
|  | 		var dataset = prepareData(data.result.series, $("#choicesResponseTimeVsRequest")); | ||
|  | 		var options = this.getOptions(); | ||
|  | 		prepareOptions(options, data); | ||
|  | 		$.plot($("#flotResponseTimeVsRequest"), dataset, options); | ||
|  | 		// setup overview | ||
|  | 		$.plot($("#overviewResponseTimeVsRequest"), dataset, prepareOverviewOptions(options)); | ||
|  | 		 | ||
|  | 	}	 | ||
|  | }; | ||
|  | 
 | ||
|  | // Response Time vs Request | ||
|  | function refreshResponseTimeVsRequest() { | ||
|  | 	var infos = responseTimeVsRequestInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	if (isGraph($("#flotResponseTimeVsRequest"))){ | ||
|  | 		infos.create(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesResponseTimeVsRequest"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotResponseTimeVsRequest", "#overviewResponseTimeVsRequest"); | ||
|  | 		$('#footerResponseRimeVsRequest .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | var latenciesVsRequestInfos = { | ||
|  | 	data: ${latencyVsRequest!"{}"}, | ||
|  |     getOptions: function() { | ||
|  |     	return{ | ||
|  |     		series: { | ||
|  |     			lines: { | ||
|  |     				show: false | ||
|  |     			}, | ||
|  |     			points: { | ||
|  |     				show: true | ||
|  |     			} | ||
|  |     		}, | ||
|  |     		xaxis: { | ||
|  |     			axisLabel: "Global number of requests per second", | ||
|  |     			axisLabelUseCanvas: true, | ||
|  |     			axisLabelFontSizePixels: 12, | ||
|  |     			axisLabelFontFamily: 'Verdana, Arial', | ||
|  |     			axisLabelPadding: 20, | ||
|  |     		}, | ||
|  |     		yaxis: { | ||
|  |     			axisLabel: "Median Latency", | ||
|  |     			axisLabelUseCanvas: true, | ||
|  |     			axisLabelFontSizePixels: 12, | ||
|  |     			axisLabelFontFamily: 'Verdana, Arial', | ||
|  |     			axisLabelPadding: 20, | ||
|  |     		}, | ||
|  |     		legend: { noColumns: 2,show: true, container: '#legendLatencyVsRequest' }, | ||
|  |     		selection: { | ||
|  |     			mode: 'xy' | ||
|  |     		}, | ||
|  |     		grid: { | ||
|  |     			hoverable: true // IMPORTANT! this is needed for tooltip to work | ||
|  |     		}, | ||
|  |     		tooltip: true, | ||
|  |     		tooltipOpts: { | ||
|  |     			content: "%s for %x was %y" | ||
|  |     		} | ||
|  |     	}; | ||
|  |     }, | ||
|  | 	createGraph: function () { | ||
|  | 		var data = this.data; | ||
|  | 		var dataset = prepareData(data.result.series, $("#choicesLatencyVsRequest")); | ||
|  | 		var options = this.getOptions(); | ||
|  | 		prepareOptions(options, data); | ||
|  | 		$.plot($("#flotLatenciesVsRequest"), dataset, options); | ||
|  | 		// setup overview | ||
|  | 		$.plot($("#overviewLatenciesVsRequest"), dataset, prepareOverviewOptions(options)); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | // Latencies vs Request | ||
|  | function refreshLatenciesVsRequest() { | ||
|  | 		var infos = latenciesVsRequestInfos; | ||
|  | 		prepareSeries(infos.data); | ||
|  | 		if(isGraph($("#flotLatenciesVsRequest"))){ | ||
|  | 			infos.createGraph(); | ||
|  | 		}else{ | ||
|  | 			var choiceContainer = $("#choicesLatencyVsRequest"); | ||
|  | 			createLegend(choiceContainer, infos); | ||
|  | 			infos.createGraph(); | ||
|  | 			setGraphZoomable("#flotLatenciesVsRequest", "#overviewLatenciesVsRequest"); | ||
|  | 			$('#footerLatenciesVsRequest .legendColorBox > div').each(function(i){ | ||
|  | 				$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 			}); | ||
|  | 		} | ||
|  | }; | ||
|  | 
 | ||
|  | var hitsPerSecondInfos = { | ||
|  | 		data: ${hitsPerSecond!"{}"}, | ||
|  | 		getOptions: function() { | ||
|  | 	    	return { | ||
|  | 	    		series: { | ||
|  | 	    			lines: { | ||
|  | 	    				show: true | ||
|  | 	    			}, | ||
|  | 	    			points: { | ||
|  | 	    				show: true | ||
|  | 	    			} | ||
|  | 	    		}, | ||
|  | 	    		xaxis: { | ||
|  | 	    			mode: "time", | ||
|  | 	    			timeformat: "%H:%M:%S", | ||
|  | 	    			axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 	    			axisLabelUseCanvas: true, | ||
|  | 	    			axisLabelFontSizePixels: 12, | ||
|  | 	    			axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	    			axisLabelPadding: 20, | ||
|  | 	    		}, | ||
|  | 	    		yaxis: { | ||
|  | 	    			axisLabel: "Number of hits / sec", | ||
|  | 	    			axisLabelUseCanvas: true, | ||
|  | 	    			axisLabelFontSizePixels: 12, | ||
|  | 	    			axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 	    			axisLabelPadding: 20  | ||
|  | 	    		}, | ||
|  | 	    		legend: { | ||
|  | 	    			noColumns: 2, | ||
|  | 	    			show: true,  | ||
|  | 	    			container: "#legendHitsPerSecond" | ||
|  | 	    		}, | ||
|  | 	    		selection: { | ||
|  | 	    			mode : 'xy' | ||
|  | 	    		}, | ||
|  | 	    		grid: { | ||
|  | 	    			hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 	    		}, | ||
|  | 	    		tooltip: true, | ||
|  | 	    		tooltipOpts: { | ||
|  | 	    			content: "%s for %x was %y.2" | ||
|  | 	    		} | ||
|  | 	    	}; | ||
|  | 		}, | ||
|  | 		createGraph: function createGraph() { | ||
|  | 			var data = this.data; | ||
|  | 			var dataset = prepareData(data.result.series, $("#choicesHitsPerSecond")); | ||
|  | 			var options = this.getOptions(); | ||
|  | 			prepareOptions(options, data); | ||
|  | 			$.plot($("#flotHitsPerSecond"), dataset, options); | ||
|  | 			// setup overview | ||
|  | 			$.plot($("#overviewHitsPerSecond"), dataset, prepareOverviewOptions(options)); | ||
|  | 		} | ||
|  | }; | ||
|  | 
 | ||
|  | // Hits per second | ||
|  | function refreshHitsPerSecond() { | ||
|  | 	var infos = hitsPerSecondInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if (isGraph($("#flotHitsPerSecond"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesHitsPerSecond"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotHitsPerSecond", "#overviewHitsPerSecond"); | ||
|  | 		$('#footerHitsPerSecond .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | var codesPerSecondInfos = { | ||
|  | 		data: ${codesPerSecond!"{}"}, | ||
|  | 		getOptions: function(){ | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					lines: { | ||
|  | 						show: true | ||
|  | 					}, | ||
|  | 					points: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					mode: "time", | ||
|  | 					timeformat: "%H:%M:%S", | ||
|  | 					axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: { | ||
|  | 					axisLabel: "Number of responses/sec", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 2, | ||
|  | 					show: true,  | ||
|  | 					container: "#legendCodesPerSecond" | ||
|  | 				},			 | ||
|  | 				selection: { | ||
|  | 					mode: 'xy' | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: "%s for %x was %y.2" | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 	createGraph: function() { | ||
|  | 		var data = this.data; | ||
|  | 		var dataset = prepareData(data.result.series, $("#choicesCodesPerSecond")); | ||
|  | 		var options = this.getOptions(); | ||
|  | 		prepareOptions(options, data); | ||
|  | 		$.plot($("#flotCodesPerSecond"), dataset, options); | ||
|  | 		// setup overview | ||
|  | 		$.plot($("#overviewCodesPerSecond"), dataset, prepareOverviewOptions(options)); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | // Codes per second | ||
|  | function refreshCodesPerSecond() { | ||
|  | 	var infos = codesPerSecondInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  | 	if(isGraph($("#flotCodesPerSecond"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesCodesPerSecond"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotCodesPerSecond", "#overviewCodesPerSecond"); | ||
|  | 		$('#footerCodesPerSecond .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | var transactionsPerSecondInfos = { | ||
|  | 		data: ${transactionsPerSecond!"{}"}, | ||
|  | 		getOptions: function(){ | ||
|  | 			return { | ||
|  | 				series: { | ||
|  | 					lines: { | ||
|  | 						show: true | ||
|  | 					}, | ||
|  | 					points: { | ||
|  | 						show: true | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				xaxis: { | ||
|  | 					mode: "time", | ||
|  | 					timeformat: "%H:%M:%S", | ||
|  | 					axisLabel: getElapsedTimeLabel(this.data.result.granularity), | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20, | ||
|  | 				}, | ||
|  | 				yaxis: { | ||
|  | 					axisLabel: "Number of transactions / sec", | ||
|  | 					axisLabelUseCanvas: true, | ||
|  | 					axisLabelFontSizePixels: 12, | ||
|  | 					axisLabelFontFamily: 'Verdana, Arial', | ||
|  | 					axisLabelPadding: 20 | ||
|  | 				}, | ||
|  | 				legend: { | ||
|  | 					noColumns: 2, | ||
|  | 					show: true,  | ||
|  | 					container: "#legendTransactionsPerSecond" | ||
|  | 				}, | ||
|  | 				selection: { | ||
|  | 					mode: 'xy' | ||
|  | 				}, | ||
|  | 				grid: { | ||
|  | 					hoverable: true // IMPORTANT! this is needed for tooltip to | ||
|  | 									// work | ||
|  | 				}, | ||
|  | 				tooltip: true, | ||
|  | 				tooltipOpts: { | ||
|  | 					content: "%s for %x was %y" | ||
|  | 				} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 	createGraph: function () { | ||
|  | 		var data = this.data; | ||
|  | 		var dataset = prepareData(data.result.series, $("#choicesTransactionsPerSecond")); | ||
|  | 		var options = this.getOptions(); | ||
|  | 		prepareOptions(options, data); | ||
|  | 		$.plot($("#flotTransactionsPerSecond"), dataset, options); | ||
|  | 		// setup overview | ||
|  | 		$.plot($("#overviewTransactionsPerSecond"), dataset, prepareOverviewOptions(options)); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | // Transactions per second | ||
|  | function refreshTransactionsPerSecond() { | ||
|  | 	var infos = transactionsPerSecondInfos; | ||
|  | 	prepareSeries(infos.data); | ||
|  | 	fixTimeStamps(infos.data.result.series, ${(timeZoneOffset?c)!0}); | ||
|  |     if(isGraph($("#flotTransactionsPerSecond"))){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}else{ | ||
|  | 		var choiceContainer = $("#choicesTransactionsPerSecond"); | ||
|  | 		createLegend(choiceContainer, infos); | ||
|  | 		infos.createGraph(); | ||
|  | 		setGraphZoomable("#flotTransactionsPerSecond", "#overviewTransactionsPerSecond"); | ||
|  | 		$('#footerTransactionsPerSecond .legendColorBox > div').each(function(i){ | ||
|  | 			$(this).clone().prependTo(choiceContainer.find("li").eq(i)); | ||
|  | 		}); | ||
|  | 	} | ||
|  | }; | ||
|  | 
 | ||
|  | // Collapse the graph matching the specified DOM element depending the collapsed | ||
|  | // status | ||
|  | function collapse(elem, collapsed){ | ||
|  | 	if(collapsed){ | ||
|  | 		$(elem).parent().find(".fa-chevron-up").removeClass("fa-chevron-up").addClass("fa-chevron-down"); | ||
|  | 	} else { | ||
|  | 		$(elem).parent().find(".fa-chevron-down").removeClass("fa-chevron-down").addClass("fa-chevron-up"); | ||
|  | 		if (elem.id == "bodyResponseTimeOverTime") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshResponseTimeOverTime(); | ||
|  | 			} | ||
|  | 			document.location.href="#responseTimesOverTime"; | ||
|  | 		} else if (elem.id == "bodyLantenciesOverTime") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshLatenciesOverTime(); | ||
|  | 			} | ||
|  | 			document.location.href="#latenciesOverTime"; | ||
|  | 		} else if (elem.id == "bodyResponseTimeDistribution") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshResponseTimeDistribution(); | ||
|  | 			} | ||
|  | 			document.location.href="#responseTimeDistribution" ; | ||
|  | 		} else if (elem.id == "bodyActiveThreadsOverTime") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshActiveThreadsOverTime(); | ||
|  | 			} | ||
|  | 			document.location.href="#activeThreadsOverTime"; | ||
|  | 		} else if (elem.id == "bodyResponseTimePerSample") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshResponseTimePerSample(); | ||
|  | 			} | ||
|  | 			document.location.href="#responseTimePerSample" ; | ||
|  | 		} else if (elem.id == "bodyTimeVsThreads") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshTimeVsThreads(); | ||
|  | 			} | ||
|  | 			document.location.href="#timeVsThreads" ; | ||
|  | 		} else if (elem.id == "bodyCodesPerSecond") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshCodesPerSecond(); | ||
|  | 			} | ||
|  | 			document.location.href="#codesPerSecond"; | ||
|  | 		} else if (elem.id == "bodyTransactionsPerSecond") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshTransactionsPerSecond(); | ||
|  | 			} | ||
|  | 			document.location.href="#transactionsPerSecond"; | ||
|  | 		} else if (elem.id == "bodyResponseTimeVsRequest") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshResponseTimeVsRequest(); | ||
|  | 			} | ||
|  | 			document.location.href="#responseTimeVsRequest"; | ||
|  | 		} else if (elem.id == "bodyLatenciesVsRequest") { | ||
|  | 			if (isGraph($(elem).find('.flot-chart-content')) == false) { | ||
|  | 				refreshLatenciesVsRequest(); | ||
|  | 			} | ||
|  | 			document.location.href="#latencyVsRequest"; | ||
|  | 		} | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | // Collapse | ||
|  | $(function() { | ||
|  | 		$('.collapse').on('shown.bs.collapse', function(){ | ||
|  | 			collapse(this, false); | ||
|  | 		}).on('hidden.bs.collapse', function(){ | ||
|  | 			collapse(this, true); | ||
|  | 		}); | ||
|  | }); | ||
|  | 
 | ||
|  | $(function() { | ||
|  | 	$(".glyphicon").mousedown( function(event){ | ||
|  | 		var tmp = $('.in:not(ul)'); | ||
|  | 		tmp.parent().parent().parent().find(".fa-chevron-up").removeClass("fa-chevron-down").addClass("fa-chevron-down"); | ||
|  | 		tmp.removeClass("in"); | ||
|  | 		tmp.addClass("out"); | ||
|  | 	}); | ||
|  | }); | ||
|  | 
 | ||
|  | /* | ||
|  |  * Activates or deactivates all series of the specified graph (represented by id parameter) | ||
|  |  * depending on checked argument.  | ||
|  |  */ | ||
|  | function toggleAll(id, checked){ | ||
|  | 	var placeholder = document.getElementById(id); | ||
|  | 	 | ||
|  | 	var cases = $(placeholder).find(':checkbox'); | ||
|  |    | ||
|  | 	cases.attr('checked', checked); | ||
|  | 	$(cases).parent().children().children().toggleClass("legend-disabled", !checked); | ||
|  | 	 | ||
|  | 	var choiceContainer; | ||
|  | 	if ( id == "choicesBytesThroughputOverTime"){ | ||
|  | 		choiceContainer = $("#choicesBytesThroughputOverTime"); | ||
|  | 		refreshBytesThroughputOverTime(); | ||
|  | 	} else if(id == "choicesResponseTimesOverTime"){ | ||
|  | 		choiceContainer = $("#choicesResponseTimesOverTime"); | ||
|  | 		refreshResponseTimeOverTime(); | ||
|  | 	} else if ( id == "choicesLatenciesOverTime"){ | ||
|  | 		choiceContainer = $("#choicesLatenciesOverTime"); | ||
|  | 		refreshLatenciesOverTime(); | ||
|  | 	} else if ( id == "choicesResponseTimePercentiles"){ | ||
|  | 		choiceContainer = $("#choicesResponseTimePercentiles"); | ||
|  | 		refreshResponseTimePercentiles(); | ||
|  | 	} else if(id == "choicesActiveThreadsOverTime"){ | ||
|  | 		choiceContainer = $("#choicesActiveThreadsOverTime"); | ||
|  | 		refreshActiveThreadsOverTime(); | ||
|  | 	} else if ( id == "choicesTimeVsThreads"){ | ||
|  | 		choiceContainer = $("#choicesTimeVsThreads"); | ||
|  | 		refreshTimeVsThreads(); | ||
|  | 	} else if ( id == "choicesResponseTimeDistribution"){ | ||
|  | 		choiceContainer = $("#choicesResponseTimeDistribution"); | ||
|  | 		refreshResponseTimeDistribution(); | ||
|  | 	} else if ( id == "choicesResponseTimePerSample"){ | ||
|  | 		choiceContainer = $("#choicesResponseTimePerSample"); | ||
|  | 		refreshResponseTimePerSample(); | ||
|  | 	} else if ( id == "choicesHitsPerSecond"){ | ||
|  | 		choiceContainer = $("#choicesHitsPerSecond"); | ||
|  | 		refreshHitsPerSecond(); | ||
|  | 	} else if(id == "choicesCodesPerSecond"){ | ||
|  | 		choiceContainer = $("#choicesCodesPerSecond"); | ||
|  | 		refreshCodesPerSecond(); | ||
|  | 	} else if ( id == "choicesTransactionsPerSecond"){ | ||
|  | 		choiceContainer = $("#choicesTransactionsPerSecond"); | ||
|  | 		refreshTransactionsPerSecond(); | ||
|  | 	} else if ( id == "choicesResponseTimeVsRequest"){ | ||
|  | 		choiceContainer = $("#choicesResponseTimeVsRequest"); | ||
|  | 		refreshResponseTimeVsRequest(); | ||
|  | 	} else if ( id == "choicesLatencyVsRequest"){ | ||
|  | 		choiceContainer = $("#choicesLatencyVsRequest"); | ||
|  | 		refreshLatenciesVsRequest(); | ||
|  | 	} | ||
|  | 	var color = checked ? "black" : "#818181"; | ||
|  | 	choiceContainer.find("label").each(function(){ | ||
|  | 		this.style.color = color; | ||
|  | 	}); | ||
|  | } | ||
|  | 
 | ||
|  | // Unchecks all boxes for "Hide all samples" functionality | ||
|  | function uncheckAll(id){ | ||
|  | 	toggleAll(id, false); | ||
|  | } | ||
|  | 
 | ||
|  | // Checks all boxes for "Show all samples" functionality | ||
|  | function checkAll(id){ | ||
|  | 	toggleAll(id, true); | ||
|  | } | ||
|  | 
 | ||
|  | // Prepares data to be consumed by plot plugins | ||
|  | function prepareData(series, choiceContainer, customizeSeries){ | ||
|  | 	var datasets = []; | ||
|  | 	 | ||
|  | 	// Add only selected series to the data set | ||
|  | 	choiceContainer.find("input:checked").each(function (index, item) { | ||
|  | 		var key = $(item).attr("name"); | ||
|  | 		var i = 0; | ||
|  | 		var size = series.length;  | ||
|  | 		while(i < size && series[i].label != key) | ||
|  | 			i++; | ||
|  | 		if(i < size){ | ||
|  | 			var currentSeries = series[i]; | ||
|  | 			datasets.push(currentSeries); | ||
|  | 			if(customizeSeries) | ||
|  | 				customizeSeries(currentSeries); | ||
|  | 		} | ||
|  | 	}); | ||
|  | 	return datasets; | ||
|  | } | ||
|  | 
 | ||
|  | // create slider | ||
|  | $(function() { | ||
|  |     $( "#slider-vertical" ).slider({ | ||
|  |       orientation: "vertical", | ||
|  |       range: "min", | ||
|  |       min: responseTimePercentilesInfos.data.result.minY, | ||
|  |       max: responseTimePercentilesInfos.data.result.maxY, | ||
|  |       value: 0, | ||
|  |       stop: function(event, ui ) { | ||
|  |        percentileThreshold= ui.value; | ||
|  | 	   refreshResponseTimePercentiles(); | ||
|  | 	   $("#amount").val(percentileThreshold); | ||
|  |       } | ||
|  |     }); | ||
|  |     $("#amount" ).val( $( "#slider-vertical" ).slider( "value" ) ); | ||
|  | 	$("#slider-vertical").children("div").css("background-color","purple"); | ||
|  | 	$("#amount" ).css("color", $("#slider-vertical").children("div").css("background-color")); | ||
|  | 	$("#slider-vertical").children("div").css("opacity","0.3"); | ||
|  | }); | ||
|  | 
 | ||
|  | /* | ||
|  |  * Ignore case comparator  | ||
|  |  */ | ||
|  | function sortAlphaCaseless(a,b){ | ||
|  |     return a.toLowerCase() > b.toLowerCase() ? 1 : -1; | ||
|  | }; | ||
|  | 
 | ||
|  | /* | ||
|  |  * Creates a legend in the specified element with graph information | ||
|  |  */ | ||
|  | function createLegend(choiceContainer, infos) { | ||
|  | 	// Sort series by name | ||
|  |     var keys = []; | ||
|  |     $.each(infos.data.result.series, function(index, series){ | ||
|  |     	keys.push(series.label); | ||
|  |     }); | ||
|  |     keys.sort(sortAlphaCaseless); | ||
|  | 	 | ||
|  |     // Create list of series with support of activation/deactivation | ||
|  |     $.each(keys, function(index, key) { | ||
|  | 		var id = choiceContainer.attr('id') + index; | ||
|  | 		$('<li />') | ||
|  | 			.append($('<input id="' + id + '" name="' + key + '" type="checkbox" checked="checked" hidden />')) | ||
|  | 			.append($('<label />', { 'text': key , 'for': id })) | ||
|  | 			.appendTo(choiceContainer); | ||
|  | 	}); | ||
|  | 	choiceContainer.find("label").click( function(){ | ||
|  | 		if (this.style.color !== "rgb(129, 129, 129)" ){ | ||
|  | 			this.style.color="#818181"; | ||
|  | 		}else { | ||
|  | 			this.style.color="black"; | ||
|  | 		} | ||
|  | 		$(this).parent().children().children().toggleClass("legend-disabled"); | ||
|  | 	}); | ||
|  | 	choiceContainer.find("label").mousedown( function(event){ | ||
|  | 		event.preventDefault(); | ||
|  | 	}); | ||
|  | 	choiceContainer.find("label").mouseenter(function(){ | ||
|  | 		this.style.cursor="pointer"; | ||
|  | 	}); | ||
|  | 	 | ||
|  | 	// Recreate graphe on series activation toggle | ||
|  | 	choiceContainer.find("input").click(function(){ | ||
|  | 		infos.createGraph(); | ||
|  | 	}); | ||
|  | } |