0

我正在使用 jmeter 在网站上执行负载测试。Jmeter 以 CSV 文件的形式生成输出。

我想使用这个 CSV 文件生成条形图。为了生成图表,我使用 D3 和 Crossfilter。

为此,我参考了http://square.github.io/crossfilter/ 并根据我的 CSV 文件要求通过编辑使用了相同的代码。

它显示以下错误:-

Error: Problem parsing d="M230,100V50h9V100MNaN,100V0h9V100" index.html:1 2 Error: Problem parsing d="M230,100V100h9V100MNaN,100V100h9V100" d3.v3.min.js:1 46 Error: Problem parsing d="M230,100V100h9V100MNaN,100V100h9V100" d3.v3.min.js:1 114 Error: Problem parsing d="M230,100V100h9V100MNaN,100V0h9V100" d3.v3.min.js:1 30

我的 CSV 文件是:

timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,bytes,grpThreads,allThreads,Latency,Hostname
12/25/2012 0:02,2417,/ratings/rate.php,200,OK,Thread Group 1-1,text,TRUE,1067,1,1,2417,PRAVIN-PC
12/25/2012 0:02,3784,/ratings/rate.php,200,OK,Thread Group 1-1,text,TRUE,913,1,1,3783,PRAVIN-PC
12/25/2012 0:12,3121,/gampad/ads,200,OK,Thread Group 1-1,text,TRUE,1214,1,1,3121,PRAVIN-PC

`

我的 HTML 文件代码是:

<style>
 body {
    font-family: "Helvetica Neue";
    margin: 40px auto;
    width: 960px;
    min-height: 2000px;
   }

   #body {
   position: relative;
   }

   footer {
     padding: 2em 0 1em 0;
     font-size: 12px;
   }

   h1 {
     font-size: 96px;
     margin-top: .3em;
     margin-bottom: 0;
   }

   h1 + h2 {
     margin-top: 0;
   }

   h2 {
     font-weight: 400;
     font-size: 28px;
   }

   h1, h2 {
     font-family: "Yanone Kaffeesatz";
     text-rendering: optimizeLegibility;
   }

   #body > p {
     line-height: 1.5em;
     width: 640px;
     text-rendering: optimizeLegibility;
   }

   #charts {
     padding: 10px 0;
   }

   .chart {
     display: inline-block;
     height: 151px;
     margin-bottom: 20px;
   }

   .reset {
     padding-left: 1em;
     font-size: smaller;
     color: #ccc;
   }

   .background.bar {
     fill: #ccc;
   }

   .foreground.bar {
     fill: steelblue;
   }

   .axis path, .axis line {
     fill: none;
     stroke: #000;
     shape-rendering: crispEdges;
   }

   .axis text {
     font: 10px sans-serif;
   }

   .brush rect.extent {
     fill: steelblue;
     fill-opacity: .125;
   }

   .brush .resize path {
     fill: #eee;
     stroke: #666;
   }

   #hour-chart {
     width: 260px;
   }

   #delay-chart {
     width: 230px;
   }

   #distance-chart {
     width: 420px;
   }

   #date-chart {
     width: 920px;
   }

   #flight-list {
     min-height: 1024px;
   }

   #flight-list .date,
   #flight-list .day {
     margin-bottom: .4em;
   }

   #flight-list .flight {
     line-height: 1.5em;
     background: #eee;
     width: 640px;
     margin-bottom: 1px;
   }

   #flight-list .time {
     color: #999;
   }

   #flight-list .flight div {
     display: inline-block;
     width: 100px;
   }

   #flight-list div.distance,
   #flight-list div.delay {
     width: 160px;
     padding-right: 10px;
     text-align: right;
   }

   #flight-list .early {
     color: green;
   }

   aside {
     position: absolute;
     left: 740px;
     font-size: smaller;
     width: 220px;
   }

   </style>

   <div id="body">

   <div id="charts">
     <div id="hour-chart" class="chart">
       <div class="title">Time of Day</div>
     </div></br>
   <div id="delay-chart" class="chart">
       <div class="title">Page Load Time (ms.)</div>
   </div>
   <!--  <div id="distance-chart" class="chart">
       <div class="title">Visit Time    (mi.)</div>
     </div>
     <div id="date-chart" class="chart">
        <div class="title">Date</div>
      </div>-->
   </div>

   <aside id="totals"><span id="active">-</span> of <span id="total">-</span> Visits selected.</aside>

   <div id="lists">
     <div id="flight-list" class="list"></div>
   </div>

   <footer>
     <span style="float:right;">
       Released under the <a href="http://www.apache.org/licenses/LICENSE-     2.0.html">Apache License 2.0</a>.
     </span>
       Copyright 2012 <a href="http://squareup.com">Square, Inc.</a>
     </footer>

   </div>

   <script src="crossfilter.min.js"></script>
   <script src="d3.v3.min.js"></script>
   <script>

   // (It's CSV, but GitHub Pages only gzip's JSON at the moment.)
   d3.csv("resultofcommandline.csv", function(flights) {
        // A nest operator, for grouping the flight list.
    var nestByDate = d3.nest()
    .key(function(d) { return d3.time.day(d.date); });

 // A little coercion, since the CSV is untyped.
flights.forEach(function(d, i) {
    d.index = i;
    d.timeStamp = parseDate(d.timeStamp);
    d.Latency = +d.Latency;
});

    // Create the crossfilter for the relevant dimensions and groups.
     var flight = crossfilter(flights),
     all = flight.groupAll(),
     hour = flight.dimension(function(d) { return d.timeStamp.getHours() +  d.timeStamp.getMinutes() / 60; }),
    hours = hour.group(Math.floor),
    latency = flight.dimension(function(d) {return Math.min(1999, d.Latency);}),
    latencys = latency.group(function (d){  return Math.floor(d/50)*50 ;});
  var charts = [
    barChart()
        .dimension(latency)
        .group(latencys)
        .x(d3.scale.linear()
        .domain([0, 2000])
        .rangeRound([0, 10 * 40])),
    barChart()
        .dimension(hour)
        .group(hours)
        .x(d3.scale.linear()
        .domain([0, 24])
        .rangeRound([0, 10 * 24]))
    ];

    // Given our array of charts, which we assume are in the same order as the
    // .chart elements in the DOM, bind the charts to the DOM and render them.
    // We also listen to the chart's brush events to update the display.
    var chart = d3.selectAll(".chart")
                .data(charts)
                .each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); });
    renderAll();

    // Renders the specified chart or list.
    function render(method) {
        d3.select(this).call(method);
    }
    // Whenever the brush moves, re-rendering everything.
    function renderAll() {
        chart.each(render);
    }

    // Like d3.time.format, but faster.
    function parseDate(d) {
        return new Date(d.substring(6,10),
            d.substring(0, 2) - 1,
            d.substring(3, 5),
            d.substring(11, 13),
            d.substring(14, 16));
    }
    window.filter = function(filters) {
        filters.forEach(function(d, i) { charts[i].filter(d); });
        renderAll();
    };

    window.reset = function(i) {
            charts[i].filter(null);
            renderAll();
    };

    function barChart() {
        if (!barChart.id) barChart.id = 0;

        var margin = {top: 10, right: 10, bottom: 20, left: 10},
        x,
        y = d3.scale.linear().range([100, 0]),
        id = barChart.id++,
        axis = d3.svg.axis().orient("bottom"),
        brush = d3.svg.brush(),
        brushDirty,
        dimension,
        group,
        round;

        function chart(div) {
            var width = x.range()[1],
            height = y.range()[0];
            y.domain([0, group.top(1)[0].value]);

        div.each(function() {
                var div = d3.select(this),
                g = div.select("g");

        // Create the skeletal chart.
        if (g.empty()) {
            div.select(".title").append("a")
            .attr("href", "javascript:reset(" + id + ")")
            .attr("class", "reset")
            .text("reset")
            .style("display", "none");
        g = div.append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
        g.append("clipPath")
            .attr("id", "clip-" + id)
            .append("rect")
            .attr("width", width)
            .attr("height", height);
        g.selectAll(".bar")
            .data(["background", "foreground"])
            .enter().append("path")
            .attr("class", function(d) { return d + " bar"; })
            .datum(group.all());
        g.selectAll(".foreground.bar")
            .attr("clip-path", "url(#clip-" + id + ")");
        g.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(0," + height + ")")
            .call(axis);
        // Initialize the brush component with pretty resize handles.
        var gBrush = g.append("g").attr("class", "brush").call(brush);
        gBrush.selectAll("rect").attr("height", height);
        gBrush.selectAll(".resize").append("path").attr("d", resizePath);
    }

    // Only redraw the brush if set externally.
    if (brushDirty) {
        brushDirty = false;
        g.selectAll(".brush").call(brush);
        div.select(".title a").style("display", brush.empty() ? "none" : null);
        if (brush.empty()) {
            g.selectAll("#clip-" + id + " rect")
                .attr("x", 0)
                .attr("width", width);
     } 
     else {
        var extent = brush.extent();
        g.selectAll("#clip-" + id + " rect")
            .attr("x", x(extent[0]))
            .attr("width", x(extent[1]) - x(extent[0]));
      }
    }

    g.selectAll(".bar").attr("d", barPath);
  });

  function barPath(groups) {
    var path = [],
        i = -1,
        n = groups.length,
        d;
    while (++i < n) {
      d = groups[i];
      path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height);
    }
    return path.join("");
  }

  function resizePath(d) {
    var e = +(d == "e"),
        x = e ? 1 : -1,
        y = height / 3;
    return "M" + (.5 * x) + "," + y
        + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
        + "V" + (2 * y - 6)
        + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
        + "Z"
        + "M" + (2.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8)
        + "M" + (4.5 * x) + "," + (y + 8)
        + "V" + (2 * y - 8);
  }
}

brush.on("brushstart.chart", function() {
  var div = d3.select(this.parentNode.parentNode.parentNode);
  div.select(".title a").style("display", null);
});

brush.on("brush.chart", function() {
  var g = d3.select(this.parentNode),
      extent = brush.extent();
  if (round) g.select(".brush")
      .call(brush.extent(extent = extent.map(round)))
    .selectAll(".resize")
      .style("display", null);
  g.select("#clip-" + id + " rect")
      .attr("x", x(extent[0]))
      .attr("width", x(extent[1]) - x(extent[0]));
  dimension.filterRange(extent);
});

brush.on("brushend.chart", function() {
  if (brush.empty()) {
    var div = d3.select(this.parentNode.parentNode.parentNode);
    div.select(".title a").style("display", "none");
    div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%");
    dimension.filterAll();
  }
});

chart.margin = function(_) {
  if (!arguments.length) return margin;
  margin = _;
  return chart;
};

chart.x = function(_) {
  if (!arguments.length) return x;
  x = _;
  axis.scale(x);
  brush.x(x);
  return chart;
};

chart.y = function(_) {
  if (!arguments.length) return y;
  y = _;
  return chart;
};

chart.dimension = function(_) {
  if (!arguments.length) return dimension;
  dimension = _;
  return chart;
};

chart.filter = function(_) {
  if (_) {
    brush.extent(_);
    dimension.filterRange(_);
  } else {
    brush.clear();
    dimension.filterAll();
  }
  brushDirty = true;
  return chart;
};

chart.group = function(_) {
  if (!arguments.length) return group;
  group = _;
  return chart;
};

chart.round = function(_) {
  if (!arguments.length) return round;
  round = _;
  return chart;
};

return d3.rebind(chart, brush, "on");
 }
 });

 </script>
4

1 回答 1

1

问题是您的parseDate()函数采用hh:mm时间格式,但您的数据包含h:mm条目。因此,您必须要么更改输入数据的格式,要么调整解析功能。

我更改了您提供的 3 个示例行,请在此处查看工作示例!

于 2013-04-26T08:22:31.563 回答