Skip to content

Commit 9d53fe9

Browse files
V VV V
authored andcommitted
debug: comprehensive /debug/iggy - scan all partitions + topic stats
1 parent 1a07125 commit 9d53fe9

1 file changed

Lines changed: 66 additions & 33 deletions

File tree

src/bin/sse_gateway.rs

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -560,12 +560,13 @@ async fn health_handler(State(state): State<AppState>) -> Json<serde_json::Value
560560
}))
561561
}
562562

563-
/// Debug endpoint — polls Iggy HTTP API directly and returns raw results.
563+
/// Debug endpoint — comprehensive Iggy diagnostics.
564+
/// Checks topic stats, scans all partitions, reports which have data.
564565
async fn debug_iggy_handler() -> Json<serde_json::Value> {
565566
let iggy_http_url = env::var("IGGY_HTTP_URL").unwrap_or_else(|_| "http://127.0.0.1:3000".into());
566567
let stream = env::var("IGGY_STREAM").unwrap_or_else(|_| "tracker".into());
567-
let topic = env::var("IGGY_TOPIC").unwrap_or_else(|_| "events".into());
568-
let topic_clean = env::var("IGGY_TOPIC_CLEAN").unwrap_or_else(|_| "events-clean".into());
568+
let topic_name = env::var("IGGY_TOPIC").unwrap_or_else(|_| "events".into());
569+
let topic_clean_name = env::var("IGGY_TOPIC_CLEAN").unwrap_or_else(|_| "events-clean".into());
569570

570571
let http = reqwest::Client::new();
571572

@@ -575,45 +576,77 @@ async fn debug_iggy_handler() -> Json<serde_json::Value> {
575576
Err(e) => return Json(json!({ "error": format!("login failed: {}", e), "iggy_http_url": iggy_http_url })),
576577
};
577578

578-
// Poll partition 0, offset 0, count 1 from events topic
579-
let events_url = format!(
580-
"{}/streams/{}/topics/{}/messages?consumer_id=debug&partition_id=0&polling_strategy=offset&value=0&count=1",
581-
iggy_http_url, stream, topic
582-
);
583-
let events_resp = http.get(&events_url)
584-
.header("Authorization", format!("Bearer {}", token))
585-
.send().await;
586-
let events_raw = match events_resp {
587-
Ok(r) => {
588-
let status = r.status().as_u16();
589-
let body = r.text().await.unwrap_or_else(|e| format!("read error: {}", e));
590-
json!({ "status": status, "body_preview": &body[..body.len().min(500)] })
579+
// Helper: get topic info (partition count + stats)
580+
let topic_info = |topic: &str| {
581+
let url = format!("{}/streams/{}/topics/{}", iggy_http_url, stream, topic);
582+
let http = http.clone();
583+
let token = token.clone();
584+
async move {
585+
match http.get(&url).header("Authorization", format!("Bearer {}", token)).send().await {
586+
Ok(r) => {
587+
let status = r.status().as_u16();
588+
let body = r.text().await.unwrap_or_default();
589+
json!({ "status": status, "body": serde_json::from_str::<serde_json::Value>(&body).unwrap_or(json!(body)) })
590+
}
591+
Err(e) => json!({ "error": format!("{}", e) }),
592+
}
591593
}
592-
Err(e) => json!({ "error": format!("{}", e) }),
593594
};
594595

595-
// Poll partition 0, offset 0, count 1 from events-clean topic
596-
let clean_url = format!(
597-
"{}/streams/{}/topics/{}/messages?consumer_id=debug&partition_id=0&polling_strategy=offset&value=0&count=1",
598-
iggy_http_url, stream, topic_clean
599-
);
600-
let clean_resp = http.get(&clean_url)
601-
.header("Authorization", format!("Bearer {}", token))
602-
.send().await;
603-
let clean_raw = match clean_resp {
604-
Ok(r) => {
605-
let status = r.status().as_u16();
606-
let body = r.text().await.unwrap_or_else(|e| format!("read error: {}", e));
607-
json!({ "status": status, "body_preview": &body[..body.len().min(500)] })
596+
// Helper: scan all partitions for a topic, report which ones have data
597+
let scan_partitions = |topic: String, partitions: u32| {
598+
let http = http.clone();
599+
let token = token.clone();
600+
let iggy_http_url = iggy_http_url.clone();
601+
let stream = stream.clone();
602+
async move {
603+
let mut results = Vec::new();
604+
for pid in 0..partitions {
605+
let url = format!(
606+
"{}/streams/{}/topics/{}/messages?consumer_id=debug&partition_id={}&polling_strategy=offset&value=0&count=1",
607+
iggy_http_url, stream, topic, pid
608+
);
609+
match http.get(&url).header("Authorization", format!("Bearer {}", token)).send().await {
610+
Ok(r) => {
611+
let body: serde_json::Value = r.json().await.unwrap_or(json!({}));
612+
let count = body.get("count").and_then(|c| c.as_u64()).unwrap_or(0);
613+
let current_offset = body.get("current_offset").and_then(|c| c.as_u64()).unwrap_or(0);
614+
if count > 0 || current_offset > 0 {
615+
results.push(json!({ "partition": pid, "count": count, "current_offset": current_offset }));
616+
}
617+
}
618+
Err(_) => {}
619+
}
620+
}
621+
results
608622
}
609-
Err(e) => json!({ "error": format!("{}", e) }),
610623
};
611624

625+
let events_info = topic_info(&topic_name).await;
626+
let clean_info = topic_info(&topic_clean_name).await;
627+
628+
// Extract partition counts
629+
let events_partitions = events_info.pointer("/body/partitions_count")
630+
.and_then(|v| v.as_u64()).unwrap_or(24) as u32;
631+
let clean_partitions = clean_info.pointer("/body/partitions_count")
632+
.and_then(|v| v.as_u64()).unwrap_or(24) as u32;
633+
634+
let events_data = scan_partitions(topic_name.clone(), events_partitions).await;
635+
let clean_data = scan_partitions(topic_clean_name.clone(), clean_partitions).await;
636+
612637
Json(json!({
613638
"iggy_http_url": iggy_http_url,
614639
"login": "ok",
615-
"events_topic": { "url": events_url, "response": events_raw },
616-
"events_clean_topic": { "url": clean_url, "response": clean_raw },
640+
"events_topic": {
641+
"name": topic_name,
642+
"info": events_info,
643+
"partitions_with_data": events_data,
644+
},
645+
"events_clean_topic": {
646+
"name": topic_clean_name,
647+
"info": clean_info,
648+
"partitions_with_data": clean_data,
649+
},
617650
}))
618651
}
619652

0 commit comments

Comments
 (0)