Skip to main content

Try It Without an Account

Run a real pipeline on your own machine before you sign up for anything. Local mode runs the Expanso Edge agent standalone, without a connection to the control plane, so there is no account, bootstrap token, or Cloud setup.

The pipeline you will run filters log noise at the source. It drops routine health checks, debug chatter, and successful static-asset requests, and keeps everything else, including errors and warnings. You send it log lines over HTTP and see what survives.

What you need​

  • expanso-edge and expanso-cli installed (Installation). Local mode needs both: the agent runs the pipeline, and the CLI submits it.
  • curl and two terminal windows.

Check both tools are on your PATH:

expanso-edge version
expanso-cli version

Step 1: Write the pipeline​

Make an empty folder for this walkthrough and work inside it:

mkdir expanso-try && cd expanso-try

Create log-filter.yaml:

cat > log-filter.yaml <<'EOF'
name: log-filter
description: Keep signal, drop routine log noise at the source
type: pipeline
config:
input:
http_server:
address: 127.0.0.1:8090
path: /ingest
pipeline:
processors:
- mapping: |
let raw = content().string()
let doc = $raw.parse_json().catch(null)
let doc = if $doc.type() == "object" { $doc } else {
{"log": $raw}
}
let level = $doc.level.string().catch("").lowercase()
let path = $doc.http.path.string().catch("")
let status = $doc.http.status.number().catch(0)
let is_health = $path.re_match(
"^/(health|healthz|ready|livez|metrics)($|[/?])"
)
let is_debug = $level == "debug"
let is_static = $status > 0 && $status < 400 &&
$path.re_match("\\.(css|js|png|jpg|svg|woff2?)($|[?#])")
root = if $is_health || $is_debug || $is_static {
deleted()
} else {
$doc.merge({"kept": true})
}
output:
sync_response: {}
EOF

The file is a job: a name, a type, and the pipeline under config. The pipeline reads each HTTP request body as one log line, decides whether to keep it with a mapping (written in Bloblang), and returns the result in the HTTP response through sync_response. Lines that are not JSON objects are kept and wrapped as {"log": ...}.

Step 2: Check it without running anything​

expanso-edge validate log-filter.yaml
[OK] log-filter.yaml: valid

validate works offline and never executes the pipeline, so you can run it after every edit. Add -o json to get each error with its path and line number.

Step 3: Start a local agent​

In your first terminal, from the expanso-try folder:

expanso-edge run --local --data-dir ./.edge

Among the startup lines (timestamps trimmed) you will see:

INF API server listening addr=127.0.0.1:9010 component=api_server
INF Expanso Edge Service started successfully component=edge_service

Leave it running. The agent now accepts jobs on localhost:9010.

--data-dir ./.edge keeps the agent's job store, execution state, and pipeline logs in this folder. Without it, the agent uses ~/.expanso/edge (or /var/lib/expanso/edge when run as a system service).

Step 4: Deploy the pipeline​

In your second terminal, from the same folder:

export EXPANSO_CLI_CONFIG_DIR="$PWD/.expanso-cli"
expanso-cli job deploy log-filter.yaml \
--endpoint http://localhost:9010
Job 'log-filter' created successfully in namespace ''

EXPANSO_CLI_CONFIG_DIR gives the CLI its own settings folder inside expanso-try, and --endpoint names the local agent on every command, so the CLI never uses a saved profile or an Expanso Cloud workspace you may have set up elsewhere. Keep both on every expanso-cli command in this walkthrough.

Step 5: Send it some logs​

Create a small sample:

cat > sample.log <<'EOF'
{"level":"info","http":{"path":"/healthz","status":200}}
{"level":"error","msg":"payment failed"}
{"level":"info","http":{"path":"/orders","status":200}}
{"level":"debug","msg":"cache lookup"}
{"level":"info","http":{"path":"/assets/app.js","status":200}}
{"level":"warn","msg":"retry budget low"}
EOF

Send it one line at a time:

while IFS= read -r line; do
curl -s -d "$line" http://127.0.0.1:8090/ingest; echo
done < sample.log

{"kept":true,"level":"error","msg":"payment failed"}
{"http":{"path":"/orders","status":200},"kept":true,"level":"info"}


{"kept":true,"level":"warn","msg":"retry budget low"}

Three of the six lines come back. The blank lines are the health check, the debug line, and the static asset: the pipeline dropped them before they could go anywhere. The error, the warning, and the real API request survive, each marked "kept": true.

Try a line of your own, in any format:

curl -s -d 'GET /login 401 from 10.0.0.9' \
http://127.0.0.1:8090/ingest; echo
{"kept":true,"log":"GET /login 401 from 10.0.0.9"}

Step 6: Change the rule​

Edit log-filter.yaml, for example to stop dropping health checks by removing $is_health || from the root = if line. Then check and redeploy the same file:

expanso-edge validate log-filter.yaml
expanso-cli job deploy log-filter.yaml \
--endpoint http://localhost:9010
[OK] log-filter.yaml: valid
Job 'log-filter' updated successfully in namespace '' (version: 2)

Run the Step 5 loop again: the health check now comes back as the first line.

Clean up​

Stop the agent with Ctrl+C in the first terminal. The job store and pipeline logs are in ./.edge, so if you start the agent again with the same --data-dir, log-filter starts again too. Delete the expanso-try folder (including .edge and any .expanso-cli settings) to start fresh.

Troubleshooting​

bind: address already in use when starting the agent means something else already uses port 9010. Pick another port for the agent:

expanso-edge run --local --data-dir ./.edge \
--api-listen 127.0.0.1:9011

Then use --endpoint http://localhost:9011 on every expanso-cli command.

The same applies to the pipeline's own port: change 8090 in both log-filter.yaml and the curl commands.

NO_CHANGES_DETECTED from expanso-cli job deploy means the file is identical to the job already deployed. Edit it first, or add --force to deploy it anyway.

Where is the pipeline's own log? In ./.edge/executions/<job-id>/logs/pipeline.log. Get the job ID with expanso-cli job list --endpoint http://localhost:9010.

Next steps​