- Expanso + Jev
- Example 06 of 10
Smart sampling: Jev scores what is interesting, a counter samples the rest.
Every event gets an interestingness score — fascinating ones are all kept, the noise is deterministically sampled down to 1%.
Where the record goes
Every stage on the left is Expanso, and it is deterministic. The record crosses to Jev once, for the one question a rule cannot answer, and comes straight back. Line numbers link to the YAML below.
POST /events- Receive
- Shape
- Ask Jev
- Gate
- Sample
- Route
interesting
keepsampled
- Receivelines 11 to 16
An HTTP server input accepts events on
POST /events. - Shapelines 17 to 26
Parses the POST body if it arrived as a string, then stamps
received_at. It applies the same fixed rules every time, with no model involved; the timestamp is the one value that differs. - Ask Jevlines 27 to 68
Expanso packs the whole record and the typed questions into one request. Jev answers. If the call fails, a
catchsubstitutes empty answers markedjev-unavailable, and the pipeline keeps going.interestingscore
- Gatelines 69 to 78
One fixed threshold over Jev’s score marks each event
keeporsampled. - Samplelines 79 to 82
Keeps every
keepevent, and of the rest exactly one in every hundred, using a counter rather than a random draw. The other ninety-nine are deleted. - Routelines 83 to 100
A
switchoutput writes kept and sampled events to separate files.
What Jev is asked
Jev, judgmentThe pipeline sends the record with one typed question. Jev answers each one with a value the pipeline can compare against a number.
interestingscoreHow interesting or unusual is this event for an engineer investigating an incident?
What Expanso does with the answers
Expanso, deterministicFixed thresholds, checked in order. The first rule that matches sets the route. These are the expressions in the pipeline, not a summary of them.
- $score >= 3keep · Highly unusual or critical: never sampled away.
- elsesampled · Subject to the 1-in-100 counter.
If Jev is unreachable: sampled
With no answer, the score defaults to 0, so every event is sampled at 1 in 100 while Jev is unreachable, including ones it would have kept.
The pipeline
This is the example's own pipeline file, unmodified. Violet marks the lines Expanso runs on its own. Orange marks the handoff, and the darker orange band is the HTTP call to Jev itself.
name: jev-smart-sampling
type: pipeline
description: Smart sampling with Jev — every event is scored for interestingness. Keep 100% of the interesting ones, 1% of the noise. Volume reduction depends on your signal-to-noise ratio.
namespace: production
labels:
category: log-processing
pattern: ai-decision
model: jev
config:
input:
http_server:
address: "0.0.0.0:8080"
path: /events
allowed_verbs: ["POST"]
pipeline:
processors:
- mapping: |
# http_server already parses JSON bodies; only parse raw strings
root = if this.type() == "string" { this.parse_json() } else { this }
- mapping: |
root = this
root.received_at = now()
# ── Ask Jev: how interesting is this event? ──
- mutation: |
meta jev_start = timestamp_unix_milli()
- branch:
request_map: |
root = {
"state": this.string(),
"model": "jev-latest",
"questions": {
"interesting": {
"type": "score",
"instructions": "How interesting or unusual is this event for an engineer investigating an incident?",
"criteria": [
"Routine noise, safe to drop",
"Mildly interesting context",
"Notable, worth keeping",
"Highly unusual, keep for investigation",
"Critical signal, never drop"
]
}
}
}
processors:
- http:
url: "${JEV_API_URL:https://api.typesafe.ai/v1/systemone}"
verb: POST
headers:
Content-Type: application/json
Authorization: "Bearer ${TYPESAFE_API_KEY}"
timeout: 2s
retries: 1
- catch:
- mapping: |
root = {"answers": {}, "model": "jev-unavailable"}
result_map: |
root.jev = {
"answers": this.answers,
"model": this.model.or("jev-latest"),
"ms": timestamp_unix_milli() - metadata("jev_start")
}
# ── Judgment-based sampling: 100% of interesting, 1% of noise ──
# (annotate first, drop in a separate mapping: assigning fields after
# root = deleted() aborts the mapping, and `this` is frozen at mapping
# entry so re-assigning it would wipe the annotations above)
- mapping: |
let score = this.jev.answers.interesting.score.or(0)
root = this
root.jev_score = $score
root.jev_decision = if $score >= 3 { "keep" } else { "sampled" }
# ── Deterministic 1% sample of low-interest events via counter ──
- mapping: |
root = if this.jev_score >= 3 || count("sampled") % 100 == 0 { this } else { deleted() }
output:
broker:
pattern: fan_out
outputs:
- stdout:
codec: lines
- switch:
cases:
- check: this.jev_decision == "keep"
output:
file:
path: ./data/jev-smart-sampling/kept-${! now().ts_format("2006-01-02") }.jsonl
codec: lines
- check: "true"
output:
file:
path: ./data/jev-smart-sampling/sampled-${! now().ts_format("2006-01-02") }.jsonl
codec: lines
100 lines. Copy and Download both give you the file byte for byte.
What you need
- Expanso Edge installed, to validate and run the pipeline.
- A Jev endpoint. The pipeline posts to
JEV_API_URL, and falls back tohttps://api.typesafe.ai/v1/systemonewhen that variable is unset. - A key for that endpoint in
TYPESAFE_API_KEY. The pipeline sends it as a bearer token and has no default for it.
What it proves
- Input. POST /events on port 8080.
- Output. Local files under
./data/jev-smart-sampling/. - Scope. This example ships as a pipeline file and sample records. Its README marks the live runtime (event generator and dashboard) as coming next, so what is published here is the pipeline itself.
- Revision. The file shown is the example as of commit
517c38fof its repository, which is still being developed.
Sample records
The first two of the records that ship with this example. Download all of them.
{"ts":"2026-09-18T14:00:01Z","service":"api-gw","msg":"GET /health 200 3ms"}{"ts":"2026-09-18T14:00:02Z","service":"api-gw","msg":"GET /health 200 2ms"}Questions about this example.
receive, shape, gate, sample, route. Each of those stages applies the same fixed rules every time, with no model involved. Expanso also sets the thresholds that turn Jev's answers into a route.
Jev answers one typed question about each record: interesting. It does not choose the route. The pipeline's gate does that from Jev's answers.
The pipeline catches the failed call, marks the record jev-unavailable, and the gate resolves to "sampled". With no answer, the score defaults to 0, so every event is sampled at 1 in 100 while Jev is unreachable, including ones it would have kept.
Run the deterministic half on your own nodes.
Expanso Edge runs these pipelines where the data is created. The first five nodes are free.