diff --git a/Cargo.lock b/Cargo.lock index 960819dbf..eb34a7a91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3250,6 +3250,7 @@ dependencies = [ "itertools 0.12.1", "jf-merkle-tree", "jf-vid", + "log", "portpicker", "prometheus", "rand 0.8.5", diff --git a/Cargo.toml b/Cargo.toml index 62944cdc1..f0fefb89d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ no-storage = [] # Enable the availability data source backed by a Postgres database. sql-data-source = [ "include_dir", + "log", "refinery", "refinery-core", "sqlx", @@ -104,6 +105,7 @@ atomic_store = { git = "https://github.com/EspressoSystems/atomicstore.git", tag # Dependencies enabled by feature "sql-data-source". include_dir = { version = "0.7", optional = true } +log = { version = "0.4", optional = true } refinery = { version = "0.8", features = ["tokio-postgres"], optional = true } refinery-core = { version = "0.8", optional = true } sqlx = { version = "0.8", features = [ diff --git a/src/data_source/sql.rs b/src/data_source/sql.rs index cbb84bc94..8960e15d4 100644 --- a/src/data_source/sql.rs +++ b/src/data_source/sql.rs @@ -26,10 +26,9 @@ pub use anyhow::Error; use hotshot_types::traits::node_implementation::NodeType; pub use refinery::Migration; -pub use sql::{Postgres, Transaction}; +pub use sql::{Config, Transaction}; pub type Builder = fetching::Builder; -pub type Config = sql::Config; impl Config { /// Connect to the database with this config. diff --git a/src/data_source/storage/sql.rs b/src/data_source/storage/sql.rs index 973401db8..75920a442 100644 --- a/src/data_source/storage/sql.rs +++ b/src/data_source/storage/sql.rs @@ -27,15 +27,16 @@ use chrono::Utc; use futures::future::FutureExt; use hotshot_types::traits::metrics::Metrics; use itertools::Itertools; +use log::LevelFilter; use sqlx::{ pool::{Pool, PoolOptions}, postgres::{PgConnectOptions, PgSslMode}, - ConnectOptions, Connection, Row, + ConnectOptions, Row, }; use std::{cmp::min, fmt::Debug, str::FromStr, time::Duration}; pub extern crate sqlx; -pub use sqlx::{Database, Postgres, Sqlite}; +pub use sqlx::{Database, Sqlite}; mod db; mod migrate; @@ -185,11 +186,8 @@ fn add_custom_migrations( /// Postgres client config. #[derive(Clone, Debug)] -pub struct Config -where - DB: Database, -{ - db_opt: ::Options, +pub struct Config { + db_opt: PgConnectOptions, pool_opt: PoolOptions, schema: String, reset: bool, @@ -199,7 +197,7 @@ where archive: bool, } -impl Default for Config { +impl Default for Config { fn default() -> Self { PgConnectOptions::default() .host("localhost") @@ -208,7 +206,7 @@ impl Default for Config { } } -impl From for Config { +impl From for Config { fn from(db_opt: PgConnectOptions) -> Self { Self { db_opt, @@ -223,7 +221,7 @@ impl From for Config { } } -impl FromStr for Config { +impl FromStr for Config { type Err = ::Err; fn from_str(s: &str) -> Result { @@ -231,7 +229,7 @@ impl FromStr for Config { } } -impl Config { +impl Config { /// Set the hostname of the database server. /// /// The default is `localhost`. @@ -275,9 +273,7 @@ impl Config { self.db_opt = self.db_opt.ssl_mode(PgSslMode::Require); self } -} -impl Config { /// Set the name of the schema to use for queries. /// /// The default schema is named `hotshot` and is created via the default migrations. @@ -375,6 +371,16 @@ impl Config { self.pool_opt = self.pool_opt.max_connections(max); self } + + /// Log at WARN level any time a SQL statement takes longer than `threshold`. + /// + /// The default threshold is 1s. + pub fn slow_statement_threshold(mut self, threshold: Duration) -> Self { + self.db_opt = self + .db_opt + .log_slow_statements(LevelFilter::Warn, threshold); + self + } } /// Storage for the APIs provided in this crate, backed by a remote PostgreSQL database. @@ -395,7 +401,7 @@ pub struct Pruner { impl SqlStorage { /// Connect to a remote database. - pub async fn connect(mut config: Config) -> Result { + pub async fn connect(mut config: Config) -> Result { let schema = config.schema.clone(); let pool = config .pool_opt @@ -409,7 +415,7 @@ impl SqlStorage { } .boxed() }) - .connect(config.db_opt.to_url_lossy().as_ref()) + .connect_with(config.db_opt) .await?; // Create or connect to the schema for this query service. @@ -678,7 +684,7 @@ pub mod testing { use portpicker::pick_unused_port; use refinery::Migration; - use super::{Config, Postgres}; + use super::Config; use crate::testing::sleep; #[derive(Debug)] @@ -745,7 +751,7 @@ pub mod testing { self.port } - pub fn config(&self) -> Config { + pub fn config(&self) -> Config { Config::default() .user("postgres") .password("password")