Skip to content

Commit

Permalink
Add remaining bandwidth log
Browse files Browse the repository at this point in the history
  • Loading branch information
dynco-nym committed Nov 29, 2024
1 parent a601105 commit 7ed0657
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 7 deletions.
3 changes: 1 addition & 2 deletions nym-node-status-api/nym-node-status-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ async fn main() -> anyhow::Result<()> {
let db_pool = storage.pool_owned();
let args_clone = args.clone();

let ipinfo_client = monitor::IpInfoClient::new(args.ipinfo_api_token.clone())?;
tokio::spawn(async move {
monitor::spawn_in_background(
db_pool,
args_clone.nym_api_client_timeout,
args_clone.nyxd_addr,
args_clone.monitor_refresh_interval,
ipinfo_client,
args_clone.ipinfo_api_token,
args_clone.geodata_ttl,
)
.await;
Expand Down
55 changes: 52 additions & 3 deletions nym-node-status-api/nym-node-status-api/src/monitor/geodata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ pub(crate) struct IpInfoClient {
}

impl IpInfoClient {
pub(crate) fn new(token: impl Into<String>) -> anyhow::Result<Self> {
pub(crate) fn new(token: impl Into<String>) -> Self {
let client = reqwest::Client::new();
let token = token.into();

Ok(Self { client, token })
Self { client, token }
}

pub(crate) async fn locate_ip(&self, ip: impl AsRef<str>) -> anyhow::Result<Location> {
Expand All @@ -33,12 +33,35 @@ impl IpInfoClient {
}
anyhow::Error::from(err)
})?;
let response_text = response.text().await?;
let response_text = response.text().await?.trim().to_string();

Ok(Location {
two_letter_iso_country_code: response_text,
})
}

/// check DOESN'T consume bandwidth allowance
pub(crate) async fn check_remaining_bandwidth(
&self,
) -> anyhow::Result<ipinfo::MeResponseRequests> {
let url = format!("https://ipinfo.io/me?token={}", &self.token);
let response = self
.client
.get(url)
.send()
.await
// map non 2xx responses to error
.and_then(|res| res.error_for_status())
.map_err(|err| {
if matches!(err.status(), Some(reqwest::StatusCode::TOO_MANY_REQUESTS)) {
tracing::error!("ipinfo rate limit exceeded");
}
anyhow::Error::from(err)
})?;
let response: ipinfo::MeResponse = response.json().await?;

Ok(response.requests)
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -61,3 +84,29 @@ impl Location {
}
}
}

pub(crate) mod ipinfo {
use super::*;

// clippy doesn't understand it's used for typed deserialization
#[allow(dead_code)]
#[derive(Debug, Clone, Deserialize)]
/// `/me` is undocumented in their developers page
/// https://ipinfo.io/developers/responses
/// but explained here
/// https://community.ipinfo.io/t/easy-way-to-check-allowance-usage/5755/2
pub(crate) struct MeResponse {
token: String,
pub(crate) requests: MeResponseRequests,
}

// clippy doesn't understand it's used for typed deserialization
#[allow(dead_code)]
#[derive(Debug, Clone, Deserialize)]
pub(crate) struct MeResponseRequests {
pub(crate) day: u64,
pub(crate) month: u64,
pub(crate) limit: u64,
pub(crate) remaining: u64,
}
}
22 changes: 20 additions & 2 deletions nym-node-status-api/nym-node-status-api/src/monitor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ pub(crate) async fn spawn_in_background(
nym_api_client_timeout: Duration,
nyxd_addr: Url,
refresh_interval: Duration,
ipinfo: IpInfoClient,
ipinfo_api_token: String,
geodata_ttl: Duration,
) {
let geocache = Cache::builder().time_to_live(geodata_ttl).build();
let ipinfo = IpInfoClient::new(ipinfo_api_token.clone());
let mut monitor = Monitor {
db_pool,
network_details: nym_network_defaults::NymNetworkDetails::new_from_env(),
Expand Down Expand Up @@ -87,6 +88,8 @@ pub(crate) async fn spawn_in_background(

impl Monitor {
async fn run(&mut self) -> anyhow::Result<()> {
self.check_ipinfo_bandwidth().await;

let default_api_url = self
.network_details
.endpoints
Expand Down Expand Up @@ -322,7 +325,7 @@ impl Monitor {
Ok(())
}

#[instrument(level = "debug", skip(self))]
#[instrument(level = "debug", skip_all)]
async fn location_cached(&mut self, node: &NymNodeDescription) -> Location {
let node_id = node.node_id;

Expand Down Expand Up @@ -433,6 +436,21 @@ impl Monitor {

Ok(mixnode_records)
}

async fn check_ipinfo_bandwidth(&self) {
match self.ipinfo.check_remaining_bandwidth().await {
Ok(bandwidth) => {
tracing::info!(
"ipinfo monthly bandwidth: {}/{} spent",
bandwidth.month,
bandwidth.limit
);
}
Err(err) => {
tracing::debug!("Couldn't check ipinfo bandwidth: {}", err);
}
}
}
}

// TODO dz is there a common monorepo place this can be put?
Expand Down

0 comments on commit 7ed0657

Please sign in to comment.