Skip to content

Commit f5515ae

Browse files
cursoragentnicot
andcommitted
Add eval results and test run info support to trace update endpoints
Add two new trace update methods accessible via client.traces: - traces.update(): PATCH /traces/id/{trace_id} to update a trace by ID - traces.update_by_otel_span_id(): PATCH /traces/otel-span-id/{otel_span_id_hex} to update a trace by OpenTelemetry span ID Both endpoints accept optional fields (only sent when provided): - custom_metadata: Dict of key-value metadata pairs - feedback: Dict of feedback values - eval_results: Dict of evaluation scores (bool or float) - test_run_info: TestRunInfo with test_run_id and test_case_id Resolves ENG-5053 Co-authored-by: Nico Tonozzi <nico@nicot.us>
1 parent da24790 commit f5515ae

5 files changed

Lines changed: 485 additions & 0 deletions

File tree

‎src/freeplay/__init__.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .model import TestRunInfo
44
from .resources.recordings import CallInfo, ResponseInfo, RecordPayload, UsageTokens
55
from .resources.sessions import SessionInfo, TraceInfo
6+
from .resources.traces import TraceUpdateResponse
67
from .support import CustomMetadata
78

89
__all__ = [
@@ -15,5 +16,6 @@
1516
"SessionInfo",
1617
"TestRunInfo",
1718
"TraceInfo",
19+
"TraceUpdateResponse",
1820
"UsageTokens",
1921
]

‎src/freeplay/freeplay.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from freeplay.resources.sessions import Sessions
99
from freeplay.resources.test_cases import TestCases
1010
from freeplay.resources.test_runs import TestRuns
11+
from freeplay.resources.traces import Traces
1112
from freeplay.support import CallSupport
1213

1314

@@ -41,3 +42,4 @@ def __init__(
4142
self.sessions = Sessions(self.call_support)
4243
self.test_runs = TestRuns(self.call_support)
4344
self.test_cases = TestCases(self.call_support)
45+
self.traces = Traces(self.call_support)

‎src/freeplay/resources/traces.py‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from dataclasses import dataclass
2+
from typing import Dict, Optional, Union
3+
4+
from freeplay.model import FeedbackValue, TestRunInfo
5+
from freeplay.support import CallSupport, CustomMetadata
6+
7+
8+
@dataclass
9+
class TraceUpdateResponse:
10+
pass
11+
12+
13+
class Traces:
14+
def __init__(self, call_support: CallSupport) -> None:
15+
self.call_support = call_support
16+
17+
def update(
18+
self,
19+
project_id: str,
20+
session_id: str,
21+
trace_id: str,
22+
custom_metadata: CustomMetadata = None,
23+
feedback: Optional[Dict[str, FeedbackValue]] = None,
24+
eval_results: Optional[Dict[str, Union[bool, float]]] = None,
25+
test_run_info: Optional[TestRunInfo] = None,
26+
) -> TraceUpdateResponse:
27+
self.call_support.update_trace(
28+
project_id,
29+
session_id,
30+
trace_id,
31+
custom_metadata=custom_metadata,
32+
feedback=feedback,
33+
eval_results=eval_results,
34+
test_run_info=test_run_info,
35+
)
36+
return TraceUpdateResponse()
37+
38+
def update_by_otel_span_id(
39+
self,
40+
project_id: str,
41+
session_id: str,
42+
otel_span_id_hex: str,
43+
custom_metadata: CustomMetadata = None,
44+
feedback: Optional[Dict[str, FeedbackValue]] = None,
45+
eval_results: Optional[Dict[str, Union[bool, float]]] = None,
46+
test_run_info: Optional[TestRunInfo] = None,
47+
) -> TraceUpdateResponse:
48+
self.call_support.update_trace_by_otel_span_id(
49+
project_id,
50+
session_id,
51+
otel_span_id_hex,
52+
custom_metadata=custom_metadata,
53+
feedback=feedback,
54+
eval_results=eval_results,
55+
test_run_info=test_run_info,
56+
)
57+
return TraceUpdateResponse()

‎src/freeplay/support.py‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,78 @@ def update_trace_metadata(
500500
response,
501501
)
502502

503+
def _build_trace_update_payload(
504+
self,
505+
custom_metadata: CustomMetadata = None,
506+
feedback: Optional[Dict[str, FeedbackValue]] = None,
507+
eval_results: Optional[Dict[str, Union[bool, float]]] = None,
508+
test_run_info: Optional[TestRunInfo] = None,
509+
) -> Dict[str, Any]:
510+
payload: Dict[str, Any] = {}
511+
if custom_metadata is not None:
512+
payload["custom_metadata"] = custom_metadata
513+
if feedback is not None:
514+
payload["feedback"] = feedback
515+
if eval_results is not None:
516+
payload["eval_results"] = eval_results
517+
if test_run_info is not None:
518+
payload["test_run_info"] = asdict(test_run_info)
519+
return payload
520+
521+
def update_trace(
522+
self,
523+
project_id: str,
524+
session_id: str,
525+
trace_id: str,
526+
custom_metadata: CustomMetadata = None,
527+
feedback: Optional[Dict[str, FeedbackValue]] = None,
528+
eval_results: Optional[Dict[str, Union[bool, float]]] = None,
529+
test_run_info: Optional[TestRunInfo] = None,
530+
) -> None:
531+
payload = self._build_trace_update_payload(
532+
custom_metadata=custom_metadata,
533+
feedback=feedback,
534+
eval_results=eval_results,
535+
test_run_info=test_run_info,
536+
)
537+
response = api_support.patch_raw(
538+
self.freeplay_api_key,
539+
f"{self.api_base}/v2/projects/{project_id}/sessions/{session_id}/traces/id/{trace_id}",
540+
payload,
541+
)
542+
if response.status_code != 200:
543+
raise freeplay_response_error(
544+
f"Error updating trace {trace_id} in project {project_id}",
545+
response,
546+
)
547+
548+
def update_trace_by_otel_span_id(
549+
self,
550+
project_id: str,
551+
session_id: str,
552+
otel_span_id_hex: str,
553+
custom_metadata: CustomMetadata = None,
554+
feedback: Optional[Dict[str, FeedbackValue]] = None,
555+
eval_results: Optional[Dict[str, Union[bool, float]]] = None,
556+
test_run_info: Optional[TestRunInfo] = None,
557+
) -> None:
558+
payload = self._build_trace_update_payload(
559+
custom_metadata=custom_metadata,
560+
feedback=feedback,
561+
eval_results=eval_results,
562+
test_run_info=test_run_info,
563+
)
564+
response = api_support.patch_raw(
565+
self.freeplay_api_key,
566+
f"{self.api_base}/v2/projects/{project_id}/sessions/{session_id}/traces/otel-span-id/{otel_span_id_hex}",
567+
payload,
568+
)
569+
if response.status_code != 200:
570+
raise freeplay_response_error(
571+
f"Error updating trace with otel span id {otel_span_id_hex} in project {project_id}",
572+
response,
573+
)
574+
503575
def create_test_run(
504576
self,
505577
project_id: str,

0 commit comments

Comments
 (0)