Expose HTTP /stats endpoint

This commit is contained in:
Igor Katson 2024-08-21 12:20:36 +01:00
parent 5d3a93b8bd
commit 561c8b8a1d
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
5 changed files with 46 additions and 1 deletions

View file

@ -14,6 +14,7 @@ use crate::{
session::{ session::{
AddTorrent, AddTorrentOptions, AddTorrentResponse, ListOnlyResponse, Session, TorrentId, AddTorrent, AddTorrentOptions, AddTorrentResponse, ListOnlyResponse, Session, TorrentId,
}, },
session_stats::snapshot::SessionStatsSnapshot,
torrent_state::{ torrent_state::{
peer::stats::snapshot::{PeerStatsFilter, PeerStatsSnapshot}, peer::stats::snapshot::{PeerStatsFilter, PeerStatsSnapshot},
FileStream, ManagedTorrentHandle, FileStream, ManagedTorrentHandle,
@ -171,6 +172,10 @@ impl Api {
make_torrent_details(&info_hash, &handle.info().info, only_files.as_deref()) make_torrent_details(&info_hash, &handle.info().info, only_files.as_deref())
} }
pub fn api_session_stats(&self) -> SessionStatsSnapshot {
self.session().stats_snapshot()
}
pub fn torrent_file_mime_type( pub fn torrent_file_mime_type(
&self, &self,
idx: TorrentIdOrHash, idx: TorrentIdOrHash,

View file

@ -63,6 +63,7 @@ impl HttpApi {
"GET /dht/table": "DHT routing table", "GET /dht/table": "DHT routing table",
"GET /torrents": "List torrents", "GET /torrents": "List torrents",
"GET /torrents/playlist": "Generate M3U8 playlist for all files in all torrents", "GET /torrents/playlist": "Generate M3U8 playlist for all files in all torrents",
"GET /stats": "Global session stats",
"POST /torrents/resolve_magnet": "Resolve a magnet to torrent file bytes", "POST /torrents/resolve_magnet": "Resolve a magnet to torrent file bytes",
"GET /torrents/{id_or_infohash}": "Torrent details", "GET /torrents/{id_or_infohash}": "Torrent details",
"GET /torrents/{id_or_infohash}/haves": "The bitfield of have pieces", "GET /torrents/{id_or_infohash}/haves": "The bitfield of have pieces",
@ -92,6 +93,10 @@ impl HttpApi {
state.api_dht_table().map(axum::Json) state.api_dht_table().map(axum::Json)
} }
async fn session_stats(State(state): State<ApiState>) -> impl IntoResponse {
axum::Json(state.api_session_stats())
}
async fn torrents_list(State(state): State<ApiState>) -> impl IntoResponse { async fn torrents_list(State(state): State<ApiState>) -> impl IntoResponse {
axum::Json(state.api_torrent_list()) axum::Json(state.api_torrent_list())
} }
@ -450,6 +455,7 @@ impl HttpApi {
.route("/rust_log", post(set_rust_log)) .route("/rust_log", post(set_rust_log))
.route("/dht/stats", get(dht_stats)) .route("/dht/stats", get(dht_stats))
.route("/dht/table", get(dht_table)) .route("/dht/table", get(dht_table))
.route("/stats", get(session_stats))
.route("/torrents", get(torrents_list)) .route("/torrents", get(torrents_list))
.route("/torrents/:id", get(torrent_details)) .route("/torrents/:id", get(torrent_details))
.route("/torrents/:id/haves", get(torrent_haves)) .route("/torrents/:id/haves", get(torrent_haves))

View file

@ -6,5 +6,5 @@ use crate::torrent_state::live::peers::stats::atomic::AggregatePeerStatsAtomic;
pub struct AtomicSessionStats { pub struct AtomicSessionStats {
pub fetched_bytes: AtomicU64, pub fetched_bytes: AtomicU64,
pub uploaded_bytes: AtomicU64, pub uploaded_bytes: AtomicU64,
pub peers: AggregatePeerStatsAtomic, pub(crate) peers: AggregatePeerStatsAtomic,
} }

View file

@ -5,11 +5,13 @@ use std::{
use atomic::AtomicSessionStats; use atomic::AtomicSessionStats;
use librqbit_core::speed_estimator::SpeedEstimator; use librqbit_core::speed_estimator::SpeedEstimator;
use snapshot::SessionStatsSnapshot;
use tracing::error_span; use tracing::error_span;
use crate::Session; use crate::Session;
pub mod atomic; pub mod atomic;
pub mod snapshot;
pub struct SessionStats { pub struct SessionStats {
pub atomic: Arc<AtomicSessionStats>, pub atomic: Arc<AtomicSessionStats>,
@ -27,6 +29,12 @@ impl SessionStats {
} }
} }
impl Default for SessionStats {
fn default() -> Self {
Self::new()
}
}
impl Session { impl Session {
pub(crate) fn start_speed_estimator_updater(self: &Arc<Self>) { pub(crate) fn start_speed_estimator_updater(self: &Arc<Self>) {
self.spawn(error_span!(parent: self.rs(), "speed_estimator"), { self.spawn(error_span!(parent: self.rs(), "speed_estimator"), {
@ -47,4 +55,8 @@ impl Session {
} }
}) })
} }
pub fn stats_snapshot(&self) -> SessionStatsSnapshot {
SessionStatsSnapshot::from(&self.stats)
}
} }

View file

@ -0,0 +1,22 @@
use serde::Serialize;
use crate::torrent_state::{peers::stats::snapshot::AggregatePeerStats, stats::Speed};
use super::SessionStats;
#[derive(Debug, Serialize)]
pub struct SessionStatsSnapshot {
download_speed: Speed,
upload_speed: Speed,
peers: AggregatePeerStats,
}
impl From<&SessionStats> for SessionStatsSnapshot {
fn from(s: &SessionStats) -> Self {
Self {
download_speed: s.down_speed_estimator.mbps().into(),
upload_speed: s.up_speed_estimator.mbps().into(),
peers: AggregatePeerStats::from(&s.atomic.peers),
}
}
}