Outputs
Produce human-friendly structured outputs from your tasks
Reading through logs can be noisy and challenging–Airplane allows tasks to produce explicit outputs separate from logs.
Airplane outputs are displayed in rich, user-friendly tables:

Output Data Model

Airplane outputs of a task are similar to the return value of a function. Airplane outputs are JSON values and can be primitive values (strings, numbers), lists, or even complex objects.
Different Airplane tasks will return different kinds of outputs. For example, a SQL task will return its SELECT results as a list of objects (which is rendered as a table of values). Node.js tasks can output values however the author desires..

Output Rendering in the UI

Airplane's UI does a best effort rendering of output, depending on the output data structure. The output is typically formatted into a table or multiple tables. If the output data structure is an object containing only lists as values, the UI will render each separate list as its own table. Otherwise, the entire output will be rendered as one table.
Primitive values (strings, numbers, booleans) are rendered as a single cell in a table.
Lists of primitive values are rendered as a single column table with multiple rows.
Lists of objects are rendered as a table, one row per item, and one column per key. For example, [{"id": 1, "name": "John"}, {"id": 2, "name": "Sally"}] will render as two rows with two columns, "id" and "name".
Nested objects are rendered as collapsed values inside the table.

Producing Output in Tasks

In various task types that can be programmed (e.g. Docker Image, Node.js), Airplane captures task output by filtering stdout lines that start with either airplane_output_set or airplane_output_append.
To produce a basic output, your task should output a line in the following format:
stdout
1
airplane_output_set SOME_JSON_VALUE
Copied!
Airplane will parse through stdout, look for lines that match that format, and save matching lines as output values.
If you're using an SDK, you should use native functions instead:
JavaScript
Python
1
import airplane from 'airplane'
2
3
export default async function(params) {
4
airplane.setOutput({id: 123, name: "abc"});
5
}
Copied!
1
import airplane
2
3
def main(params):
4
airplane.set_output({"id": 123, "name": "abc"})
Copied!
Later outputs will overwrite earlier ones, so if your task is meant to have multiple outputs, you should either collect all the outputs into an array and set it once, or use airplane_output_append, which is described below.

Appending to outputs

If your output is intended to be an array, instead of setting the entire output to be an array, you can use the following:
stdout
JavaScript
Python
1
airplane_output_append {id: 1, name: "abc"}
2
airplane_output_append {id: 2, name: "def"}
Copied!
1
import airplane from 'airplane'
2
3
export default async function(params) {
4
airplane.appendOutput({id: 1, name: "abc"});
5
airplane.appendOutput({id: 2, name: "def"});
6
}
Copied!
1
import airplane
2
3
def main(params):
4
airplane.append_output({"id": 1, "name": "abc"})
5
airplane.append_output({"id": 2, "name": "def"})
Copied!
The resulting output will be [{id: 1, name: "abc"}, {id: 2, name: "def"}].
During visualization, if a task outputs a list of objects, the values are collected into a table with a column per key:
stdout
JavaScript
Python
1
airplane_output_append {"name": "Alabama", "capital": "Montgomery"}
2
airplane_output_append {"name": "Alaska", "capital": "Juneau"}
3
airplane_output_append {"name": "Arizona", "capital": "Phoenix"}
Copied!
1
airplane.appendOutput({name: "Alabama", capital: "Montgomery"})
2
airplane.appendOutput({name: "Alaska", capital: "Juneau"})
3
airplane.appendOutput({name: "Arizona", capital: "Phoenix"})
Copied!
1
airplane.append_output({"name": "Alabama", "capital": "Montgomery"})
2
airplane.append_output({"name": "Alaska", "capital": "Juneau"})
3
airplane.append_output({"name": "Arizona", "capital": "Phoenix"})
Copied!

Common Use Cases

Displaying User Messages

By default, users see if a run has succeeded or failed. You can output messages as you make progress (outputs are shown as soon as they're received), and you can also output more detailed error messages if something fails.

Exporting Data

You can use Airplane outputs for lightweight reporting. For example, you can query a database for a set of data, output each row as a JSON object, and allow users a quick way to see data (and download it as a CSV).

Passing Outputs from Other Tasks

If you're using the Airplane Runtime API or an SDK, you can trigger another task from the current task and read its output. This allows you to chain tasks together similar to how you would call from one microservice to another.
You could set up a first task to perform and output some computation and then invoke it from a second task.

Advanced

JSON Paths

Setting and appending can also apply to a subset of the output instead of overwriting the entire output or appending to the main array. The airplane output set and airplane output append commands have an optional path parameter, which allows part of an existing output to be edited.
1
airplane_output_set {"k1": "v1", "k2": {"nested": "abc"}, "k3": [1, 2, 3]}
2
airplane_output_set:k1 "new value"
3
4
# Output is now: {"k1": "new value", "k2": {"nested": "abc"}, "k3": [1, 2, 3]}
5
6
# Note that these are all valid path syntaxes
7
airplane_output_set:k2.nested "def"
8
airplane_output_set:k2["nested"] "def"
9
airplane_output_set:["k2"]["nested"] "def"
10
airplane_output_set:["k2"].nested "def"
11
12
# Output is now: {"k1": "new value", "k2": {"nested": "def"}, "k3": [1, 2, 3]}
13
14
airplane_output_set:k3[2] 4
15
16
# Output is now: {"k1": "new value", "k2": {"nested": "def"}, "k3": [1, 2, 4]}
17
18
# Append also accepts paths
19
airplane_output_append:k3 8
20
21
# Output is now: {"k1": "new value", "k2": {"nested": "def"}, "k3": [1, 2, 4, 8]}
Copied!
The set/append output functions in the SDKs will help to automatically construct the JSON path for you, from an array of path components. Refer to the documentation of each individual SDK for the correct format.

Handling large outputs

Due to limitations of Docker/Kubernetes, output lines in stdout that are too long (greater than approximately 16000 characters) may not be parsed correctly, so we provide a "chunking" mechanism to split up such lines.
If you are using a SDK, this chunking is automatically handled for you.
stdout
1
airplane_chunk:key1 airplane_outp
2
airplane_chunk:key1 ut_set "Hello World!"
3
airplane_chunk_end:key1
4
5
airplane_chunk:key2 airplane_outp
6
airplane_chunk:key2 ut_set "How ar
7
airplane_chunk:key2 e you?"
8
airplane_chunk_end:key2
9
10
(is equivalent to)
11
12
airplane_output_set "Hello World!"
13
airplane_output_set "How are you?"
Copied!
Last modified 18d ago