EDXSample
4 minute read
Minimum Agent Version: v2.25.0
Overview
EDXSample returns true for a share of the items it evaluates, so you can sample inside an OTTL statement instead of adding a separate Sample processor.
It has two forms. Without a key, each evaluation is an independent random draw. With a key, the decision is a stable hash of that value, so every item sharing the key is kept or dropped together: a trace ID keeps whole traces, a user ID keeps whole sessions, a pod name keeps whole pods.
The keyed form uses the same hash and the same decision rule as the Sample processor, so a condition keyed on a field agrees with that processor at the same percentage.
Syntax
EDXSample(percentage)
EDXSample(percentage, key)
percentage: The share of items for which the function returnstrue, from 0 to 100. Fractions are allowed, so0.1keeps one item in a thousand. It can be an expression over the item, such asattributes["priority"] * 10. A value outside 0 to 100, orNaN, fails the statement.key: Optional. When set, the decision is a stable hash of this value instead of a random draw. A null or empty key fails the statement withEDXSample: key is empty.
The function also accepts a third seed argument, which fixes the random sequence of the keyless form. OTTL fills optional arguments in order, so a seed can only be passed alongside a key, and a key makes the seed inert. Use the two forms above.
A percentage of 0 always returns false and 100 always returns true, in both forms. Neither boundary reads the key, so they are safe on items that do not carry it.
Keyed Sampling
The key is hashed to a position between 0 and 100, and the item is kept when that position is below the percentage. The position depends only on the key, so it is the same on every agent and on every run.
| Key | Position | EDXSample(10, key) | EDXSample(25, key) | EDXSample(50, key) |
|---|---|---|---|---|
00f067aa0ba902b7 | 1.31 | true | true | true |
user-4417 | 13.14 | false | true | true |
user-8821 | 48.67 | false | false | true |
4bf92f3577b34da6a3ce929d0e0e4736 | 58.82 | false | false | false |
Raising the percentage only ever adds keys, so a key kept at 10 percent is still kept at 25 percent.
Examples
Marking a sampled session
Input
{
"_type": "log",
"timestamp": 1735789600000,
"body": "checkout completed",
"resource": {...},
"attributes": {
"user_id": "user-4417",
"priority": 5
}
}
Statement
set(attributes["sampled_10"], EDXSample(10, attributes["user_id"]))
set(attributes["sampled_25"], EDXSample(25, attributes["user_id"]))
set(attributes["always"], EDXSample(100))
set(attributes["never"], EDXSample(0))
Output
{
"_type": "log",
"timestamp": 1735789630000,
"body": "checkout completed",
"resource": {...},
"attributes": {
"user_id": "user-4417",
"priority": 5,
"sampled_10": false,
"sampled_25": true,
"always": true,
"never": false
}
}
Every log carrying user-4417 produces the same two decisions, so a session is either wholly in the 25 percent sample or wholly out of it.
Keeping whole traces
Key on the trace ID so that a sampled trace keeps all of its spans, rather than a random tenth of them:
nodes:
- name: keep_whole_traces
type: route_ottl
paths:
- path: sampled
condition: EDXSample(10, trace.id)
exit_if_matched: true
Taking the rate from the item
Because percentage is an expression, the rate can come from the data. This keeps a tenth of priority 1, half of priority 5, and all of priority 10:
nodes:
- name: sample_by_priority
type: route_ottl
paths:
- path: sampled
condition: EDXSample(attributes["priority"] * 10)
exit_if_matched: true
A priority above 10 puts the percentage over 100 and fails the statement, so clamp the field upstream if it is unbounded.
Testing a sampling rule
The keyless form draws at random, so a dry run over the same input gives different results each time. To check a rule in Live Capture or a dry run, key it on a field instead. The decision is then fixed per key and repeats across runs and agents:
set(attributes["sampled"], EDXSample(10, attributes["user_id"]))
The boundaries are also useful while testing: EDXSample(100) passes everything and EDXSample(0) passes nothing, so you can confirm the rest of the statement independently of the sampling.