Implement Structured Logging Infrastructure with Credential Protection - Task #11
🎯 Epic Context
📊 Current State Analysis
Existing Infrastructure:
- ✅ CLI framework with
--verbose and --quiet flags (unused)
- ✅ Error handling patterns established
- ✅ URL redaction utility in
src/tls.rs (redact_url function)
- ❌ No logging dependencies - missing
tracing ecosystem
- ❌ No structured logging implementation
- ❌ Verbose/quiet flags not connected to any logging
Security Context:
- Must comply with WARP.md credential protection requirements
- Existing
redact_url() function available for DATABASE_URL sanitization
- Zero credential leakage tolerance
🎯 Requirements Implementation
Requirement 7.1: Structured JSON Logging
- Current: Plain stdout output only
- Target: JSON-structured logs via
tracing crate
- Trigger:
--verbose flag activation
Requirement 7.2: Credential Protection
- Current: No logging, so no risk
- Target: Integrate existing
redact_url() function
- Scope: DATABASE_URL, passwords, sensitive connection strings
Requirement 7.3: Multi-level Verbosity
- Current: Single
--verbose boolean flag
- Target: Progressive levels based on flag count (
-v, -vv, -vvv)
- Mapping: 1=info, 2=debug, 3+=trace
Requirement 7.4: Quiet Mode
- Current: Basic
--quiet flag exists
- Target: Suppress all output except errors
- Behavior: Override verbose settings when active
🚀 Proposed Implementation
Phase 1: Dependencies & Infrastructure
# Cargo.toml additions
[dependencies]
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["json", "env-filter", "time"] }
serde = { version = "1.0", features = ["derive"] }
Phase 2: Core Logging Module (src/logging.rs)
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, fmt};
use crate::tls::redact_url;
#[derive(Debug, Clone)]
pub struct LoggingConfig {
pub verbose_count: u8,
pub quiet: bool,
}
impl LoggingConfig {
pub fn from_args(verbose_count: u8, quiet: bool) -> Self {
Self { verbose_count, quiet }
}
pub fn init_structured_logging(&self) -> Result<(), Box<dyn std::error::Error>> {
let level = if self.quiet {
"error"
} else {
match self.verbose_count {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
}
};
let filter = EnvFilter::new(format!("gold_digger={}", level));
tracing_subscriber::registry()
.with(fmt::layer()
.json()
.with_current_span(false)
.with_span_list(true))
.with(filter)
.init();
tracing::info!(
version = env!("CARGO_PKG_VERSION"),
verbose_count = self.verbose_count,
quiet = self.quiet,
"Structured logging initialized"
);
Ok(())
}
}
// Credential-safe logging macros
#[macro_export]
macro_rules! log_database_url {
($url:expr) => {
tracing::debug!(database_url = %crate::tls::redact_url($url), "Database connection configured");
};
}
Phase 3: Integration Points
Main Application (src/main.rs):
mod logging;
use logging::LoggingConfig;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
// Initialize structured logging FIRST
let logging_config = LoggingConfig::from_args(args.verbose, args.quiet);
logging_config.init_structured_logging()?;
tracing::info!("Gold Digger starting");
// Rest of application...
}
Database Operations:
- Add
#[tracing::instrument] to database functions
- Log connection establishment, query execution time
- Include row count milestones (every 1000 rows)
- Use
log_database_url! macro for safe URL logging
CLI Integration:
- Enhance
--verbose to accept multiple occurrences (-v, -vv, -vvv)
- Ensure
--quiet overrides all verbosity settings
- Add
--log-format option for JSON/text output selection
✅ Acceptance Criteria
Core Functionality
Security & Credentials
Performance & Integration
Documentation & Testing
🧪 Validation Steps
Development Testing
# Test different verbosity levels
cargo run -- --help
cargo run -- -q --database-url "$DATABASE_URL" --query "SELECT 1"
cargo run -- -v --database-url "$DATABASE_URL" --query "SELECT * FROM users LIMIT 5"
cargo run -- -vvv --database-url "$DATABASE_URL" --query "SELECT COUNT(*) FROM large_table"
Security Validation
# Verify no credential leakage in any verbosity mode
export DATABASE_URL="mysql://secret_user:secret_pass@host:3306/db"
cargo run -- -vvv --database-url "$DATABASE_URL" --query "SELECT 1" 2>&1 | grep -i "secret"
# Should return no matches
Performance Testing
# Ensure no overhead when logging disabled
hyperfine 'cargo run -- -q --database-url "$DATABASE_URL" --query "SELECT 1"'
hyperfine 'cargo run -- -vvv --database-url "$DATABASE_URL" --query "SELECT 1"'
🔗 Related Resources
🎯 Definition of Done
Epic: #52 | Task: #11 | Requirements: 7.1-7.4 | Priority: High
Implement Structured Logging Infrastructure with Credential Protection - Task #11
🎯 Epic Context
📊 Current State Analysis
Existing Infrastructure:
--verboseand--quietflags (unused)src/tls.rs(redact_urlfunction)tracingecosystemSecurity Context:
redact_url()function available for DATABASE_URL sanitization🎯 Requirements Implementation
Requirement 7.1: Structured JSON Logging
tracingcrate--verboseflag activationRequirement 7.2: Credential Protection
redact_url()functionRequirement 7.3: Multi-level Verbosity
--verboseboolean flag-v,-vv,-vvv)Requirement 7.4: Quiet Mode
--quietflag exists🚀 Proposed Implementation
Phase 1: Dependencies & Infrastructure
Phase 2: Core Logging Module (
src/logging.rs)Phase 3: Integration Points
Main Application (
src/main.rs):Database Operations:
#[tracing::instrument]to database functionslog_database_url!macro for safe URL loggingCLI Integration:
--verboseto accept multiple occurrences (-v,-vv,-vvv)--quietoverrides all verbosity settings--log-formatoption for JSON/text output selection✅ Acceptance Criteria
Core Functionality
tracingandtracing-subscriberwith JSON support--verbosecount maps to log levels (warn→info→debug→trace)--quietsuppresses all logs except errorsSecurity & Credentials
redact_url()for URL sanitizationPerformance & Integration
#[instrument]Documentation & Testing
🧪 Validation Steps
Development Testing
Security Validation
Performance Testing
🔗 Related Resources
🎯 Definition of Done
Epic: #52 | Task: #11 | Requirements: 7.1-7.4 | Priority: High