feat: enhance tracing with field attributes and warn logging across all handlers
All checks were successful
CI / Tests (push) Successful in 5m17s
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 3s
CI / Deploy Dashboard (push) Has been skipped
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Has been skipped
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m38s
CI / Security Audit (push) Successful in 1m50s
All checks were successful
CI / Tests (push) Successful in 5m17s
CI / Detect Changes (push) Successful in 3s
CI / Deploy Agent (push) Successful in 3s
CI / Deploy Dashboard (push) Has been skipped
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Has been skipped
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m38s
CI / Security Audit (push) Successful in 1m50s
Add repo_id, finding_id, and filter fields to tracing::instrument attributes for better trace correlation in SigNoz. Replace all silently swallowed errors (Err(_) => Vec::new()) with tracing::warn! logging across mod.rs, dast.rs, graph.rs handlers. Add stage-level spans with .instrument() to pipeline orchestrator for visibility into scan phases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use mongodb::bson::doc;
|
||||
use tracing::Instrument;
|
||||
|
||||
use compliance_core::models::*;
|
||||
use compliance_core::traits::Scanner;
|
||||
@@ -50,7 +51,7 @@ impl PipelineOrchestrator {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id, trigger = ?trigger))]
|
||||
pub async fn run(&self, repo_id: &str, trigger: ScanTrigger) -> Result<(), AgentError> {
|
||||
// Look up the repository
|
||||
let repo = self
|
||||
@@ -90,6 +91,7 @@ impl PipelineOrchestrator {
|
||||
.await?;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(repo_id, error = %e, "Scan pipeline failed");
|
||||
self.db
|
||||
.scan_runs()
|
||||
.update_one(
|
||||
@@ -109,7 +111,7 @@ impl PipelineOrchestrator {
|
||||
result.map(|_| ())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = repo.name.as_str()))]
|
||||
async fn run_pipeline(
|
||||
&self,
|
||||
repo: &TrackedRepository,
|
||||
@@ -138,8 +140,13 @@ impl PipelineOrchestrator {
|
||||
// Stage 1: Semgrep SAST
|
||||
tracing::info!("[{repo_id}] Stage 1: Semgrep SAST");
|
||||
self.update_phase(scan_run_id, "sast").await;
|
||||
let semgrep = SemgrepScanner;
|
||||
match semgrep.scan(&repo_path, &repo_id).await {
|
||||
match async {
|
||||
let semgrep = SemgrepScanner;
|
||||
semgrep.scan(&repo_path, &repo_id).await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_sast"))
|
||||
.await
|
||||
{
|
||||
Ok(output) => all_findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] Semgrep failed: {e}"),
|
||||
}
|
||||
@@ -147,8 +154,13 @@ impl PipelineOrchestrator {
|
||||
// Stage 2: SBOM Generation
|
||||
tracing::info!("[{repo_id}] Stage 2: SBOM Generation");
|
||||
self.update_phase(scan_run_id, "sbom_generation").await;
|
||||
let sbom_scanner = SbomScanner;
|
||||
let mut sbom_entries = match sbom_scanner.scan(&repo_path, &repo_id).await {
|
||||
let mut sbom_entries = match async {
|
||||
let sbom_scanner = SbomScanner;
|
||||
sbom_scanner.scan(&repo_path, &repo_id).await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_sbom_generation"))
|
||||
.await
|
||||
{
|
||||
Ok(output) => output.sbom_entries,
|
||||
Err(e) => {
|
||||
tracing::warn!("[{repo_id}] SBOM generation failed: {e}");
|
||||
@@ -167,9 +179,13 @@ impl PipelineOrchestrator {
|
||||
k.expose_secret().to_string()
|
||||
}),
|
||||
);
|
||||
let cve_alerts = match cve_scanner
|
||||
.scan_dependencies(&repo_id, &mut sbom_entries)
|
||||
.await
|
||||
let cve_alerts = match async {
|
||||
cve_scanner
|
||||
.scan_dependencies(&repo_id, &mut sbom_entries)
|
||||
.await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_cve_scanning"))
|
||||
.await
|
||||
{
|
||||
Ok(alerts) => alerts,
|
||||
Err(e) => {
|
||||
@@ -181,22 +197,36 @@ impl PipelineOrchestrator {
|
||||
// Stage 4: Pattern Scanning (GDPR + OAuth)
|
||||
tracing::info!("[{repo_id}] Stage 4: Pattern Scanning");
|
||||
self.update_phase(scan_run_id, "pattern_scanning").await;
|
||||
let gdpr = GdprPatternScanner::new();
|
||||
match gdpr.scan(&repo_path, &repo_id).await {
|
||||
Ok(output) => all_findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] GDPR pattern scan failed: {e}"),
|
||||
}
|
||||
let oauth = OAuthPatternScanner::new();
|
||||
match oauth.scan(&repo_path, &repo_id).await {
|
||||
Ok(output) => all_findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] OAuth pattern scan failed: {e}"),
|
||||
{
|
||||
let pattern_findings = async {
|
||||
let mut findings = Vec::new();
|
||||
let gdpr = GdprPatternScanner::new();
|
||||
match gdpr.scan(&repo_path, &repo_id).await {
|
||||
Ok(output) => findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] GDPR pattern scan failed: {e}"),
|
||||
}
|
||||
let oauth = OAuthPatternScanner::new();
|
||||
match oauth.scan(&repo_path, &repo_id).await {
|
||||
Ok(output) => findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] OAuth pattern scan failed: {e}"),
|
||||
}
|
||||
findings
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_pattern_scanning"))
|
||||
.await;
|
||||
all_findings.extend(pattern_findings);
|
||||
}
|
||||
|
||||
// Stage 4a: Secret Detection (Gitleaks)
|
||||
tracing::info!("[{repo_id}] Stage 4a: Secret Detection");
|
||||
self.update_phase(scan_run_id, "secret_detection").await;
|
||||
let gitleaks = GitleaksScanner;
|
||||
match gitleaks.scan(&repo_path, &repo_id).await {
|
||||
match async {
|
||||
let gitleaks = GitleaksScanner;
|
||||
gitleaks.scan(&repo_path, &repo_id).await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_secret_detection"))
|
||||
.await
|
||||
{
|
||||
Ok(output) => all_findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] Gitleaks failed: {e}"),
|
||||
}
|
||||
@@ -204,8 +234,13 @@ impl PipelineOrchestrator {
|
||||
// Stage 4b: Lint Scanning
|
||||
tracing::info!("[{repo_id}] Stage 4b: Lint Scanning");
|
||||
self.update_phase(scan_run_id, "lint_scanning").await;
|
||||
let lint = LintScanner;
|
||||
match lint.scan(&repo_path, &repo_id).await {
|
||||
match async {
|
||||
let lint = LintScanner;
|
||||
lint.scan(&repo_path, &repo_id).await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_lint_scanning"))
|
||||
.await
|
||||
{
|
||||
Ok(output) => all_findings.extend(output.findings),
|
||||
Err(e) => tracing::warn!("[{repo_id}] Lint scanning failed: {e}"),
|
||||
}
|
||||
@@ -214,19 +249,26 @@ impl PipelineOrchestrator {
|
||||
if let Some(old_sha) = &repo.last_scanned_commit {
|
||||
tracing::info!("[{repo_id}] Stage 4c: LLM Code Review");
|
||||
self.update_phase(scan_run_id, "code_review").await;
|
||||
let reviewer = CodeReviewScanner::new(self.llm.clone());
|
||||
let review_output = reviewer
|
||||
.review_diff(&repo_path, &repo_id, old_sha, ¤t_sha)
|
||||
.await;
|
||||
let review_output = async {
|
||||
let reviewer = CodeReviewScanner::new(self.llm.clone());
|
||||
reviewer
|
||||
.review_diff(&repo_path, &repo_id, old_sha, ¤t_sha)
|
||||
.await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_code_review"))
|
||||
.await;
|
||||
all_findings.extend(review_output.findings);
|
||||
}
|
||||
|
||||
// Stage 4.5: Graph Building
|
||||
tracing::info!("[{repo_id}] Stage 4.5: Graph Building");
|
||||
self.update_phase(scan_run_id, "graph_building").await;
|
||||
let graph_context = match self
|
||||
.build_code_graph(&repo_path, &repo_id, &all_findings)
|
||||
.await
|
||||
let graph_context = match async {
|
||||
self.build_code_graph(&repo_path, &repo_id, &all_findings)
|
||||
.await
|
||||
}
|
||||
.instrument(tracing::info_span!("stage_graph_building"))
|
||||
.await
|
||||
{
|
||||
Ok(ctx) => Some(ctx),
|
||||
Err(e) => {
|
||||
|
||||
Reference in New Issue
Block a user