feat(db): label postgres connections and log audit readiness#1008
feat(db): label postgres connections and log audit readiness#1008pjb157 wants to merge 2 commits into
Conversation
Deploying control-layer with
|
| Latest commit: |
d8ee035
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://6fafefa0.control-layer.pages.dev |
| Branch Preview URL: | https://imparando-69eaab5e-a36f-4c43.control-layer.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR labels PostgreSQL connections with a consistent application_name per component and adds startup logging to report whether PostgreSQL audit-related settings (pgAudit + connection logging) appear to be configured.
Changes:
- Apply
application_nameto main, replica, and schema-scoped pools (main/fusillade/outlet). - Add a new
db::auditmodule to encapsulate application-name constants and audit-readiness logging. - Log audit-readiness status for the main DB and for dedicated fusillade/outlet databases.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
dwctl/src/lib.rs |
Sets application_name on connect options for each pool and logs audit-readiness after migrations. |
dwctl/src/db/mod.rs |
Exposes the new audit module. |
dwctl/src/db/audit.rs |
Adds helpers/constants for labeling connections and inspecting/logging audit configuration. |
| //! dwctl::migrator().run(&pool).await?; | ||
| //! ``` | ||
|
|
||
| pub mod audit; |
There was a problem hiding this comment.
The new audit module is exported publicly, but the module-level rustdoc above still lists only handlers/models/errors/embedded. Please update the "Modules" section to mention audit (or explain why it’s intentionally omitted) so the documentation matches the actual public API surface.
| pub const MAIN_APPLICATION_NAME: &str = "control-layer"; | ||
| pub const FUSILLADE_APPLICATION_NAME: &str = "control-layer/fusillade"; | ||
| pub const OUTLET_APPLICATION_NAME: &str = "control-layer/outlet"; | ||
|
|
||
| pub fn with_application_name(options: PgConnectOptions, application_name: &str) -> PgConnectOptions { | ||
| options.application_name(application_name) | ||
| } | ||
|
|
||
| pub async fn log_postgres_audit_status(component: &str, pool: &PgPool) { |
There was a problem hiding this comment.
dwctl::db::audit and its items are declared pub, but these constants/functions appear to be used only within this crate. Consider reducing visibility to pub(crate) (and/or adding rustdoc if the intent is to support external callers) to avoid unintentionally expanding the crate’s public API.
| pub const MAIN_APPLICATION_NAME: &str = "control-layer"; | |
| pub const FUSILLADE_APPLICATION_NAME: &str = "control-layer/fusillade"; | |
| pub const OUTLET_APPLICATION_NAME: &str = "control-layer/outlet"; | |
| pub fn with_application_name(options: PgConnectOptions, application_name: &str) -> PgConnectOptions { | |
| options.application_name(application_name) | |
| } | |
| pub async fn log_postgres_audit_status(component: &str, pool: &PgPool) { | |
| pub(crate) const MAIN_APPLICATION_NAME: &str = "control-layer"; | |
| pub(crate) const FUSILLADE_APPLICATION_NAME: &str = "control-layer/fusillade"; | |
| pub(crate) const OUTLET_APPLICATION_NAME: &str = "control-layer/outlet"; | |
| pub(crate) fn with_application_name(options: PgConnectOptions, application_name: &str) -> PgConnectOptions { | |
| options.application_name(application_name) | |
| } | |
| pub(crate) async fn log_postgres_audit_status(component: &str, pool: &PgPool) { |
| pub async fn log_postgres_audit_status(component: &str, pool: &PgPool) { | ||
| let database_name: String = match sqlx::query_scalar("SELECT current_database()").fetch_one(pool).await { | ||
| Ok(name) => name, | ||
| Err(error) => { | ||
| tracing::warn!(component, error = %error, "Failed to inspect PostgreSQL audit settings"); | ||
| return; | ||
| } | ||
| }; | ||
|
|
||
| let extension_installed: bool = match sqlx::query_scalar("SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pgaudit')") | ||
| .fetch_one(pool) | ||
| .await | ||
| { | ||
| Ok(installed) => installed, | ||
| Err(error) => { | ||
| tracing::warn!( | ||
| component, | ||
| database = %database_name, | ||
| error = %error, | ||
| "Failed to check whether pgAudit is installed" | ||
| ); | ||
| return; | ||
| } | ||
| }; | ||
|
|
||
| let shared_preload_libraries: Option<String> = match sqlx::query_scalar("SELECT current_setting('shared_preload_libraries', true)") | ||
| .fetch_one(pool) | ||
| .await | ||
| { | ||
| Ok(value) => value, | ||
| Err(error) => { | ||
| tracing::warn!( | ||
| component, | ||
| database = %database_name, | ||
| error = %error, | ||
| "Failed to read shared_preload_libraries" | ||
| ); | ||
| return; | ||
| } | ||
| }; | ||
| let pgaudit_log: Option<String> = match sqlx::query_scalar("SELECT current_setting('pgaudit.log', true)") | ||
| .fetch_one(pool) | ||
| .await | ||
| { | ||
| Ok(value) => value, | ||
| Err(error) => { | ||
| tracing::warn!( | ||
| component, | ||
| database = %database_name, | ||
| error = %error, | ||
| "Failed to read pgaudit.log" | ||
| ); | ||
| return; | ||
| } | ||
| }; | ||
| let log_connections: Option<String> = match sqlx::query_scalar("SELECT current_setting('log_connections', true)") |
There was a problem hiding this comment.
log_postgres_audit_status performs multiple sequential round-trips (current_database + 4 current_setting/extension checks). Since this runs during startup, consider collapsing these into a single SELECT (e.g., selecting all settings/EXISTS in one query) to reduce latency and connection churn.
| db::audit::log_postgres_audit_status("control-layer", db_pools.write()).await; | ||
| match config.database.fusillade() { | ||
| config::ComponentDb::Schema { .. } => { | ||
| info!("Fusillade uses the main PostgreSQL database in schema mode; audit settings are inherited"); | ||
| } | ||
| config::ComponentDb::Dedicated { .. } => { | ||
| db::audit::log_postgres_audit_status("control-layer/fusillade", fusillade_pools.write()).await; |
There was a problem hiding this comment.
These component string literals duplicate the application-name constants in db::audit (e.g. MAIN_APPLICATION_NAME / FUSILLADE_APPLICATION_NAME). Using the constants here would avoid drift if the names change and keep labeling consistent.
| db::audit::log_postgres_audit_status("control-layer", db_pools.write()).await; | |
| match config.database.fusillade() { | |
| config::ComponentDb::Schema { .. } => { | |
| info!("Fusillade uses the main PostgreSQL database in schema mode; audit settings are inherited"); | |
| } | |
| config::ComponentDb::Dedicated { .. } => { | |
| db::audit::log_postgres_audit_status("control-layer/fusillade", fusillade_pools.write()).await; | |
| db::audit::log_postgres_audit_status(db::audit::MAIN_APPLICATION_NAME, db_pools.write()).await; | |
| match config.database.fusillade() { | |
| config::ComponentDb::Schema { .. } => { | |
| info!("Fusillade uses the main PostgreSQL database in schema mode; audit settings are inherited"); | |
| } | |
| config::ComponentDb::Dedicated { .. } => { | |
| db::audit::log_postgres_audit_status( | |
| db::audit::FUSILLADE_APPLICATION_NAME, | |
| fusillade_pools.write(), | |
| ) | |
| .await; |
| info!("Outlet uses the main PostgreSQL database in schema mode; audit settings are inherited"); | ||
| } | ||
| config::ComponentDb::Dedicated { .. } => { | ||
| db::audit::log_postgres_audit_status("control-layer/outlet", pools.write()).await; |
There was a problem hiding this comment.
This uses a hard-coded component label ("control-layer/outlet") even though db::audit::OUTLET_APPLICATION_NAME already defines the same string. Prefer reusing the constant to avoid future mismatches.
| db::audit::log_postgres_audit_status("control-layer/outlet", pools.write()).await; | |
| db::audit::log_postgres_audit_status(db::audit::OUTLET_APPLICATION_NAME, pools.write()).await; |
No description provided.