Add remaining bandwidth log
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
@@ -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)]
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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?
|
||||
|
||||
Reference in New Issue
Block a user