There runs yet another daemon, the so called Tapper::Reports::API
, on the same host where already the TAP Receiver
runs. This Reports API
is meant for everything that needs more than just dropping TAP reports to a port, e.g., some interactive dialog or parameters.
This Tapper::Reports::API
listens on Port 7358
. Its API is modeled after classic unix script look&feel with a first line containing a description how to interpret the rest of the lines.
The first line consists of a shebang (#!
), a api command
and command parameters
. The rest of the file is the payload
for the api command
.
The syntax of the command params
varies depending on the api command
to make each command intuitively useable. Sometimes they are just positional parameters, sometimes they look like the start of a HERE document (i.e., they are prefixed with <<
as you can see below).
In this section the raw API is described. That's the way you can use without any dependencies except for the minimum ability to talk to a port, e.g., via netcat
.
See section Client Utility tapper-api for how to use a dedicated command line utility that makes talking to the reports API easier, but is a dependency that might not be available in your personal test environment.
This api command lets you upload files, aka. attachments, to reports. These files are available later through the web interface. Use this to attach log files, config files or console output.
#! upload REPORTID FILENAME [ CONTENTTYPE ]
payload
REPORTID
The id of the report to which the file is assigned
FILENAME
The name of the file
CONTENTTYPE
Optional MIME type; defaults to
plain
; useapplication/octet-stream
to make it downloadable later in browser.
The raw content of the file to upload.
Just echo
the first api-command line and then immediately cat
the file content:
$ ( echo "#! upload 552 xyz.tmp" ; cat xyz.tmp ) | netcat -w1 bascha 7358
This api command lets you download files, aka. attachments, from reports.
#! upload REPORTID FILENAME
There is no other payload neccessary here, just this single line.
REPORTID
The id of the report to which the file is assigned
FILENAME
The name of the file as it was specified on upload
Just echo
the first api-command line and redirect the answer into a file.
$ ( echo "#! download 552 xyz.tmp" ) | netcat -w1 bascha 7358 > xyz.tmp
To query report results we provide sending templates to the API in which you can use a query language to get report details: This api-command is called like the template engine so that we can provide other template engines as well.
#! mason debug=0 <<ENDMARKER
payload
ENDMARKER
debug=1
If
debug
is specified and value set to 1 then any error message that might occur is reported as result content. If debug is omitted or false and an error occurs then the result is just empty.<<ENDMARKER
You can choose any word instead of ENDMARKER which should mark the end of input, like in HERE documents, usually some word that is not contained in the template payload.
A mason template.
Mason
is a template language, see http://masonhq.com. Inside the template we provide a function reportdata
to access report data via a query language. See section Query language DPath for details about this.
This is a raw Mason template:
% my $world = "Mason World";
Hello <% $world %>!
% my @res = reportdata '{ "suite.name" => "perfmon" } :: //tap/tests_planned';
Planned perfmon tests:
% foreach (@res) {
<% $_ %>
% }
If you want to submit such a Mason template you can add the api-command line and the EOF marker like this:
$ EOFMARKER="MASONTEMPLATE".$$
$ payload_file="perfmon_tests_planned.mas"
$ ( echo "#! mason <<$EOFMARKER" ; cat $payload_file ; echo "$EOFMARKER" ) \
| netcat -w1 bascha 7358
The output of this is the rendered template. You can extend the line to save the rendered result into a file:
$ ( echo "#! mason <<$EOFMARKER" ; cat $payload_file ; echo "$EOFMARKER" ) \
| netcat -w1 bascha 7358 > result.txt
The answer for this looks like this:
Hello Mason World!
Planned perfmon tests:
3
4
17
The query language, which is the argument to the reportdata
as used embedded in the mason
examples above:
reportdata '{ "suite.name" => "perfmon" } :: //tap/tests_planned'
consists of 2 parts, divided by the ::
.
We call the first part in braces reports filter and the second part data filter.
The reports filter selects which reports to look at. The expression inside the braces is actually a complete SQL::Abstract
expression (http://search.cpan.org/~mstrout/SQL-Abstract/) working internally as a select
in the context of the object relational mapper, which targets the table Report
with an active JOIN to the table Suite
.
All the matching reports are then taken to build a data structure for each one, consisting of the table data and the parsed TAP part which is turned into a data structure via TAP::DOM
(http://search.cpan.org/~schwigon/TAP-DOM/).
The data filter works then on that data structure for each report.
The filter expressions are best described by example:
Select a report by ID { 'id' => 1234 }
Select a report by suite name { 'suite_name' => 'oprofile' }
Select a report by machine name { 'machine_name' => 'bascha' }
Select a report by date
Here the value that you want to select is a structure by itself, consisting of the comparison operator and a time string:
{ 'created_at' => { '<', '2009-04-09 10:00' } }
The data structure that is created for each report can be evaluated using the data filter part of the query language, i.e., everything after the ::
. This part is passed through to Data::DPath
(http://search.cpan.org/~schwigon/Data-DPath/).
Using the query language can be slow. The biggest slowdown occurs with the ANYWHERE
element //
, again with several of them, because they span up a big search tree.
Therefore, if you know the depth of your path, try to replace the //
with some *
because that only spans up on the current step not every possible step, like this:
{ ... } :: //section/stats-proc-interrupts-before//tap//data/TLB";
{ ... } :: /results/*/section/stats-proc-interrupts-before/tap/lines/*/_children/*/data/TLB";
There is a command line utility tapper-api
that helps with using the API without the need to talk the protocol and fiddle with netcat
by yourself.
You can aquire a help page to each sub command:
$ /opt/tapper/perl/bin/tapper-api help upload
prints
tapper-api upload --reportid=s --file=s [ --contenttype=s ]
--verbose some more informational output
--reportid INT; the testrun id to change
--file STRING; the file to upload, use '-' for STDIN
--contenttype STRING; content-type, default 'plain',
use 'application/octed-stream' for binaries
Use it from the Tapper path, like:
$ /opt/tapper/perl/bin/tapper-api upload \
--file /var/log/messages \
--reportid=301
You can also use the special filename - to read from STDIN, e.g., if you need to pipe the output of tools like dmesg
:
$ dmesg | /opt/tapper/perl/bin/tapper-api upload \
--file=- \
--filename dmesg \
--reportid=301
TODO