diff --git a/Cargo.lock b/Cargo.lock index 00c2e49d1df..bb131c2c749 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,7 +89,7 @@ dependencies = [ [[package]] name = "async-bb8-diesel" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/async-bb8-diesel?rev=1a5c55d#1a5c55d9e31210fd7dfff944798e89578e3a0dfc" +source = "git+https://github.com/oxidecomputer/async-bb8-diesel?rev=22c26ef#22c26ef840075a57b18ac2eae3ead989b992773e" dependencies = [ "async-trait", "bb8", @@ -631,7 +631,7 @@ dependencies = [ [[package]] name = "diesel" version = "2.0.0" -source = "git+https://github.com/diesel-rs/diesel?rev=a39dd2e#a39dd2ebc5acccb8cde73d40b0d81dde3e073170" +source = "git+https://github.com/diesel-rs/diesel?rev=ce77c382#ce77c382d2836f6b385225991cf58cb2d2dd65d6" dependencies = [ "bitflags", "byteorder", @@ -646,10 +646,19 @@ dependencies = [ "uuid", ] +[[package]] +name = "diesel-dtrace" +version = "0.1.0" +source = "git+https://github.com/oxidecomputer/diesel-dtrace?branch=main#dfeff3201eb8180220542b29021f0b5f71e50b46" +dependencies = [ + "diesel", + "usdt", +] + [[package]] name = "diesel_derives" version = "2.0.0" -source = "git+https://github.com/diesel-rs/diesel?rev=a39dd2e#a39dd2ebc5acccb8cde73d40b0d81dde3e073170" +source = "git+https://github.com/diesel-rs/diesel?rev=ce77c382#ce77c382d2836f6b385225991cf58cb2d2dd65d6" dependencies = [ "proc-macro2", "quote", @@ -1762,6 +1771,7 @@ dependencies = [ "cookie", "db-macros", "diesel", + "diesel-dtrace", "dropshot", "expectorate", "futures", @@ -1805,6 +1815,7 @@ dependencies = [ "tokio", "tokio-postgres", "toml", + "usdt", "uuid", ] diff --git a/nexus/Cargo.toml b/nexus/Cargo.toml index d6db89b61f8..8246bcaed63 100644 --- a/nexus/Cargo.toml +++ b/nexus/Cargo.toml @@ -11,10 +11,10 @@ path = "../rpaths" anyhow = "1.0" async-trait = "0.1.51" bb8 = "0.7.1" -async-bb8-diesel = { git = "https://github.com/oxidecomputer/async-bb8-diesel", rev = "1a5c55d" } +async-bb8-diesel = { git = "https://github.com/oxidecomputer/async-bb8-diesel", rev = "22c26ef" } cookie = "0.15" # Tracking pending 2.0 version. -diesel = { git = "https://github.com/diesel-rs/diesel", rev = "a39dd2e", features = ["postgres", "r2d2", "chrono", "serde_json", "network-address", "uuid"] } +diesel = { git = "https://github.com/diesel-rs/diesel", rev = "ce77c382", features = ["postgres", "r2d2", "chrono", "serde_json", "network-address", "uuid"] } futures = "0.3.18" hex = "0.4.3" http = "0.2.5" @@ -40,6 +40,7 @@ sled-agent-client = { path = "../sled-agent-client" } structopt = "0.3" thiserror = "1.0" toml = "0.5.6" +usdt = "0.2" [dependencies.api_identity] path = "../api_identity" @@ -48,9 +49,14 @@ path = "../api_identity" version = "0.4" features = [ "serde" ] +[dependencies.diesel-dtrace] +git = "https://github.com/oxidecomputer/diesel-dtrace" +branch = "main" + [dependencies.dropshot] git = "https://github.com/oxidecomputer/dropshot" branch = "main" +features = [ "usdt-probes" ] [dependencies.omicron-common] path = "../common" diff --git a/nexus/src/config.rs b/nexus/src/config.rs index 602ba266466..e8fc1e0fdc2 100644 --- a/nexus/src/config.rs +++ b/nexus/src/config.rs @@ -359,6 +359,7 @@ mod test { if_exists = "fail" [insecure] allow_any_request_to_spoof_authn_header = true + if_exists = "fail" "##, ) .unwrap(); diff --git a/nexus/src/db/collection_insert.rs b/nexus/src/db/collection_insert.rs index f55aa44bb4f..ce1fb854d42 100644 --- a/nexus/src/db/collection_insert.rs +++ b/nexus/src/db/collection_insert.rs @@ -9,6 +9,7 @@ //! 2) updates the collection's child resource generation number //! 3) inserts the child resource row +use super::pool::DbConnection; use async_bb8_diesel::{ AsyncRunQueryDsl, ConnectionError, ConnectionManager, PoolError, }; @@ -204,11 +205,11 @@ where /// - Error(other diesel error) pub async fn insert_and_get_result_async( self, - pool: &bb8::Pool>, + pool: &bb8::Pool>, ) -> AsyncInsertIntoCollectionResult where // We require this bound to ensure that "Self" is runnable as query. - Self: query_methods::LoadQuery, + Self: query_methods::LoadQuery, { self.get_result_async::(pool) .await @@ -223,11 +224,11 @@ where /// - Error(other diesel error) pub async fn insert_and_get_results_async( self, - pool: &bb8::Pool>, + pool: &bb8::Pool>, ) -> AsyncInsertIntoCollectionResult> where // We require this bound to ensure that "Self" is runnable as query. - Self: query_methods::LoadQuery, + Self: query_methods::LoadQuery, { self.get_results_async::(pool) .await @@ -242,11 +243,11 @@ where /// - Error(other diesel error) pub fn insert_and_get_result( self, - conn: &mut PgConnection, + conn: &mut DbConnection, ) -> SyncInsertIntoCollectionResult where // We require this bound to ensure that "Self" is runnable as query. - Self: query_methods::LoadQuery, + Self: query_methods::LoadQuery, { self.get_result::(conn) .map_err(Self::translate_sync_error) @@ -260,11 +261,11 @@ where /// - Error(other diesel error) pub fn insert_and_get_results( self, - conn: &mut PgConnection, + conn: &mut DbConnection, ) -> SyncInsertIntoCollectionResult> where // We require this bound to ensure that "Self" is runnable as query. - Self: query_methods::LoadQuery, + Self: query_methods::LoadQuery, { self.get_results::(conn) .map_err(Self::translate_sync_error) @@ -323,7 +324,7 @@ where type SqlType = SelectableSqlType; } -impl RunQueryDsl +impl RunQueryDsl for InsertIntoCollectionStatement where ResourceTable: Table + Copy + Debug, diff --git a/nexus/src/db/datastore.rs b/nexus/src/db/datastore.rs index 7e20306592e..1134872fc4b 100644 --- a/nexus/src/db/datastore.rs +++ b/nexus/src/db/datastore.rs @@ -27,6 +27,7 @@ use super::collection_insert::{ }; use super::error::diesel_pool_result_optional; use super::identity::{Asset, Resource}; +use super::pool::DbConnection; use super::Pool; use crate::authz; use crate::context::OpContext; @@ -81,15 +82,14 @@ impl DataStore { // the database. Eventually, this function should only be used for doing // authentication in the first place (since we can't do an authz check in // that case). - fn pool(&self) -> &bb8::Pool> { + fn pool(&self) -> &bb8::Pool> { self.pool.pool() } fn pool_authorized( &self, opctx: &OpContext, - ) -> Result<&bb8::Pool>, Error> - { + ) -> Result<&bb8::Pool>, Error> { opctx.authorize(authz::Action::Query, authz::DATABASE)?; Ok(self.pool.pool()) } diff --git a/nexus/src/db/pool.rs b/nexus/src/db/pool.rs index 79432398978..eea50d6304b 100644 --- a/nexus/src/db/pool.rs +++ b/nexus/src/db/pool.rs @@ -31,24 +31,27 @@ use super::Config as DbConfig; use async_bb8_diesel::ConnectionManager; use diesel::PgConnection; +use diesel_dtrace::DTraceConnection; + +pub type DbConnection = DTraceConnection; /// Wrapper around a database connection pool. /// /// Expected to be used as the primary interface to the database. pub struct Pool { - pool: bb8::Pool>, + pool: bb8::Pool>, } impl Pool { pub fn new(db_config: &DbConfig) -> Self { let manager = - ConnectionManager::::new(&db_config.url.url()); + ConnectionManager::::new(&db_config.url.url()); let pool = bb8::Builder::new().build_unchecked(manager); Pool { pool } } /// Returns a reference to the underlying pool. - pub fn pool(&self) -> &bb8::Pool> { + pub fn pool(&self) -> &bb8::Pool> { &self.pool } } diff --git a/nexus/src/db/update_and_check.rs b/nexus/src/db/update_and_check.rs index be17d97bf70..0e921dca1a1 100644 --- a/nexus/src/db/update_and_check.rs +++ b/nexus/src/db/update_and_check.rs @@ -4,6 +4,7 @@ //! CTE implementation for "UPDATE with extended return status". +use super::pool::DbConnection; use async_bb8_diesel::{AsyncRunQueryDsl, ConnectionManager, PoolError}; use diesel::associations::HasTable; use diesel::helper_types::*; @@ -142,11 +143,11 @@ where /// - Error (row doesn't exist, or other diesel error) pub async fn execute_and_check( self, - pool: &bb8::Pool>, + pool: &bb8::Pool>, ) -> Result, PoolError> where // We require this bound to ensure that "Self" is runnable as query. - Self: LoadQuery, Option, Q)>, + Self: LoadQuery, Option, Q)>, { let (id0, id1, found) = self.get_result_async::<(Option, Option, Q)>(pool).await?; @@ -176,7 +177,7 @@ where ); } -impl RunQueryDsl for UpdateAndQueryStatement +impl RunQueryDsl for UpdateAndQueryStatement where US: UpdateStatementExt, US::Table: Table, diff --git a/nexus/src/lib.rs b/nexus/src/lib.rs index aa070cd3adf..1a65289597f 100644 --- a/nexus/src/lib.rs +++ b/nexus/src/lib.rs @@ -167,6 +167,13 @@ pub async fn run_server(config: &Config) -> Result<(), String> { .log .to_logger("nexus") .map_err(|message| format!("initializing logger: {}", message))?; + if let Err(e) = usdt::register_probes() { + let msg = format!("failed to register DTrace probes: {}", e); + error!(log, "{}", msg); + return Err(msg); + } else { + debug!(log, "registered DTrace probes"); + } let rack_id = Uuid::new_v4(); let server = Server::start(config, &rack_id, &log).await?; server.register_as_producer().await;