Skip to content

Commit 7a567e8

Browse files
committed
Save recent connections in stat manager
1 parent a911e54 commit 7a567e8

File tree

3 files changed

+285
-61
lines changed

3 files changed

+285
-61
lines changed

leaf/src/app/api/api_server.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,34 @@ mod handlers {
156156
let mut stats = Vec::new();
157157
let sm = rm.stat_manager();
158158
let sm = sm.read().await;
159-
for c in sm.counters.iter() {
159+
for c in sm.counters.values() {
160+
stats.push(models::Stat {
161+
network: c.sess.network.to_string(),
162+
inbound_tag: c.sess.inbound_tag.to_owned(),
163+
forwarded_source: c.sess.forwarded_source.map(|x| x.to_string()),
164+
source: c.sess.source.to_string(),
165+
destination: c.sess.destination.to_string(),
166+
outbound_tag: c.sess.outbound_tag.to_owned(),
167+
bytes_sent: c.bytes_sent(),
168+
bytes_recvd: c.bytes_recvd(),
169+
send_completed: c.send_completed(),
170+
recv_completed: c.recv_completed(),
171+
start_time: c.start_time(),
172+
dns_sniffed_domain: c.sess.dns_sniffed_domain.clone(),
173+
tls_sniffed_domain: c.sess.tls_sniffed_domain.clone(),
174+
http_sniffed_domain: c.sess.http_sniffed_domain.clone(),
175+
});
176+
}
177+
Ok(Json(stats))
178+
}
179+
180+
pub async fn stat_recent_json(
181+
State(rm): State<Arc<RuntimeManager>>,
182+
) -> Result<Json<Vec<models::Stat>>, Infallible> {
183+
let mut stats = Vec::new();
184+
let sm = rm.stat_manager();
185+
let sm = sm.read().await;
186+
for c in sm.recent_counters.iter() {
160187
stats.push(models::Stat {
161188
network: c.sess.network.to_string(),
162189
inbound_tag: c.sess.inbound_tag.to_owned(),
@@ -202,19 +229,19 @@ table, th, td {
202229
let total_counters = sm.counters.len();
203230
let active_counters = sm
204231
.counters
205-
.iter()
232+
.values()
206233
.filter(|x| !x.send_completed() || !x.recv_completed())
207234
.count();
208235
let active_sources = HashSet::<IpAddr>::from_iter(
209236
sm.counters
210-
.iter()
237+
.values()
211238
.filter(|x| !x.send_completed() || !x.recv_completed())
212239
.map(|c| c.sess.source.ip()),
213240
)
214241
.len();
215242
let active_forwarded_source = HashSet::<IpAddr>::from_iter(
216243
sm.counters
217-
.iter()
244+
.values()
218245
.filter(|x| !x.send_completed() || !x.recv_completed())
219246
.filter_map(|c| c.sess.forwarded_source),
220247
)
@@ -224,7 +251,55 @@ table, th, td {
224251
total_counters, active_counters, active_sources, active_forwarded_source,
225252
));
226253
body.push_str("<tr><td>Network</td><td>Inbound</td><td>Forwarded</td><td>Source</td><td>Destination</td><td>Outbound</td><td>SentBytes</td><td>RecvdBytes</td><td>SendFin</td><td>RecvFin</td><td>StartTime</td></tr>");
227-
for c in sm.counters.iter() {
254+
for c in sm.counters.values() {
255+
body.push_str(&format!(
256+
"<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>",
257+
&c.sess.network,
258+
&c.sess.inbound_tag,
259+
&c.sess.forwarded_source.map(|x|x.to_string()).unwrap_or("None".to_string()),
260+
&c.sess.source,
261+
&c.sess.destination,
262+
&c.sess.outbound_tag,
263+
c.bytes_sent(),
264+
c.bytes_recvd(),
265+
c.send_completed(),
266+
c.recv_completed(),
267+
Local
268+
.timestamp_opt(c.start_time() as i64, 0)
269+
.unwrap()
270+
.format("%H:%M:%S")
271+
.to_string(),
272+
));
273+
}
274+
body.push_str("</table></html>");
275+
Ok(Html(body))
276+
}
277+
278+
pub async fn stat_recent_html(
279+
State(rm): State<Arc<RuntimeManager>>,
280+
) -> Result<Html<String>, Infallible> {
281+
let mut body = String::from(
282+
r#"<html>
283+
<head><style>
284+
table, th, td {
285+
border: 1px solid black;
286+
border-collapse: collapse;
287+
text-align: right;
288+
padding: 4;
289+
font-size: small;
290+
}
291+
.highlight {
292+
font-weight: bold;
293+
}
294+
</style></head>
295+
<table style="border=4px solid">
296+
"#,
297+
);
298+
let sm = rm.stat_manager();
299+
let sm = sm.read().await;
300+
body.push_str(&format!("Recent {}<br><br>", sm.recent_counters.len(),));
301+
body.push_str("<tr><td>Network</td><td>Inbound</td><td>Forwarded</td><td>Source</td><td>Destination</td><td>Outbound</td><td>SentBytes</td><td>RecvdBytes</td><td>SendFin</td><td>RecvFin</td><td>StartTime</td></tr>");
302+
for c in sm.recent_counters.iter() {
228303
body.push_str(&format!(
229304
"<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>",
230305
&c.sess.network,
@@ -314,6 +389,14 @@ impl ApiServer {
314389
app = app
315390
.route("/api/v1/runtime/stat/html", get(handlers::stat_html))
316391
.route("/api/v1/runtime/stat/json", get(handlers::stat_json))
392+
.route(
393+
"/api/v1/runtime/stat/recent/html",
394+
get(handlers::stat_recent_html),
395+
)
396+
.route(
397+
"/api/v1/runtime/stat/recent/json",
398+
get(handlers::stat_recent_json),
399+
)
317400
.route(
318401
"/api/v1/runtime/outbound/{tag}/last_peer_active",
319402
get(handlers::last_peer_active),

0 commit comments

Comments
 (0)