adk_server/rest/controllers/
debug.rs1use crate::ServerConfig;
2use axum::{
3 Json,
4 extract::{Path, State},
5 http::StatusCode,
6};
7use serde::Serialize;
8use std::collections::HashMap;
9
10#[derive(Clone)]
11pub struct DebugController {
12 config: ServerConfig,
13}
14
15impl DebugController {
16 pub fn new(config: ServerConfig) -> Self {
17 Self { config }
18 }
19}
20
21#[derive(Serialize)]
22pub struct GraphResponse {
23 #[serde(rename = "dotSrc")]
24 pub dot_src: String,
25}
26
27pub async fn get_trace_by_event_id(
29 State(controller): State<DebugController>,
30 Path(event_id): Path<String>,
31) -> Result<Json<HashMap<String, String>>, StatusCode> {
32 if let Some(exporter) = &controller.config.span_exporter {
33 if let Some(attributes) = exporter.get_trace_by_event_id(&event_id) {
35 return Ok(Json(attributes));
36 }
37
38 let trace_dict = exporter.get_trace_dict();
40 for (_, attributes) in trace_dict.iter() {
41 if attributes.values().any(|v| v == &event_id) {
43 return Ok(Json(attributes.clone()));
44 }
45 }
46 }
47
48 Err(StatusCode::NOT_FOUND)
49}
50
51fn convert_to_span_data(attributes: &HashMap<String, String>) -> serde_json::Value {
54 let start_time: u64 = attributes.get("start_time").and_then(|s| s.parse().ok()).unwrap_or(0);
55 let end_time: u64 = attributes.get("end_time").and_then(|s| s.parse().ok()).unwrap_or(0);
56
57 let mut obj = serde_json::json!({
59 "name": attributes.get("span_name").map_or("unknown", |v| v.as_str()),
60 "span_id": attributes.get("span_id").map_or("", |v| v.as_str()),
61 "trace_id": attributes.get("trace_id").map_or("", |v| v.as_str()),
62 "start_time": start_time,
63 "end_time": end_time,
64 "attributes": attributes,
65 "invoc_id": attributes.get("gcp.vertex.agent.invocation_id").map_or("", |v| v.as_str())
66 });
67
68 if let Some(llm_req) = attributes.get("gcp.vertex.agent.llm_request") {
70 obj["gcp.vertex.agent.llm_request"] = serde_json::Value::String(llm_req.clone());
71 }
72 if let Some(llm_resp) = attributes.get("gcp.vertex.agent.llm_response") {
73 obj["gcp.vertex.agent.llm_response"] = serde_json::Value::String(llm_resp.clone());
74 }
75
76 obj
77}
78
79pub async fn get_session_traces(
81 State(controller): State<DebugController>,
82 Path(session_id): Path<String>,
83) -> Result<Json<Vec<serde_json::Value>>, StatusCode> {
84 if let Some(exporter) = &controller.config.span_exporter {
85 let traces = exporter.get_session_trace(&session_id);
86 let span_data: Vec<serde_json::Value> = traces.iter().map(convert_to_span_data).collect();
87 return Ok(Json(span_data));
88 }
89
90 Ok(Json(Vec::new()))
91}
92
93pub async fn get_graph(
94 State(_controller): State<DebugController>,
95 Path((_app_name, _user_id, _session_id, _event_id)): Path<(String, String, String, String)>,
96) -> Result<Json<GraphResponse>, StatusCode> {
97 let dot_src = "digraph G { Agent -> User [label=\"response\"]; }".to_string();
99 Ok(Json(GraphResponse { dot_src }))
100}
101
102pub async fn get_eval_sets(
104 State(_controller): State<DebugController>,
105 Path(_app_name): Path<String>,
106) -> Result<Json<Vec<serde_json::Value>>, StatusCode> {
107 Ok(Json(Vec::new()))
109}
110
111pub async fn get_event(
113 State(controller): State<DebugController>,
114 Path((app_name, _user_id, session_id, event_id)): Path<(String, String, String, String)>,
115) -> Result<Json<serde_json::Value>, StatusCode> {
116 if let Some(exporter) = &controller.config.span_exporter {
118 let traces = exporter.get_session_trace(&session_id);
119
120 for attrs in traces {
122 if let Some(stored_event_id) = attrs.get("gcp.vertex.agent.event_id") {
123 if stored_event_id == &event_id {
124 let invocation_id =
126 attrs.get("gcp.vertex.agent.invocation_id").cloned().unwrap_or_default();
127
128 return Ok(Json(serde_json::json!({
129 "id": event_id,
130 "invocationId": invocation_id,
131 "appName": app_name,
132 "sessionId": session_id,
133 "attributes": attrs,
134 "gcp.vertex.agent.llm_request": attrs.get("gcp.vertex.agent.llm_request"),
135 "gcp.vertex.agent.llm_response": attrs.get("gcp.vertex.agent.llm_response")
136 })));
137 }
138 }
139 }
140 }
141
142 Ok(Json(serde_json::json!({
144 "id": event_id,
145 "invocationId": "",
146 "appName": app_name,
147 "sessionId": session_id
148 })))
149}