Assert the entries your services log, read from files or sent to Axx over UDP, TCP or HTTP.
A log is where a service’s log lines are: a file Axx reads, or an address Axx listens on while services send their lines to it. Register it with the {word} log with the following properties:, then assert the entries a scenario must produce. Only what the log received after the scenario registered it counts, and every step waits for its entries (10 seconds unless within {duration} says otherwise).
Use logs to prove that something did not happen: have the service log its decision (“line ML-KES-0413-1 rejected: duplicate reference”) and assert that entry, rather than waiting and hoping nothing arrives. Match on data unique to the scenario (a reference, an id): scenarios run in parallel and share the log.
The url says where the lines are:
| url | Axx |
|---|---|
file:///var/log/app.log, file://logs/app.log |
reads what is appended to the file (relative to axx.yaml); file://.axx/logs/services.log is the console of the services Axx starts |
udp://0.0.0.0:5140 |
listens; each datagram is one or more lines (e.g. Docker’s syslog log driver, a service’s syslog handler) |
tcp://0.0.0.0:5150 |
listens; newline-delimited or octet-counted (RFC 6587) messages |
http://0.0.0.0:5160/logs, https://... |
listens; the body of each POST or PUT to that path (e.g. a Fluent Bit or Vector http output). https uses a self-signed certificate |
Axx opens listeners before it starts the services, for the log steps of the scenarios in the run, so services can send from the start; axx up keeps them open between runs. Services in containers reach them at host.docker.internal.
Patterns are regular expressions (Java syntax), searched in the log’s text, not matched against whole lines: ^ and $ match at line boundaries, every match counts, and a pattern can span lines (\n, or (?s) to let . match newlines), which covers multi-line entries such as stack traces.
Add it to a project with axx pack add logs.
logs.log
Section titled “logs.log”Given the {word} log with the following properties: | property | value |The table may start with the row naming its columns, as above, or go straight to its rows.
Register a log under a name. Assertions only look at what the log receives from then on.
| Parameter | Takes | For example |
|---|---|---|
{word} |
one word, with no spaces | parcels, PX-4101 |
| Property | Takes | Default |
|---|---|---|
url |
where the log’s lines are: a file Axx reads (file://, relative to the directory of axx.yaml or absolute), or an address Axx listens on (udp://, tcp://, http://, https://); ${env:..} and ${sys:..} are expanded |
required |
Any other property fails the step.
Example:
Given the parcels log with the following properties: | url | udp://0.0.0.0:5140 |Given the console log with the following properties: | url | file://.axx/logs/services.log |logs.entry
Section titled “logs.entry”Then [[within {duration} ]]the {word} log has an entry matching {string}Wait (10s, or the given time) until the log has a match for the regular expression. The pattern is searched in the log’s text: ^ and $ match at line boundaries and a pattern can span lines.
| Parameter | Takes | For example |
|---|---|---|
{duration} |
a duration in seconds (s) or minutes (m) |
5s, 2m |
{word} |
one word, with no spaces | parcels, PX-4101 |
{string} |
text in double or single quotes, which the step leaves out | "Get a quote", 'Express' |
Variants, the parts in [[...]] said or left out:
the {word} log has an entry matching {string}within {duration} the {word} log has an entry matching {string}
Example:
Then the parcels log has an entry matching 'registration refused reference=PX-EVT-4003'Then within 30s the parcels log has an entry matching 'manifest line processed line=ML-MAP-0019-3 status=IMPORTED'logs.entries
Section titled “logs.entries”Then [[within {duration} ]]the {word} log has entries matching: | pattern |Wait until the log has a match for every regular expression in the table. Each row needs a match of its own: the same pattern in two rows needs two matches.
| Parameter | Takes | For example |
|---|---|---|
{duration} |
a duration in seconds (s) or minutes (m) |
5s, 2m |
{word} |
one word, with no spaces | parcels, PX-4101 |
A row is a regular expression the log must have a match for.
Variants, the parts in [[...]] said or left out:
the {word} log has entries matching:within {duration} the {word} log has entries matching:
Example:
Then the console log has entries matching: | msg="manifest line processed" line=ML-FJORD-0101-1 status=REJECTED | | msg="manifest line processed" line=ML-FJORD-0101-2 status=REJECTED |logs.count
Section titled “logs.count”Then [[within {duration} ]]the {word} log has {int} entry/entries matching {string}Wait until the log has the given number of matches for the regular expression, for example one per retry. More matches than that fail the step.
| Parameter | Takes | For example |
|---|---|---|
{duration} |
a duration in seconds (s) or minutes (m) |
5s, 2m |
{word} |
one word, with no spaces | parcels, PX-4101 |
{int} |
a whole number | 200, 3 |
{string} |
text in double or single quotes, which the step leaves out | "Get a quote", 'Express' |
Variants, the parts in [[...]] said or left out:
the {word} log has {int} entry/entries matching {string}within {duration} the {word} log has {int} entry/entries matching {string}
Example:
Then the parcels log has 2 entries matching 'storing parcel PX-DBF-3002 failed, retrying'logs.across
Section titled “logs.across”Then [[within {duration} ]]the logs have entries matching: | log | pattern |The table may start with the row naming its columns, as above, or go straight to its rows.
Wait until every log in the table has a match for its regular expression, for example the service’s own entry and its dependency’s. Each row needs a match of its own.
| Parameter | Takes | For example |
|---|---|---|
{duration} |
a duration in seconds (s) or minutes (m) |
5s, 2m |
A row names a log registered in the scenario, and a regular expression it must have a match for.
Variants, the parts in [[...]] said or left out:
the logs have entries matching:within {duration} the logs have entries matching:
Example:
Then the logs have entries matching: | parcels | msg="registration refused; not announced" reference=PX-ADR-1104 | | console | GET /v1/postcodes/DE/00012 |