use std::time::Instant;
use chrono::Utc;
use crate::catalog::operability_evidence_report_uri;
use crate::error::Result;
use crate::evidence::{build_operability_evidence_checks, evidence_status};
use crate::models::{
OperabilityCoverage, OperabilityEvidenceReport, OperabilitySampleWindow, QueueDiagnostics,
};
use super::AxiomSync;
struct OperabilityRuntimeState {
traces_analyzed: usize,
request_logs_scanned: usize,
request_type_count: usize,
trace_metrics_snapshot_uri: String,
queue: QueueDiagnostics,
}
impl AxiomSync {
pub fn collect_operability_evidence(
&self,
trace_limit: usize,
request_limit: usize,
) -> Result<OperabilityEvidenceReport> {
let request_id = uuid::Uuid::new_v4().to_string();
let started = Instant::now();
let trace_limit = trace_limit.max(1);
let request_limit = request_limit.max(1);
let output = (|| -> Result<OperabilityEvidenceReport> {
let runtime = self.collect_operability_runtime_state(trace_limit, request_limit)?;
let checks = build_operability_evidence_checks(
runtime.request_logs_scanned,
runtime.traces_analyzed,
runtime.request_type_count,
&runtime.queue,
);
let passed = checks.iter().all(|check| check.passed);
let status = evidence_status(passed);
let report_id = uuid::Uuid::new_v4().to_string();
let report_uri = operability_evidence_report_uri(&report_id)?;
let report = OperabilityEvidenceReport {
report_id,
created_at: Utc::now().to_rfc3339(),
passed,
status,
sample_window: OperabilitySampleWindow {
trace_limit,
request_limit,
},
coverage: OperabilityCoverage {
traces_analyzed: runtime.traces_analyzed,
request_logs_scanned: runtime.request_logs_scanned,
trace_metrics_snapshot_uri: runtime.trace_metrics_snapshot_uri,
},
queue: runtime.queue,
checks,
report_uri: report_uri.to_string(),
};
self.fs
.write(&report_uri, &serde_json::to_string_pretty(&report)?, true)?;
Ok(report)
})();
match output {
Ok(report) => {
self.log_request_status(
request_id,
"operability.evidence",
report.status.as_str(),
started,
None,
Some(serde_json::json!({
"trace_limit": report.sample_window.trace_limit,
"request_limit": report.sample_window.request_limit,
"passed": report.passed,
"traces_analyzed": report.coverage.traces_analyzed,
"request_logs_scanned": report.coverage.request_logs_scanned,
"trace_metrics_snapshot_uri": report.coverage.trace_metrics_snapshot_uri,
"report_uri": report.report_uri,
})),
);
Ok(report)
}
Err(err) => {
self.log_request_error(
request_id,
"operability.evidence",
started,
None,
&err,
Some(serde_json::json!({
"trace_limit": trace_limit,
"request_limit": request_limit,
})),
);
Err(err)
}
}
}
fn collect_operability_runtime_state(
&self,
trace_limit: usize,
request_limit: usize,
) -> Result<OperabilityRuntimeState> {
let trace_snapshot = self.create_trace_metrics_snapshot(trace_limit, false)?;
let trace_metrics = self.trace_metrics(trace_limit, false)?;
let request_logs = self.list_request_logs(request_limit)?;
let queue = self.queue_diagnostics()?;
Ok(OperabilityRuntimeState {
traces_analyzed: trace_metrics.traces_analyzed,
request_logs_scanned: request_logs.len(),
request_type_count: trace_metrics.by_request_type.len(),
trace_metrics_snapshot_uri: trace_snapshot.report_uri,
queue,
})
}
}