Channel
Channels are proxies through which a simulation sends inputs and receives outputs from the system-under-test. For example:
channels:
db:
format:
type: sql
target:
type: stream
command: psql -q $DATABASE_URL
api:
format:
type: template
template: curl -sS -X {{method}} $API_BASE_URL{{path}}
target:
type: exec
log:
target:
type: stream
command: tail -F logs/app.logOutput
A channel may produce outputs, which could be either:
- interactive, or explicitly caused by one input, e.g. a response to an HTTP request
- ambient, or having ambiguous causality, e.g. an application log line
In either case, every output is added to the log and may be included in a signal.
Interactive outputs always include an input_id foreign key to the input that caused it. Currently, these will only come from channels with exec targets.
Ambient outputs come from channels with stream targets. They may come from channels that take inputs, or from read-only channels.
Target
A channel MUST specify a target, which defines how the channel sends data to and receives data from the system. There are two supported types: exec and stream.
Exec
Runs each input as a command in a sub-shell. It expects a string, and will record an error if it receives anything else. It will also record an error if the command has a non-zero exit.
Since the commands run in the shell, they can make use of features like quoting, expansions and pipes. Additionally the CLI will load the local .env, which means these commands can reference those environment variables.
The stdout of each command's sub-shell will be recorded as interactive outputs, i.e. they will include the ID of the input that triggered them.
So, for example, if API_URL and API_TOKEN were defined in .env, you could send this command to exec:
curl -s -H "Authorization: Bearer $API_TOKEN" \
"${API_URL:-http://localhost:3000}/users" \
| jq -r '.[].email'Each line jq prints to stdout is recorded as an interactive output.
Stream
Runs the specified command in a sub-shell, prior to the start of a simulation. It then pipes each input to the sub-shell's stdin.
Similar to exec, the command can take advantage of shell features and reference environment variables in the local .env.
Any data received from stdout or stderr will be recorded as ambient outputs, i.e. ones that do not reference any input.
For example, you could send SQL inputs like this:
format:
type: sql
target:
type: stream
command: psql -q $DATABASE_URLRelatedly, a stream target may be used to implement a read-only channel - i.e. one that no input is routed to - since the channel will record stdout and stderr regardless of effect input.
A log tail is a good example of this:
target:
type: stream
command: tail -F logs/app.logFormat
A channel MAY specify a format, which defines how it will transform an input prior to sending it to the target. If no format is specified, the input's JSON-encoded data will be sent.
Template
Builds a string by running the input through the specified Handlebars template. For example, here's simple channel that sends inputs over HTTP:
format:
type: template
template: >-
curl -sS --fail-with-body -X {{data.method}} "${API_BASE_URL:-http://localhost:5173}{{{data.path}}}"
{{#if data.body}}-H 'Content-Type: application/json' --data '{{json data.body}}'{{/if}}
target:
type: execThe template can reference the following fields
effect- information about the effect that emitted the input - currently only includeskey, the key of the effecttimestamp- the logical timestamp of the inputdata- the input data generated by the effect'sschema
SQL
Transforms an input into a SQL insert statement. For example, if an input had the following data:
{
"id": 1,
"name": "Alice",
"admin": true
}it would become:
INSERT INTO `users` (id, name, admin) VALUES (1, 'Alice', true);The table name is taken from the table field on the associated effect's metadata.
If that's not specifed, it will fallback to the effect's key.
Examples
cURL
You can use cURL as an exec target for an API channel. This example uses a template
that expects the effect data to include method and path fields.
format:
type: template
template: curl -sS -X {{data.method}} ${API_BASE_URL:-http://localhost:5173}{{data.path}}
target:
type: execPostgreSQL
Use a stream target and sql format to pipe SQL statements into psql's stdin.
format:
type: sql
target:
type: stream
command: psql -q $DATABASE_URLLog File
Use a stream target to receive signals from a log file. This is an example of a read-only channel,
meaning no effects will be sent to it.
target:
type: stream
command: tail -F logs/app.log