1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase", deny_unknown_fields)]
9pub struct TraceObjectiveMetricsRequest {
10 pub trace_id: String,
11 pub conversation_id: String,
12 pub run_id: String,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
14 pub expected_turns: Option<u64>,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub expected_tool_calls: Option<u64>,
17}
18
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[serde(rename_all = "camelCase", deny_unknown_fields)]
22pub struct ObjectiveTraceEvent {
23 pub id: String,
24 pub event_type: String,
25 #[serde(default)]
26 pub payload: Value,
27 #[serde(default)]
28 pub sequence: i64,
29 #[serde(default)]
30 pub created_at_ms: i64,
31}
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase", deny_unknown_fields)]
36pub struct ObjectiveMetricObservation {
37 pub metric: String,
38 pub value: f64,
39 pub unit: String,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub numerator: Option<u64>,
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub denominator: Option<u64>,
44}
45
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase", deny_unknown_fields)]
49pub struct TraceObjectiveMetrics {
50 pub trace_id: String,
51 pub conversation_id: String,
52 pub run_id: String,
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 pub expected_turns: Option<u64>,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
56 pub expected_tool_calls: Option<u64>,
57 pub event_count: u64,
58 pub recognized_event_count: u64,
59 pub unknown_event_count: u64,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub started_at_ms: Option<i64>,
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub completed_at_ms: Option<i64>,
64 pub wall_duration_ms: u64,
65 pub model_duration_ms: u64,
66 pub max_model_duration_ms: u64,
67 pub tool_duration_ms: u64,
68 pub max_tool_duration_ms: u64,
69 pub run_started_count: u64,
70 pub run_completed_count: u64,
71 pub run_failed_count: u64,
72 pub model_started_count: u64,
73 pub model_completed_count: u64,
74 pub model_failed_count: u64,
75 pub tool_started_count: u64,
76 pub tool_completed_count: u64,
77 pub tool_failed_count: u64,
78 pub retry_count: u64,
79 pub context_compaction_count: u64,
80 pub input_tokens: u64,
81 pub input_cached_tokens: u64,
82 pub input_cache_write_tokens: u64,
83 pub output_tokens: u64,
84 pub total_tokens: u64,
85 pub cost_micros: u64,
86 pub error_count: u64,
87 pub timestamp_regression_count: u64,
88 pub sequence_regression_count: u64,
89 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub recognized_event_rate: Option<f64>,
91 #[serde(default, skip_serializing_if = "Option::is_none")]
92 pub run_success_rate: Option<f64>,
93 #[serde(default, skip_serializing_if = "Option::is_none")]
94 pub model_success_rate: Option<f64>,
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub tool_success_rate: Option<f64>,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub turn_completion_rate: Option<f64>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub expected_tool_completion_rate: Option<f64>,
101 #[serde(default, skip_serializing_if = "Option::is_none")]
102 pub average_model_duration_ms: Option<f64>,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 pub average_tool_duration_ms: Option<f64>,
105 #[serde(default, skip_serializing_if = "Option::is_none")]
106 pub output_tokens_per_second: Option<f64>,
107 #[serde(default, skip_serializing_if = "Option::is_none")]
108 pub input_cache_hit_rate: Option<f64>,
109 pub complete: bool,
110 #[serde(default)]
111 pub missing_signals: Vec<String>,
112 #[serde(default)]
113 pub observations: Vec<ObjectiveMetricObservation>,
114}