diff --git a/web3_proxy/src/app/mod.rs b/web3_proxy/src/app/mod.rs index 758152d9..8d599074 100644 --- a/web3_proxy/src/app/mod.rs +++ b/web3_proxy/src/app/mod.rs @@ -21,6 +21,7 @@ use chrono::Utc; use deferred_rate_limiter::DeferredRateLimiter; use derive_more::From; use entities::sea_orm_active_enums::LogLevel; +use entities::user; use ethers::core::utils::keccak256; use ethers::prelude::{Address, Block, Bytes, Transaction, TxHash, H256, U64}; use ethers::utils::rlp::{Decodable, Rlp}; @@ -30,7 +31,9 @@ use hashbrown::{HashMap, HashSet}; use ipnet::IpNet; use log::{debug, error, info, trace, warn, Level}; use metered::{metered, ErrorCount, HitCount, ResponseTime, Throughput}; -use migration::sea_orm::{self, ConnectionTrait, Database, DatabaseConnection}; +use migration::sea_orm::{ + self, ConnectionTrait, Database, DatabaseConnection, EntityTrait, PaginatorTrait, +}; use migration::sea_query::table::ColumnDef; use migration::{Alias, DbErr, Migrator, MigratorTrait, Table}; use moka::future::Cache; @@ -710,6 +713,21 @@ impl Web3ProxyApp { // TODO: what globals? should this be the hostname or what? // globals.insert("service", "web3_proxy"); + #[derive(Default, Serialize)] + struct UserCount(i64); + + let user_count: UserCount = if let Some(db) = self.db_conn() { + match user::Entity::find().count(&db).await { + Ok(user_count) => UserCount(user_count as i64), + Err(err) => { + warn!("unable to count users: {:?}", err); + UserCount(-1) + } + } + } else { + UserCount(-1) + }; + #[derive(Default, Serialize)] struct RecentCounts { one_week: i64, @@ -846,6 +864,7 @@ impl Web3ProxyApp { recent_ip_counts: RecentCounts, recent_user_id_counts: RecentCounts, recent_tx_counts: RecentCounts, + user_count: UserCount, } let metrics = CombinedMetrics { @@ -854,6 +873,7 @@ impl Web3ProxyApp { recent_ip_counts, recent_user_id_counts, recent_tx_counts, + user_count, }; serde_prometheus::to_string(&metrics, Some("web3_proxy"), globals) diff --git a/web3_proxy/src/bin/web3_proxy_cli/change_user_address.rs b/web3_proxy/src/bin/web3_proxy_cli/change_user_address.rs index d2f02c6c..1dc41460 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/change_user_address.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/change_user_address.rs @@ -11,7 +11,7 @@ use migration::sea_orm::{ /// change a user's address. #[derive(FromArgs, PartialEq, Eq, Debug)] #[argh(subcommand, name = "change_user_address")] -pub struct ChangeUserAddressCommand { +pub struct ChangeUserAddressSubCommand { /// the address of the user you want to change #[argh(positional)] old_address: String, @@ -21,7 +21,7 @@ pub struct ChangeUserAddressCommand { new_address: String, } -impl ChangeUserAddressCommand { +impl ChangeUserAddressSubCommand { pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { let old_address: Address = self.old_address.parse()?; let new_address: Address = self.new_address.parse()?; diff --git a/web3_proxy/src/bin/web3_proxy_cli/change_user_address_by_key.rs b/web3_proxy/src/bin/web3_proxy_cli/change_user_address_by_key.rs index c234c5a6..828615dd 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/change_user_address_by_key.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/change_user_address_by_key.rs @@ -13,7 +13,7 @@ use web3_proxy::frontend::authorization::RpcSecretKey; /// change a user's tier. #[derive(FromArgs, PartialEq, Eq, Debug)] #[argh(subcommand, name = "change_user_address_by_key")] -pub struct ChangeUserAddressByKeyCommand { +pub struct ChangeUserAddressByKeySubCommand { #[argh(positional)] /// the RPC key owned by the user you want to change. rpc_secret_key: RpcSecretKey, @@ -23,7 +23,7 @@ pub struct ChangeUserAddressByKeyCommand { new_address: String, } -impl ChangeUserAddressByKeyCommand { +impl ChangeUserAddressByKeySubCommand { pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { let rpc_secret_key: Uuid = self.rpc_secret_key.into(); diff --git a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier.rs b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier.rs index 43cecb7f..2e672c80 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier.rs @@ -10,7 +10,7 @@ use migration::sea_orm::{ /// change a user's tier. #[derive(FromArgs, PartialEq, Eq, Debug)] #[argh(subcommand, name = "change_user_tier")] -pub struct ChangeUserTierCommand { +pub struct ChangeUserTierSubCommand { /// the title of the user tier you are going to modify. #[argh(positional)] user_tier_title: String, @@ -24,7 +24,7 @@ pub struct ChangeUserTierCommand { max_concurrent_requests: Option, } -impl ChangeUserTierCommand { +impl ChangeUserTierSubCommand { // TODO: don't expose the RpcSecretKeys at all. Better to take a user/key id. this is definitely most convenient pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { diff --git a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_address.rs b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_address.rs index ec879bc6..bd59d486 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_address.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_address.rs @@ -11,7 +11,7 @@ use migration::sea_orm::{ /// change a user's tier. #[derive(FromArgs, PartialEq, Eq, Debug)] #[argh(subcommand, name = "change_user_tier_by_address")] -pub struct ChangeUserTierByAddressCommand { +pub struct ChangeUserTierByAddressSubCommand { #[argh(positional)] /// the address of the user you want to change. user_address: Address, @@ -21,7 +21,7 @@ pub struct ChangeUserTierByAddressCommand { user_tier_title: String, } -impl ChangeUserTierByAddressCommand { +impl ChangeUserTierByAddressSubCommand { pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { let address: Vec = self.user_address.to_fixed_bytes().into(); diff --git a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_key.rs b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_key.rs index 5957e965..1c0c05a0 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_key.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/change_user_tier_by_key.rs @@ -12,7 +12,7 @@ use web3_proxy::frontend::authorization::RpcSecretKey; /// change a user's tier. #[derive(FromArgs, PartialEq, Eq, Debug)] #[argh(subcommand, name = "change_user_tier_by_key")] -pub struct ChangeUserTierByKeyCommand { +pub struct ChangeUserTierByKeySubCommand { #[argh(positional)] /// the RPC key owned by the user you want to change. rpc_secret_key: RpcSecretKey, @@ -22,7 +22,7 @@ pub struct ChangeUserTierByKeyCommand { user_tier_title: String, } -impl ChangeUserTierByKeyCommand { +impl ChangeUserTierByKeySubCommand { // TODO: don't expose the RpcSecretKeys at all. Better to take a user/key id. this is definitely most convenient pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { diff --git a/web3_proxy/src/bin/web3_proxy_cli/cost_calculator.rs b/web3_proxy/src/bin/web3_proxy_cli/cost_calculator.rs index 218709d5..d889482f 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/cost_calculator.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/cost_calculator.rs @@ -45,7 +45,7 @@ impl FromStr for TimeFrame { /// calculate costs #[derive(FromArgs, PartialEq, Debug, Eq)] #[argh(subcommand, name = "cost_calculator")] -pub struct CostCalculatorCommand { +pub struct CostCalculatorSubCommand { /// dollar cost of running web3-proxy #[argh(positional)] cost: Decimal, @@ -65,7 +65,7 @@ pub struct CostCalculatorCommand { // TODO: goal price } -impl CostCalculatorCommand { +impl CostCalculatorSubCommand { pub async fn main(self, db_conn: &DatabaseConnection) -> anyhow::Result<()> { #[derive(Debug, FromQueryResult)] struct SelectResult { diff --git a/web3_proxy/src/bin/web3_proxy_cli/main.rs b/web3_proxy/src/bin/web3_proxy_cli/main.rs index 28782625..b6da3b0c 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/main.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/main.rs @@ -5,6 +5,7 @@ mod change_user_tier_by_address; mod change_user_tier_by_key; mod check_config; mod cost_calculator; +mod count_users; mod create_user; mod drop_migration_lock; mod health_compass; @@ -41,13 +42,14 @@ pub struct CliConfig { #[derive(FromArgs, PartialEq, Debug)] #[argh(subcommand)] enum SubCommand { - ChangeUserAddress(change_user_address::ChangeUserAddressCommand), - ChangeUserAddressByKey(change_user_address_by_key::ChangeUserAddressByKeyCommand), - ChangeUserTier(change_user_tier::ChangeUserTierCommand), - ChangeUserTierByAddress(change_user_tier_by_address::ChangeUserTierByAddressCommand), - ChangeUserTierByKey(change_user_tier_by_key::ChangeUserTierByKeyCommand), + ChangeUserAddress(change_user_address::ChangeUserAddressSubCommand), + ChangeUserAddressByKey(change_user_address_by_key::ChangeUserAddressByKeySubCommand), + ChangeUserTier(change_user_tier::ChangeUserTierSubCommand), + ChangeUserTierByAddress(change_user_tier_by_address::ChangeUserTierByAddressSubCommand), + ChangeUserTierByKey(change_user_tier_by_key::ChangeUserTierByKeySubCommand), CheckConfig(check_config::CheckConfigSubCommand), - CostCalculatorCommand(cost_calculator::CostCalculatorCommand), + CostCalculator(cost_calculator::CostCalculatorSubCommand), + CountUsers(count_users::CountUsersSubCommand), CreateUser(create_user::CreateUserSubCommand), DropMigrationLock(drop_migration_lock::DropMigrationLockSubCommand), HealthCompass(health_compass::HealthCompassSubCommand), @@ -119,7 +121,12 @@ async fn main() -> anyhow::Result<()> { x.main(&db_conn).await } - SubCommand::CostCalculatorCommand(x) => { + SubCommand::CostCalculator(x) => { + let db_conn = get_db(cli_config.db_url, 1, 1).await?; + + x.main(&db_conn).await + } + SubCommand::CountUsers(x) => { let db_conn = get_db(cli_config.db_url, 1, 1).await?; x.main(&db_conn).await