# Example metric under test
class ExecutionTimeMetric:
    def __init__(self, name: str = "execution_time_metric"):
        self.name = name

    def score(self, task_span: SpanModel, **_):
        if task_span.start_time and task_span.end_time:
            duration = (task_span.end_time - task_span.start_time).total_seconds()
            value = 1.0 if duration < 2.0 else 0.5
            reason = f"Duration: {duration:.2f}s"
        else:
            value = 0.0
            reason = "Missing timing information"
        return score_result.ScoreResult(value=value, name=self.name, reason=reason)

@track
def my_tracked_function(question: str) -> str:
    # Your LLM/tool code here that produces spans
    return f"Answer to: {question}"

with opik.record_traces_locally() as storage:
    # Execute tracked code that creates spans
    _ = my_tracked_function("What is the capital of France?")

    # Access the in-memory span tree (flush is automatic before reading)
    span_trees = storage.span_trees
    assert len(span_trees) > 0, "No spans recorded"
    root_span = span_trees[0]

    # Evaluate your task span metric directly
    metric = ExecutionTimeMetric()
    result = metric.score(task_span=root_span)
    print(result)
```

Note:

* Local recording cannot be nested. If a recording block is already active, entering another will raise an error.
* See the Python SDK reference for more details: [Local Recording Context Manager](https://www.comet.com/docs/opik/python-sdk-reference/message_processing_emulation/local_recording.html)

## Best Practices

### 1. Handle Missing Data Gracefully

Always check for `None` values in optional span attributes:

```python
def score(self, task_span: SpanModel, **ignored_kwargs: Any) -> score_result.ScoreResult:
    # Safe access to optional fields
    duration = None
    if task_span.start_time and task_span.end_time:
        duration = (task_span.end_time - task_span.start_time).total_seconds()

    cost = task_span.total_cost if task_span.total_cost else 0.0
    metadata = task_span.metadata or {}
```

### 2. Focus on Execution Patterns

Use task span metrics to evaluate **how** your application executes, not just the final output:

```python