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 >= 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]