20260526 增加持续soak监控与本地回放工具
This commit is contained in:
2037
src/bin/rpki_artifact_metrics.rs
Normal file
2037
src/bin/rpki_artifact_metrics.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ pub mod decode;
|
||||
pub mod encode;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod export;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod materialize;
|
||||
pub mod model;
|
||||
pub mod sequence;
|
||||
@@ -15,6 +16,7 @@ pub use export::{
|
||||
CirExportError, CirExportSummary, CirTrustAnchorBinding, build_cir_from_run,
|
||||
build_cir_from_run_multi, export_cir_from_run, export_cir_from_run_multi, write_cir_file,
|
||||
};
|
||||
#[cfg(feature = "full")]
|
||||
pub use materialize::{
|
||||
CirMaterializeError, CirMaterializeSummary, materialize_cir, materialize_cir_from_raw_store,
|
||||
materialize_cir_from_repo_bytes, mirror_relative_path_for_rsync_uri, resolve_static_pool_file,
|
||||
|
||||
@@ -12,6 +12,7 @@ pub mod audit_downloads;
|
||||
pub mod audit_trace;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod blob_store;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod cli;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod current_repo_index;
|
||||
|
||||
@@ -589,6 +589,48 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
struct FailRrdpThenFailRsyncExecutor {
|
||||
rrdp_count: Arc<AtomicUsize>,
|
||||
rsync_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl RepoTransportExecutor for FailRrdpThenFailRsyncExecutor {
|
||||
fn execute_transport(&self, task: RepoTransportTask) -> RepoTransportResultEnvelope {
|
||||
match task.mode {
|
||||
RepoTransportMode::Rrdp => {
|
||||
self.rrdp_count.fetch_add(1, Ordering::SeqCst);
|
||||
RepoTransportResultEnvelope {
|
||||
dedup_key: task.dedup_key,
|
||||
repo_identity: task.repo_identity,
|
||||
mode: RepoTransportMode::Rrdp,
|
||||
tal_id: task.tal_id,
|
||||
rir_id: task.rir_id,
|
||||
timing_ms: 10,
|
||||
result: RepoTransportResultKind::Failed {
|
||||
detail: "rrdp failed".to_string(),
|
||||
warnings: vec![Warning::new("rrdp failed")],
|
||||
},
|
||||
}
|
||||
}
|
||||
RepoTransportMode::Rsync => {
|
||||
self.rsync_count.fetch_add(1, Ordering::SeqCst);
|
||||
RepoTransportResultEnvelope {
|
||||
dedup_key: task.dedup_key,
|
||||
repo_identity: task.repo_identity,
|
||||
mode: RepoTransportMode::Rsync,
|
||||
tal_id: task.tal_id,
|
||||
rir_id: task.rir_id,
|
||||
timing_ms: 12,
|
||||
result: RepoTransportResultKind::Failed {
|
||||
detail: "rsync failed".to_string(),
|
||||
warnings: vec![Warning::new("rsync failed")],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phase1_runtime_waits_for_rrdp_transport_and_returns_rrdp_outcome() {
|
||||
let coordinator = GlobalRunCoordinator::new(
|
||||
@@ -852,6 +894,42 @@ mod tests {
|
||||
assert_eq!(rsync_count.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phase1_runtime_terminal_failure_keeps_rsync_failure_duration() {
|
||||
let rrdp_count = Arc::new(AtomicUsize::new(0));
|
||||
let rsync_count = Arc::new(AtomicUsize::new(0));
|
||||
let coordinator = GlobalRunCoordinator::new(
|
||||
ParallelPhase1Config::default(),
|
||||
vec![TalInputSpec::from_url("https://example.test/arin.tal")],
|
||||
);
|
||||
let pool = RepoTransportWorkerPool::new(
|
||||
RepoWorkerPoolConfig { max_workers: 1 },
|
||||
FailRrdpThenFailRsyncExecutor {
|
||||
rrdp_count: Arc::clone(&rrdp_count),
|
||||
rsync_count: Arc::clone(&rsync_count),
|
||||
},
|
||||
)
|
||||
.expect("pool");
|
||||
let runtime = Phase1RepoSyncRuntime::new(
|
||||
coordinator,
|
||||
pool,
|
||||
Arc::new(|_base: &str| "rsync://example.test/module/".to_string()),
|
||||
SyncPreference::RrdpThenRsync,
|
||||
);
|
||||
|
||||
let outcome = runtime
|
||||
.sync_publication_point_repo(&sample_ca("rsync://example.test/repo/root.mft"))
|
||||
.expect("sync repo");
|
||||
assert!(!outcome.repo_sync_ok);
|
||||
assert_eq!(
|
||||
outcome.repo_sync_phase.as_deref(),
|
||||
Some("rrdp_failed_rsync_failed")
|
||||
);
|
||||
assert_eq!(outcome.repo_sync_duration_ms, 12);
|
||||
assert_eq!(rrdp_count.load(Ordering::SeqCst), 1);
|
||||
assert_eq!(rsync_count.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phase1_runtime_prefetch_submits_transport_task_before_consumption() {
|
||||
let rrdp_count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
@@ -433,6 +433,7 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
|
||||
}
|
||||
|
||||
let repo_sync_started = std::time::Instant::now();
|
||||
let mut runtime_repo_sync_duration_ms = None;
|
||||
let (repo_sync_ok, repo_sync_err, repo_sync_source, repo_sync_phase): (
|
||||
bool,
|
||||
Option<String>,
|
||||
@@ -444,9 +445,10 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
|
||||
repo_sync_err,
|
||||
repo_sync_source,
|
||||
repo_sync_phase,
|
||||
repo_sync_duration_ms: _,
|
||||
repo_sync_duration_ms,
|
||||
warnings: repo_warnings,
|
||||
} = runtime.sync_publication_point_repo(ca)?;
|
||||
runtime_repo_sync_duration_ms = Some(repo_sync_duration_ms);
|
||||
warnings.extend(repo_warnings);
|
||||
(
|
||||
repo_sync_ok,
|
||||
@@ -575,7 +577,11 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
|
||||
}
|
||||
}
|
||||
};
|
||||
let repo_sync_duration_ms = repo_sync_started.elapsed().as_millis() as u64;
|
||||
let repo_sync_duration_ms = effective_repo_sync_duration_ms(
|
||||
repo_sync_started.elapsed().as_millis() as u64,
|
||||
runtime_repo_sync_duration_ms,
|
||||
repo_sync_ok,
|
||||
);
|
||||
crate::progress_log::emit(
|
||||
"publication_point_repo_sync_done",
|
||||
serde_json::json!({
|
||||
@@ -1640,6 +1646,19 @@ fn repo_sync_source_label(source: crate::sync::repo::RepoSyncSource) -> &'static
|
||||
}
|
||||
}
|
||||
|
||||
fn effective_repo_sync_duration_ms(
|
||||
elapsed_ms: u64,
|
||||
runtime_reported_duration_ms: Option<u64>,
|
||||
repo_sync_ok: bool,
|
||||
) -> u64 {
|
||||
if repo_sync_ok {
|
||||
return elapsed_ms;
|
||||
}
|
||||
runtime_reported_duration_ms
|
||||
.map(|runtime_ms| elapsed_ms.max(runtime_ms))
|
||||
.unwrap_or(elapsed_ms)
|
||||
}
|
||||
|
||||
fn kind_from_vcir_artifact_kind(kind: VcirArtifactKind) -> AuditObjectKind {
|
||||
match kind {
|
||||
VcirArtifactKind::Mft => AuditObjectKind::Manifest,
|
||||
@@ -6463,6 +6482,15 @@ authorityKeyIdentifier = keyid:always
|
||||
assert!(audit.objects.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn effective_repo_sync_duration_uses_runtime_duration_for_failures() {
|
||||
assert_eq!(effective_repo_sync_duration_ms(0, Some(12), false), 12);
|
||||
assert_eq!(effective_repo_sync_duration_ms(5, Some(12), false), 12);
|
||||
assert_eq!(effective_repo_sync_duration_ms(20, Some(12), false), 20);
|
||||
assert_eq!(effective_repo_sync_duration_ms(5, None, false), 5);
|
||||
assert_eq!(effective_repo_sync_duration_ms(5, Some(12), true), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reconstruct_snapshot_from_vcir_reports_missing_manifest_and_related_raw_bytes() {
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
|
||||
Reference in New Issue
Block a user