Kristof Jozsa wrote:
Hi Ronan,

Ronan Klyne wrote:
- while I woulnd't call the Graph Results component unusable, it's far from being very useful when you want quality reports :)
I use XML logs and XSL to generate my own reports - I find that I can get all I need with the mathematical capabilities of XSLT2.0 and usiogn SVG for my graphs.

Would you mind sharing your XSL tricks? The SVG graphs sound very good.. I used the CSV logs, preprocessed as described in the wiki and used Excel tricks to generate any decent results, but it was quite a pain to do it, and the results are quite far from being very nice..

This requires XSLT2 - I use Saxon 9 as a processor.

I use this code to generate a tree fragment in memory, which describes the graph data:
(You'll certainly have to modify this)

    <xsl:variable name="data">
      <xsl:for-each select="distinct-values($groups/group/*/@lb)">
        <xsl:sort select="." data-type="text"/>
        <xsl:variable name="lb" select="." />
        <node label="{$lb}" value="-1" colour="#BFBFFF"/>
        <xsl:for-each select="$groups/group">
          <xsl:sort select="@threads" data-type="number"/>
          <xsl:variable name="group" select="."/>
<xsl:variable name="times" select="$group/[EMAIL PROTECTED]'true' and @lb=$lb and @t]/@t" />
          <xsl:variable name="perc">
            <xsl:call-template name="percentiles">
              <xsl:with-param name="responsetimes" select="$times" />
              <xsl:with-param name="percentile" select="0.95" />
            </xsl:call-template>
          </xsl:variable>
          <node label="{$group/@threads}" value="0{$perc}"/>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:variable>

<snip/>

And this template to generate the SVG graph from that data:

<xsl:template name="graph">
  <xsl:param name="data"/>
  <xsl:param name="graph_height" select="$def_graph_height"/>
  <xsl:param name="left_margin" select="20"/>
  <xsl:param name="graph_width" select="$def_graph_width"/>
<xsl:param name="bar_width" select="2*(($graph_width - 2*$left_margin) div (3*count($data/node)))"/> <xsl:param name="bar_spacing" select="1*(($graph_width - 2*$left_margin) div (3*count($data/node)))"/>

  <xsl:variable name="bar_count" select="count($data/node)"/>
  <xsl:message select="concat('Graph name: ', $data/node[1]/@label)" />
  <xsl:variable name="max_time" select="max($data/node/@value)" />
  <xsl:message select="concat('$max_time: ', $max_time)" />
  <xsl:variable name="fix_scale" select="55000" />
  <xsl:variable name="max_graph_height">
    <xsl:choose>
      <xsl:when test="$fix_scale &gt;= 0">
        <xsl:value-of select="$fix_scale"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="floor(($max_time + 999) div 1000) * 1000"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
<xsl:variable name="actual_width" select="($bar_count * ($bar_width + $bar_spacing)) + $bar_spacing"/> <svg:svg id="body" viewBox="-50 -50 {$graph_width + 100} {$graph_height + 100}">
    <svg:title>Some title</svg:title>
    <!-- main graphic -->
<svg:g id="barChart" transform="translate(10, 10)" fill-rule="nonzero" clip-rule="nonzero" stroke="none" class="legend" stroke-width="1" stroke-linecap="square" stroke-miterlimit="1" style="text-anchor:start" shape-rendering="crispEdges"> <svg:g id="GridAndLegend" style="stroke:none;" shape-rendering="crispEdges" stroke-width="1">
          <!-- back face and surrounding lines -->
<svg:path fill="lightgray" stroke="black" d="M $left_margin,{$graph_height + 20} h{$actual_width} v-{$graph_height} h-{$actual_width} v{$graph_height}"/>
          <!-- draw zero mark and legend -->
<svg:path fill="none" stroke="black" d="M {$left_margin - 10},{$graph_height + 20} h10"/> <svg:text text-anchor="end" baseline-shift="-3" transform="matrix(1 0 0 1 {$left_margin - 15} {$graph_height + 20})">0</svg:text>
          <xsl:variable name="step" select="$max_graph_height idiv 10"/>
          <xsl:if test="$step = 0">
            <xsl:message select="$data"/>
          </xsl:if>
          <xsl:if test="$step > 0">
<xsl:for-each select="for $i in 1 to ($max_graph_height idiv $step) return $step * $i"> <xsl:variable name="vert_posn" select="(. div $max_graph_height) * $graph_height"/> <svg:path fill="none" stroke="black" d="M {$left_margin - 10},{$graph_height + 20 - floor($vert_posn)} h{$actual_width + 10}"/> <svg:text text-anchor="end" baseline-shift="-3" transform="matrix(1 0 0 1 {$left_margin - 15} {$graph_height + 20 - floor($vert_posn)})">
              <xsl:value-of select="."/>
            </svg:text>
          </xsl:for-each>
          </xsl:if>
        </svg:g>

        <!-- draw the graph bars themselves from data -->
        <xsl:for-each select="$data/node">
<xsl:variable name="value" select="if (@value >=0) then @value else $max_graph_height"/> <xsl:variable name="bar_height" select="floor(($value div $max_graph_height) * $graph_height)"/> <xsl:variable name="bar_left" select="((position() - 1) * ($bar_width + $bar_spacing)) + $bar_spacing"/> <xsl:variable name="colour" select="if (@colour) then @colour else 'blue'" />
          <!-- draw the bar -->
<svg:path fill="{$colour}" stroke="none" d="M {$bar_left + $left_margin},{$graph_height + 19} h{$bar_width} v-{$bar_height} h-{$bar_width} v{$bar_height}"/>
          <!-- draw the label -->
<!--xsl:if test="not (./preceding-sibling::*[1][substring-after(@label, '-') = substring-after(current()/@label, '-')])"--> <svg:text text-anchor="left" transform="matrix(0 -1 1 0 {$left_margin + $bar_left + ($bar_width div 2) + 1} {$graph_height + 40})">
              <xsl:value-of select="@label"/>
            </svg:text>
          <!--/xsl:if-->
        </xsl:for-each>
<!--svg:text transform="matrix(2 0 0 2 {$left_margin} {$graph_height + 70})">Operation scaling</svg:text-->
    </svg:g>
  </svg:svg>
</xsl:template>



<snip/>

Then this code to put the graph in a file.

    <xsl:if test="$data/node">
      <xsl:result-document href="graph-{$graph-name}" format="svg">
        <xsl:call-template name="graph">
          <xsl:with-param name="data" select="$data" />
        </xsl:call-template>
      </xsl:result-document>
    </xsl:if>

This depends on having the named output method 'svg' described at the top of the document, thusly:

<xsl:output name="svg" method="xml" indent="yes" encoding="UTF-8" />

This will probably need a lot of customisation to produce what you need, but should serve as a starting point. I wouldn't want anyone to have to go through writing a bar chart from scratch in XSL again ;)

Yours,

        Ronan



--
Ronan Klyne
Business Collaborator Developer
Tel: +44 01189 028518
[EMAIL PROTECTED]
www.groupbc.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to