How DCG History and Telemetry Tracking Works in Destructive Command Guard
Destructive Command Guard (dcg) records every evaluated command in a lightweight SQLite database using an asynchronous writer that batches entries to avoid blocking the main pipeline.
The dcg history and telemetry tracking system provides comprehensive audit capabilities for command-line operations in the Dicklesworthstone/destructive_command_guard repository. This subsystem captures execution metadata, outcomes, and analytical data while maintaining minimal performance overhead through asynchronous I/O workers and configurable redaction policies.
Core Architecture of DCG History and Telemetry
The history subsystem resides in src/history/ and consists of three primary components that work together to provide durable, queryable records of all command evaluations.
HistoryDb SQLite Backend
The HistoryDb struct in src/history/mod.rs manages persistent storage using SQLite. It creates and maintains two tables: the commands table for raw entries and a virtual commands_fts table for full-text search capabilities. The database also stores a schema_version row to facilitate migrations. As implemented in the source code, HistoryDb provides the log_commands_batch() method for bulk inserts and implements recovery logic through recover_history_db() when corruption is detected.
HistoryWriter Async Pipeline
The HistoryWriter struct handles non-blocking command logging. According to src/history/mod.rs, the writer spawns a dedicated history_worker thread that receives CommandEntry structs through an mpsc channel. The writer batches entries until reaching either the batch_size threshold (default 50) or the flush_interval duration (100 ms), then persists them via flush_batch(). This architecture ensures that the main dcg pipeline never blocks on I/O operations.
CommandEntry Data Model
Defined in src/history/schema.rs, the CommandEntry struct captures:
- UTC timestamp
- Agent type (e.g., "claude_code")
- Working directory
- Command string (with optional redaction)
- Outcome enum (
AlloworDeny) - Session ID generated via
generate_session_id()
The History Tracking Workflow
When dcg evaluates a command, the tracking workflow follows this pipeline:
dcg evaluates a command → HistoryWriter::log(entry) → mpsc channel →
history_worker thread → batch → HistoryDb::log_commands_batch()
The writer initializes through HistoryWriter::new(db_path, &config), which reads configuration from src/config.rs. If the DCG_HISTORY_DISABLED environment variable is set, the function returns a no-op writer that discards entries without database interaction.
Each log() call processes the command through redact_for_history() according to the HistoryRedactionMode setting—supporting None, Full, or Pattern modes to mask sensitive arguments. The worker thread accumulates entries until flush conditions are met. If flush_batch() encounters errors, it falls back to single-row inserts; fatal storage errors trigger database recovery attempts via recover_history_db(). Persistent failures cause the writer to disable further writes for that process to prevent cascading errors.
Telemetry Features and Data Management
Beyond simple logging, the dcg history and telemetry tracking system provides automated maintenance and analytical capabilities.
Auto-Pruning and Retention
The history_worker periodically checks HistoryDb::should_auto_prune() when auto_prune is enabled in the configuration. When triggered, it executes prune_older_than_days(retention_days), maintaining a default 90-day retention window to bound database size. This automated cleanup runs without user intervention while preserving recent analytical data.
Session Tracking
Each HistoryWriter instance generates a unique session identifier using SHA-256 via generate_session_id(), producing values prefixed with ses-. This identifier attaches to every CommandEntry in that session, enabling retrospective grouping of all events from a single dcg run for debugging or audit trails.
Command Redaction
Security-sensitive data protection occurs through the redact_for_history helper, which delegates to the logging subsystem in src/logging.rs. When configured with HistoryRedactionMode::Pattern, the system applies regex patterns to mask passwords, tokens, or other confidential arguments before persistence, ensuring compliance with security policies while maintaining audit functionality.
Export and Analytics
HistoryDb implements comprehensive export APIs supporting ExportOptions and ExportFilters to produce JSON, SARIF, or CSV outputs. Security teams can query aggregated statistics using analyze_pack_effectiveness(), which returns PackEffectivenessAnalysis containing metrics such as most-frequent blocked patterns and outcome distributions. The CLI dcg stats command in src/main.rs leverages these APIs to surface pack effectiveness and denial trends.
Implementation Examples
The following examples demonstrate interacting with the history system from Rust code.
Logging a command evaluation:
use destructive_command_guard::history::{HistoryWriter, CommandEntry, Outcome};
let config = HistoryConfig::load()?; // reads ~/.config/dcg/config.toml
let writer = HistoryWriter::new(None, &config); // default DB path
let entry = CommandEntry {
timestamp: chrono::Utc::now(),
agent_type: "claude_code".into(),
working_dir: std::env::current_dir()?.to_string_lossy().into(),
command: raw_command.clone(),
outcome: Outcome::Deny,
..Default::default()
};
writer.log(entry);
Synchronous flushing before process termination:
// Usually called in Drop, but can be explicit for a graceful shutdown.
writer.flush_sync();
Retrieving analytical data:
use destructive_command_guard::history::{HistoryDb, PackEffectivenessAnalysis};
let db = HistoryDb::open(None)?; // default location
let analysis = db.analyze_pack_effectiveness()?; // returns `PackEffectivenessAnalysis`
println!("Most frequent block: {}", analysis.most_frequent_block);
Summary
- Destructive Command Guard maintains a SQLite-based history system in
src/history/that records every command evaluation with metadata and outcomes. - Asynchronous architecture using
HistoryWriterand a dedicatedhistory_workerthread ensures zero blocking of the main evaluation pipeline through batch processing (default 50 entries or 100ms intervals). - Data protection via configurable
HistoryRedactionModesettings and automatic session ID generation enables secure audit trails grouped by execution context. - Maintenance automation includes auto-pruning (default 90-day retention) and database recovery mechanisms to ensure long-term reliability.
- Export capabilities support JSON, SARIF, and CSV formats for compliance reporting and security analytics through
PackEffectivenessAnalysis.
Frequently Asked Questions
How does DCG store command history?
DCG persists command history in a lightweight SQLite database managed by the HistoryDb struct. The system creates the commands table for raw entries and a commands_fts virtual table for full-text search. Storage operations occur asynchronously through a dedicated worker thread that batches writes to minimize I/O impact on the main process.
What happens if the history database becomes corrupted?
The HistoryWriter implements error handling in flush_batch() that attempts single-row insert fallback when bulk operations fail. For fatal storage errors, the system invokes recover_history_db() to restore database integrity. If recovery fails, the writer disables further persistence for that process to prevent crash loops while allowing dcg to continue operating.
Can I disable history tracking in DCG?
Yes. Setting the DCG_HISTORY_DISABLED environment variable causes HistoryWriter::new() to return a no-op writer that immediately discards all entries without database interaction. Alternatively, configuration options in HistoryConfig allow tuning redaction levels and disabling auto-pruning without stopping history collection entirely.
How does DCG protect sensitive data in command history?
The redact_for_history helper in src/logging.rs processes commands according to HistoryRedactionMode before persistence. The Pattern mode applies configurable regex patterns to mask sensitive arguments like passwords or API keys, while Full mode redacts the entire command string. This ensures audit trails remain useful without exposing confidential information.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →