What You’ll Learn
- How traces are captured during an experiment run, with no setup
- How to score an evaluator on a captured trace
- How to keep evaluation traces out of your production application
Prerequisites
- A task instrumented with OpenTelemetry — either through a Fiddler integration or your own spans
- A Fiddler API key from Settings > Credentials
- Python 3.10 or later
- Fiddler Evals SDK:
pip install fiddler-evals
If you prefer a notebook, open the fully worked example in Google Colab or download it from GitHub.
There Is Nothing to Turn On
Trace capture is automatic.fiddler-otel is a base dependency of the Evals SDK, so evaluate() sets capture up on its own as long as it can resolve a Fiddler application for the dataset.
Score an Evaluator on the Trace
Declare asession parameter on your evaluator’s score function and the runner passes the captured spans to it.
Parameter binding is by name, so evaluators that do not declare session are unaffected.
session to None and handle the None case.
Capture is best-effort, so an evaluator that assumes a session breaks the moment tracing is unavailable.
EvalFn converts your return value for you: bool becomes 1.0 or 0.0, int and float pass through, and None produces a SKIPPED score.
Return a Score directly when you want to control the reasoning text:
Score you construct yourself requires both name and evaluator_name, and the explanation field is reasoning.
What a Session Contains
Your evaluator receives aSession with two attributes:
UUID
The experiment item’s ID. Equal to
experiment_item.id.list[dict]
The spans the task produced, in completion order.
Times are integer nanoseconds so duration is a plain subtraction with no precision loss:
resource, links, and instrumentation scope — are omitted because they are constant or empty for eval runs.
The full-fidelity span is still written to the trace store and visible in the UI, so nothing is lost.
Keep Evaluation Traces Out of Production
Evaluation traces are real traces, so send them to a dedicated pre-production application rather than the one serving live traffic. A process shares one globalFiddlerClient. If one already exists and its application_id does not match the dataset’s application, evaluate() raises ValueError instead of degrading quietly — this is the one capture failure that is deliberately not best-effort, because silently mixing evaluation and production traffic is worse than a failed run.
Point the dataset at its own application and the SDK handles the rest:
A golden dataset promoted from production spans necessarily belongs to the application that served those spans —
span promotion resolves spans through the dataset’s application, and trace capture follows it.
Replaying such a dataset writes its captured traces to that same application.