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:
@@ -17,7 +17,7 @@ use super::ApiResponse;
|
||||
type AgentExt = Extension<Arc<ComplianceAgent>>;
|
||||
|
||||
/// POST /api/v1/chat/:repo_id — Send a chat message with RAG context
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn chat(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -127,7 +127,7 @@ pub async fn chat(
|
||||
}
|
||||
|
||||
/// POST /api/v1/chat/:repo_id/build-embeddings — Trigger embedding build
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn build_embeddings(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -228,7 +228,7 @@ pub async fn build_embeddings(
|
||||
}
|
||||
|
||||
/// GET /api/v1/chat/:repo_id/status — Get latest embedding build status
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn embedding_status(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
|
||||
@@ -63,7 +63,10 @@ pub async fn list_targets(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch DAST targets: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -101,7 +104,7 @@ pub async fn add_target(
|
||||
}
|
||||
|
||||
/// POST /api/v1/dast/targets/:id/scan — Trigger DAST scan
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(target_id = %id))]
|
||||
pub async fn trigger_scan(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
@@ -163,7 +166,10 @@ pub async fn list_scan_runs(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch DAST scan runs: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -196,7 +202,10 @@ pub async fn list_findings(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch DAST findings: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -207,7 +216,7 @@ pub async fn list_findings(
|
||||
}
|
||||
|
||||
/// GET /api/v1/dast/findings/:id — Finding detail with evidence
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(finding_id = %id))]
|
||||
pub async fn get_finding(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
|
||||
@@ -33,7 +33,7 @@ fn default_search_limit() -> usize {
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id — Full graph data
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn get_graph(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -55,11 +55,17 @@ pub async fn get_graph(
|
||||
|
||||
let all_nodes: Vec<CodeNode> = match db.graph_nodes().find(filter.clone()).await {
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch graph nodes: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
let edges: Vec<CodeEdge> = match db.graph_edges().find(filter).await {
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch graph edges: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
// Remove disconnected nodes (no edges) to keep the graph clean
|
||||
@@ -89,7 +95,7 @@ pub async fn get_graph(
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id/nodes — List nodes (paginated)
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn get_nodes(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -99,7 +105,10 @@ pub async fn get_nodes(
|
||||
|
||||
let nodes: Vec<CodeNode> = match db.graph_nodes().find(filter).await {
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch graph nodes: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let total = nodes.len() as u64;
|
||||
@@ -111,7 +120,7 @@ pub async fn get_nodes(
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id/communities — List detected communities
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn get_communities(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -121,7 +130,10 @@ pub async fn get_communities(
|
||||
|
||||
let nodes: Vec<CodeNode> = match db.graph_nodes().find(filter).await {
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch graph nodes for communities: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let mut communities: std::collections::HashMap<u32, Vec<String>> =
|
||||
@@ -161,7 +173,7 @@ pub struct CommunityInfo {
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id/impact/:finding_id — Impact analysis
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id, finding_id = %finding_id))]
|
||||
pub async fn get_impact(
|
||||
Extension(agent): AgentExt,
|
||||
Path((repo_id, finding_id)): Path<(String, String)>,
|
||||
@@ -183,7 +195,7 @@ pub async fn get_impact(
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id/search — BM25 symbol search
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id, query = %params.q))]
|
||||
pub async fn search_symbols(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -204,7 +216,10 @@ pub async fn search_symbols(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to search graph nodes: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let total = nodes.len() as u64;
|
||||
@@ -216,7 +231,7 @@ pub async fn search_symbols(
|
||||
}
|
||||
|
||||
/// GET /api/v1/graph/:repo_id/file-content — Read source file from cloned repo
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn get_file_content(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
@@ -278,7 +293,7 @@ pub struct FileContent {
|
||||
}
|
||||
|
||||
/// POST /api/v1/graph/:repo_id/build — Trigger graph rebuild
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %repo_id))]
|
||||
pub async fn trigger_build(
|
||||
Extension(agent): AgentExt,
|
||||
Path(repo_id): Path<String>,
|
||||
|
||||
@@ -234,7 +234,10 @@ pub async fn stats_overview(Extension(agent): AgentExt) -> ApiResult<OverviewSta
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch recent scans: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -276,7 +279,10 @@ pub async fn list_repositories(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch repositories: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -342,7 +348,7 @@ pub async fn get_ssh_public_key(
|
||||
Ok(Json(serde_json::json!({ "public_key": public_key.trim() })))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %id))]
|
||||
pub async fn trigger_scan(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
@@ -357,7 +363,7 @@ pub async fn trigger_scan(
|
||||
Ok(Json(serde_json::json!({ "status": "scan_triggered" })))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = %id))]
|
||||
pub async fn delete_repository(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
@@ -404,7 +410,7 @@ pub async fn delete_repository(
|
||||
Ok(Json(serde_json::json!({ "status": "deleted" })))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = ?filter.repo_id, severity = ?filter.severity, scan_type = ?filter.scan_type))]
|
||||
pub async fn list_findings(
|
||||
Extension(agent): AgentExt,
|
||||
Query(filter): Query<FindingsFilter>,
|
||||
@@ -463,7 +469,10 @@ pub async fn list_findings(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch findings: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -473,7 +482,7 @@ pub async fn list_findings(
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(finding_id = %id))]
|
||||
pub async fn get_finding(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
@@ -494,7 +503,7 @@ pub async fn get_finding(
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(finding_id = %id))]
|
||||
pub async fn update_finding_status(
|
||||
Extension(agent): AgentExt,
|
||||
Path(id): Path<String>,
|
||||
@@ -598,7 +607,7 @@ pub async fn sbom_filters(
|
||||
})))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, fields(repo_id = ?filter.repo_id, package_manager = ?filter.package_manager))]
|
||||
pub async fn list_sbom(
|
||||
Extension(agent): AgentExt,
|
||||
Query(filter): Query<SbomFilter>,
|
||||
@@ -644,7 +653,10 @@ pub async fn list_sbom(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch SBOM entries: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -666,7 +678,10 @@ pub async fn export_sbom(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch SBOM entries for export: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let body = if params.format == "spdx" {
|
||||
@@ -799,7 +814,10 @@ pub async fn license_summary(
|
||||
|
||||
let entries: Vec<SbomEntry> = match db.sbom_entries().find(query).await {
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch SBOM entries for license summary: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let mut license_map: std::collections::HashMap<String, Vec<String>> =
|
||||
@@ -845,7 +863,10 @@ pub async fn sbom_diff(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch SBOM entries for repo_a: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
let entries_b: Vec<SbomEntry> = match db
|
||||
@@ -854,7 +875,10 @@ pub async fn sbom_diff(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch SBOM entries for repo_b: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
// Build maps by (name, package_manager) -> version
|
||||
@@ -944,7 +968,10 @@ pub async fn list_issues(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch tracker issues: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
@@ -972,7 +999,10 @@ pub async fn list_scan_runs(
|
||||
.await
|
||||
{
|
||||
Ok(cursor) => collect_cursor_async(cursor).await,
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to fetch scan runs: {e}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Json(ApiResponse {
|
||||
|
||||
Reference in New Issue
Block a user