Add `sink.text.details`, a testing textual sink which prints details
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 8 Jun 2019 00:26:34 +0000 (20:26 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Mon, 17 Jun 2019 20:56:59 +0000 (16:56 -0400)
commit55478183b5a100be028ed476718f0773ec7b4af5
tree225c428a6e6c8d4a1df9446750d6d7af044869f3
parentae83436ea714ed6a8a97c54f8128ab6b63ed557d
Add `sink.text.details`, a testing textual sink which prints details

This patch adds a new sink component class, `sink.text.details`. Such
a sink component prints all the messages and their details, including
the full metadata objects, in a deterministic way.

You can test it easily like this:

    babeltrace2 /path/to/trace -c sink.text.details

The purpose of this sink is to use it for regression testing using the
following approach:

1. Run the `babeltrace2` program with a `sink.text.details` component,
   providing a known input trace to the graph, for example a CTF trace
   with `src.ctf.fs`. The graph can include one or more filters with
   specific parameters to test them specifically.

2. Inspect the output with your human eyes and brain. Verify that
   everything is as expected. It is possible that, for a given test,
   some elements of the output are less important (for example, the
   metadata objects or the message times): there are component
   parameters to remove parts of the output to reduce the noise.

3. Save the output of 2. to a file.

4. Create a test which runs 1. with the same input and compares its
   output to the file saved in 3. Any regression will show up as a
   difference between both inputs.

Step 2. is particularly important because this is where you validate
that the output shows what you expect from the graph. To make this
easier, I tried to make the output format of `sink.text.details` as
human-readable as possible:

* The component optionally colorizes the output. This is the default
  when the terminal supports it. There's no color codes by default when
  you redirect the output.

* The component honors the preferred display base of integer fields and
  prepends the typical `0x` and `0` prefixes.

* The component inserts digit separators to make it easier to read large
  numbers, for example `102,354,895,784,619` and `0x7f4d:d04f:c636`.

* The component does not print the metadata objects interlaced with the
  data and message objects. I found that this was noisy, for example
  showing all the integer field class details for each integer field
  when what you really want is to inspect the event payloads from one
  message to the other.

  Instead, I chose to print trace classes, stream classes, and event
  classes only once, and before the message which is associated to them.
  This typically occurs before a stream beginning message, but for event
  classes, it can also occur before an event message, as a source can
  add event classes to an existing stream class.

* The component assigns a unique ID to each trace object to follow the
  messages associated to a specific stream more easily, as many streams
  can share the same ID, across difference traces or even with the same
  trace, when they have different stream classes.

  The component prints this unique trace ID, as well as the stream
  class and stream IDs, before each message type as such
  (`{Trace 1, Stream class ID 0, Stream ID 2}` in the following
  example):

      [102,354,895,784,619 cycles, 1,441,852,773,172,610,636 ns from origin]
      {Trace 1, Stream class ID 0, Stream ID 2}
      Event `lttng_ust_statedump:build_id` (Class ID 56):
        Common context:
          vpid: 17,868
          ip: 0x7f4d:d04f:c636
        Payload:
          baddr: 0x7f4d:d02d:1000
          ...

  A unique trace ID is never reused for two different traces within the
  lifetime of a `sink.text.details` component.

  You can track all the messages of a given stream with this unique
  tuple. For example, you can find the last packet beginning message for
  the packet of a given event message having unique trace ID 0, stream
  class ID 2, and stream ID 5 by finding the last

      {Trace 0, Stream class ID 2, Stream ID 5}
      Packet beginning

  string.

  This makes it possible to avoid redundancy and reduce textual noise in
  the printed messages. For example, the component does not print the
  packet context field for each event message, but only for the packet
  beginning message.

In order to make step 4. continue to work in the future and really test
regressions, the output of step 1. must always be the same
(deterministic). For `sink.text.details`, this means:

* The component does not print run-time addresses.

* The component sorts mappings of enumeration field classes (by label),
  and ranges within such mappings, before it prints them.

* The component sorts event classes of stream classes (by ID) before
  it prints them.

* The component sorts stream classes of trace classes (by ID) before
  it prints them.

* The component sorts streams of traces (by ID and class ID) before
  it prints them.

* The component sorts environment entries of trace classes (by name)
  before it prints them.

To make step 3. easier, the component does not print trailing spaces
or trailing empty lines.

A `sink.text.details` component can also be used for support if we want
all the details of a given graph's output.

The available component parameters are:

`color`:
  `never`, `auto`, or `always` (just like `sink.text.pretty`).

  Default: `auto`

`with-metadata`:
  True to print metadata objects (only the first time they are
  encountered).

  Default: true

`with-time`:
  True to print message times.

  Default: true

`with-trace-class-name`:
  True to print trace class names.

  Default: true

`with-trace-name`:
  True to print trace names.

  Default: true

`with-stream-class-name`:
  True to print stream class names.

  Default: true

`with-stream-name`:
  True to print stream names.

  Default: true

`with-uuid`:
  True to print UUIDs.

  Default: true

`compact`:
  True to make the output compact (one message per line, no property
  names).

  Default: false

This patch does not add the facilities to create tests easily using the
CLI and a `sink.text.details` component: this is reserved for a future
patch.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I9cc39cdfe44436974600388342029a2e4e2acb76
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1412
Tested-by: jenkins
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
14 files changed:
configure.ac
src/cli/babeltrace2.c
src/plugins/text/Makefile.am
src/plugins/text/details/Makefile.am [new file with mode: 0644]
src/plugins/text/details/colors.h [new file with mode: 0644]
src/plugins/text/details/details.c [new file with mode: 0644]
src/plugins/text/details/details.h [new file with mode: 0644]
src/plugins/text/details/logging.c [new file with mode: 0644]
src/plugins/text/details/logging.h [new file with mode: 0644]
src/plugins/text/details/obj-lifetime-mgmt.c [new file with mode: 0644]
src/plugins/text/details/obj-lifetime-mgmt.h [new file with mode: 0644]
src/plugins/text/details/write.c [new file with mode: 0644]
src/plugins/text/details/write.h [new file with mode: 0644]
src/plugins/text/plugin.c
This page took 0.027681 seconds and 4 git commands to generate.