20260609 CIR区分fresh和cached验证输入
This commit is contained in:
@@ -352,11 +352,24 @@ impl Histogram {
|
||||
struct CirMetrics {
|
||||
version: u32,
|
||||
objects: u64,
|
||||
fresh_objects: u64,
|
||||
cached_objects: u64,
|
||||
trust_anchors: u64,
|
||||
rejected_objects: u64,
|
||||
fresh_rejected_objects: u64,
|
||||
cached_rejected_objects: u64,
|
||||
object_list_sha256: String,
|
||||
fresh_object_list_sha256: String,
|
||||
cached_object_list_sha256: String,
|
||||
reject_list_sha256: String,
|
||||
fresh_reject_list_sha256: String,
|
||||
cached_reject_list_sha256: String,
|
||||
objects_by_type: BTreeMap<String, u64>,
|
||||
fresh_objects_by_type: BTreeMap<String, u64>,
|
||||
cached_objects_by_type: BTreeMap<String, u64>,
|
||||
rejected_objects_by_type: BTreeMap<String, u64>,
|
||||
fresh_rejected_objects_by_type: BTreeMap<String, u64>,
|
||||
cached_rejected_objects_by_type: BTreeMap<String, u64>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize)]
|
||||
@@ -973,25 +986,62 @@ fn parse_cir(path: &Path, snapshot: &mut MetricsSnapshot) {
|
||||
{
|
||||
Ok(cir) => {
|
||||
let mut objects_by_type = BTreeMap::new();
|
||||
for object in &cir.objects {
|
||||
for object in cir.validated_objects() {
|
||||
*objects_by_type
|
||||
.entry(object_type_from_uri(&object.rsync_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
let mut fresh_objects_by_type = BTreeMap::new();
|
||||
for object in &cir.fresh_validated_objects {
|
||||
*fresh_objects_by_type
|
||||
.entry(object_type_from_uri(&object.rsync_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
let mut cached_objects_by_type = BTreeMap::new();
|
||||
for object in &cir.cached_validated_objects {
|
||||
*cached_objects_by_type
|
||||
.entry(object_type_from_uri(&object.rsync_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
let mut rejected_objects_by_type = BTreeMap::new();
|
||||
for object in &cir.rejected_objects {
|
||||
for object in cir.rejected_objects() {
|
||||
*rejected_objects_by_type
|
||||
.entry(object_type_from_uri(&object.object_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
let mut fresh_rejected_objects_by_type = BTreeMap::new();
|
||||
for object in &cir.fresh_rejected_objects {
|
||||
*fresh_rejected_objects_by_type
|
||||
.entry(object_type_from_uri(&object.object_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
let mut cached_rejected_objects_by_type = BTreeMap::new();
|
||||
for object in &cir.cached_rejected_objects {
|
||||
*cached_rejected_objects_by_type
|
||||
.entry(object_type_from_uri(&object.object_uri))
|
||||
.or_default() += 1;
|
||||
}
|
||||
snapshot.cir = Some(CirMetrics {
|
||||
version: cir.version,
|
||||
objects: cir.objects.len() as u64,
|
||||
objects: cir.validated_object_count() as u64,
|
||||
fresh_objects: cir.fresh_validated_objects.len() as u64,
|
||||
cached_objects: cir.cached_validated_objects.len() as u64,
|
||||
trust_anchors: cir.trust_anchors.len() as u64,
|
||||
rejected_objects: cir.rejected_objects.len() as u64,
|
||||
rejected_objects: cir.rejected_object_count() as u64,
|
||||
fresh_rejected_objects: cir.fresh_rejected_objects.len() as u64,
|
||||
cached_rejected_objects: cir.cached_rejected_objects.len() as u64,
|
||||
object_list_sha256: hex::encode(&cir.object_list_sha256),
|
||||
fresh_object_list_sha256: hex::encode(&cir.fresh_object_list_sha256),
|
||||
cached_object_list_sha256: hex::encode(&cir.cached_object_list_sha256),
|
||||
reject_list_sha256: hex::encode(&cir.reject_list_sha256),
|
||||
fresh_reject_list_sha256: hex::encode(&cir.fresh_reject_list_sha256),
|
||||
cached_reject_list_sha256: hex::encode(&cir.cached_reject_list_sha256),
|
||||
objects_by_type,
|
||||
fresh_objects_by_type,
|
||||
cached_objects_by_type,
|
||||
rejected_objects_by_type,
|
||||
fresh_rejected_objects_by_type,
|
||||
cached_rejected_objects_by_type,
|
||||
});
|
||||
}
|
||||
Err(err) => snapshot
|
||||
@@ -1580,6 +1630,14 @@ fn render_cir_metrics(writer: &mut PromWriter<'_>, instance: &str, cir: &CirMetr
|
||||
&[label("instance", instance)],
|
||||
cir.objects as f64,
|
||||
);
|
||||
for (source, count) in [("fresh", cir.fresh_objects), ("cached", cir.cached_objects)] {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_objects_by_source",
|
||||
"CIR object count by validation input source",
|
||||
&[label("instance", instance), label("source", source)],
|
||||
count as f64,
|
||||
);
|
||||
}
|
||||
writer.gauge(
|
||||
"ours_rp_cir_trust_anchors",
|
||||
"CIR trust anchor count",
|
||||
@@ -1592,6 +1650,29 @@ fn render_cir_metrics(writer: &mut PromWriter<'_>, instance: &str, cir: &CirMetr
|
||||
&[label("instance", instance)],
|
||||
cir.rejected_objects as f64,
|
||||
);
|
||||
for (source, count) in [
|
||||
("fresh", cir.fresh_rejected_objects),
|
||||
("cached", cir.cached_rejected_objects),
|
||||
] {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_rejected_objects_by_source",
|
||||
"CIR rejected object count by validation input source",
|
||||
&[label("instance", instance), label("source", source)],
|
||||
count as f64,
|
||||
);
|
||||
}
|
||||
for (source, digest) in [
|
||||
("merged", cir.object_list_sha256.as_str()),
|
||||
("fresh", cir.fresh_object_list_sha256.as_str()),
|
||||
("cached", cir.cached_object_list_sha256.as_str()),
|
||||
] {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_object_list_digest_present",
|
||||
"CIR object list digest is present by validation input source",
|
||||
&[label("instance", instance), label("source", source)],
|
||||
if digest.len() == 64 { 1.0 } else { 0.0 },
|
||||
);
|
||||
}
|
||||
writer.gauge(
|
||||
"ours_rp_cir_reject_list_digest_present",
|
||||
"CIR reject list digest is present",
|
||||
@@ -1602,6 +1683,18 @@ fn render_cir_metrics(writer: &mut PromWriter<'_>, instance: &str, cir: &CirMetr
|
||||
0.0
|
||||
},
|
||||
);
|
||||
for (source, digest) in [
|
||||
("merged", cir.reject_list_sha256.as_str()),
|
||||
("fresh", cir.fresh_reject_list_sha256.as_str()),
|
||||
("cached", cir.cached_reject_list_sha256.as_str()),
|
||||
] {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_reject_list_digest_present_by_source",
|
||||
"CIR reject list digest is present by validation input source",
|
||||
&[label("instance", instance), label("source", source)],
|
||||
if digest.len() == 64 { 1.0 } else { 0.0 },
|
||||
);
|
||||
}
|
||||
for (object_type, count) in &cir.objects_by_type {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_objects_by_type",
|
||||
@@ -1613,6 +1706,23 @@ fn render_cir_metrics(writer: &mut PromWriter<'_>, instance: &str, cir: &CirMetr
|
||||
*count as f64,
|
||||
);
|
||||
}
|
||||
for (source, counts) in [
|
||||
("fresh", &cir.fresh_objects_by_type),
|
||||
("cached", &cir.cached_objects_by_type),
|
||||
] {
|
||||
for (object_type, count) in counts {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_objects_by_source_type",
|
||||
"CIR object count by validation input source and file type",
|
||||
&[
|
||||
label("instance", instance),
|
||||
label("source", source),
|
||||
label("object_type", object_type),
|
||||
],
|
||||
*count as f64,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (object_type, count) in &cir.rejected_objects_by_type {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_rejected_objects_by_type",
|
||||
@@ -1624,6 +1734,23 @@ fn render_cir_metrics(writer: &mut PromWriter<'_>, instance: &str, cir: &CirMetr
|
||||
*count as f64,
|
||||
);
|
||||
}
|
||||
for (source, counts) in [
|
||||
("fresh", &cir.fresh_rejected_objects_by_type),
|
||||
("cached", &cir.cached_rejected_objects_by_type),
|
||||
] {
|
||||
for (object_type, count) in counts {
|
||||
writer.gauge(
|
||||
"ours_rp_cir_rejected_objects_by_source_type",
|
||||
"CIR rejected object count by validation input source and file type",
|
||||
&[
|
||||
label("instance", instance),
|
||||
label("source", source),
|
||||
label("object_type", object_type),
|
||||
],
|
||||
*count as f64,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_ccr_metrics(writer: &mut PromWriter<'_>, instance: &str, ccr: &CcrMetrics) {
|
||||
@@ -2092,8 +2219,8 @@ mod tests {
|
||||
encode_content_info,
|
||||
};
|
||||
use crate::cir::{
|
||||
CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirRejectedObject,
|
||||
CirTrustAnchor, compute_reject_list_sha256, encode_cir, sha256,
|
||||
CanonicalInputRepresentation, CirObject, CirRejectedObject, CirTrustAnchor, encode_cir,
|
||||
sha256,
|
||||
};
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -2154,7 +2281,7 @@ mod tests {
|
||||
assert!(snapshot.repo_stats[0].sync_success);
|
||||
assert_eq!(snapshot.repo_stats[0].download_bytes, 333);
|
||||
assert_eq!(snapshot.top_pp_by_object_count[0].object_count, 2);
|
||||
assert_eq!(snapshot.cir.as_ref().unwrap().objects, 1);
|
||||
assert_eq!(snapshot.cir.as_ref().unwrap().objects, 2);
|
||||
assert_eq!(snapshot.ccr.as_ref().unwrap().state_items["tas"], 1);
|
||||
let metrics = render_metrics(&snapshot);
|
||||
assert!(metrics.contains("ours_rp_repository_info"));
|
||||
@@ -2162,12 +2289,29 @@ mod tests {
|
||||
assert!(metrics.contains("ours_rp_repository_download_bytes"));
|
||||
assert!(metrics.contains("ours_rp_large_publication_points"));
|
||||
assert!(metrics.contains("ours_rp_cir_objects"));
|
||||
assert!(metrics.contains("ours_rp_cir_objects_by_source"));
|
||||
assert!(metrics.contains("ours_rp_cir_rejected_objects_by_source"));
|
||||
assert!(metrics.contains("ours_rp_cir_objects_by_source_type"));
|
||||
assert!(metrics.contains("ours_rp_cir_rejected_objects_by_source_type"));
|
||||
assert!(metrics.contains("ours_rp_cir_object_list_digest_present"));
|
||||
assert!(metrics.contains("ours_rp_cir_reject_list_digest_present_by_source"));
|
||||
assert!(metrics.contains("ours_rp_ccr_state_items"));
|
||||
assert!(
|
||||
metrics.contains(r#"ours_rp_cir_objects_by_source{instance="test",source="fresh"} 2"#)
|
||||
);
|
||||
assert!(
|
||||
metrics.contains(r#"ours_rp_cir_objects_by_source{instance="test",source="cached"} 0"#)
|
||||
);
|
||||
assert!(metrics.contains(
|
||||
r#"ours_rp_cir_rejected_objects_by_source{instance="test",source="fresh"} 1"#
|
||||
));
|
||||
assert!(metrics.contains(r#"ours_rp_vrps{instance="test",kind="total"} 3"#));
|
||||
assert!(metrics.contains(r#"ours_rp_vrps{instance="test",kind="unique"} 2"#));
|
||||
let status = render_status_json(&snapshot).expect("status");
|
||||
assert!(status.contains("topPublicationPointsByObjectCount"));
|
||||
assert!(status.contains(r#""vrpsUnique": 2"#));
|
||||
assert!(status.contains(r#""freshObjects": 2"#));
|
||||
assert!(status.contains(r#""cachedObjects": 0"#));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2186,30 +2330,33 @@ mod tests {
|
||||
object_uri: "rsync://repo.example/a/bad.roa".to_string(),
|
||||
reason: Some("bad".to_string()),
|
||||
}];
|
||||
let cir = CanonicalInputRepresentation {
|
||||
version: crate::cir::CIR_VERSION_V3,
|
||||
hash_alg: CirHashAlgorithm::Sha256,
|
||||
validation_time: time::OffsetDateTime::parse(
|
||||
let cir = CanonicalInputRepresentation::new_v4(
|
||||
time::OffsetDateTime::parse(
|
||||
"2026-05-25T00:00:00Z",
|
||||
&time::format_description::well_known::Rfc3339,
|
||||
)
|
||||
.unwrap(),
|
||||
objects: vec![CirObject {
|
||||
rsync_uri: "rsync://repo.example/a/a.roa".to_string(),
|
||||
sha256: vec![1; 32],
|
||||
}],
|
||||
trust_anchors: vec![CirTrustAnchor {
|
||||
vec![
|
||||
CirObject {
|
||||
rsync_uri: "rsync://repo.example/a/a.roa".to_string(),
|
||||
sha256: vec![1; 32],
|
||||
},
|
||||
CirObject {
|
||||
rsync_uri: "rsync://repo.example/a/bad.roa".to_string(),
|
||||
sha256: vec![2; 32],
|
||||
},
|
||||
],
|
||||
Vec::new(),
|
||||
vec![CirTrustAnchor {
|
||||
ta_rsync_uri: "rsync://repo.example/ta.cer".to_string(),
|
||||
tal_uri: "https://tal.example/tal.tal".to_string(),
|
||||
tal_bytes: b"rsync://repo.example/ta.cer\n\nAQID\n".to_vec(),
|
||||
ta_certificate_der: b"ta".to_vec(),
|
||||
ta_certificate_sha256: sha256(b"ta"),
|
||||
}],
|
||||
reject_list_sha256: compute_reject_list_sha256(
|
||||
rejected.iter().map(|item| item.object_uri.as_str()),
|
||||
),
|
||||
rejected_objects: rejected,
|
||||
};
|
||||
rejected,
|
||||
Vec::new(),
|
||||
);
|
||||
encode_cir(&cir).expect("encode cir")
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ mod tests {
|
||||
build_aspa_payload_state, build_roa_payload_state, encode_content_info,
|
||||
};
|
||||
use crate::cir::{
|
||||
CIR_VERSION_V3, CanonicalInputRepresentation, CirHashAlgorithm, CirObject,
|
||||
CirRejectedObject, CirTrustAnchor, compute_reject_list_sha256, encode_cir, sha256,
|
||||
CanonicalInputRepresentation, CirObject, CirRejectedObject, CirTrustAnchor, encode_cir,
|
||||
sha256,
|
||||
};
|
||||
use crate::data_model::roa::{IpPrefix, RoaAfi};
|
||||
use crate::validation::objects::{AspaAttestation, Vrp};
|
||||
@@ -100,6 +100,7 @@ mod tests {
|
||||
&[
|
||||
object("rsync://example.net/a.roa", 0x11),
|
||||
object("rsync://example.net/persistent.roa", 0x44),
|
||||
object("rsync://example.net/reject-old.roa", 0xee),
|
||||
],
|
||||
&[],
|
||||
64496,
|
||||
@@ -485,7 +486,18 @@ mod tests {
|
||||
9,
|
||||
64496,
|
||||
);
|
||||
write_sample_with_ccr_seq(root, "right2", 2, &[peer_mismatch], &[], 10, 64497);
|
||||
write_sample_with_ccr_seq(
|
||||
root,
|
||||
"right2",
|
||||
2,
|
||||
&[
|
||||
peer_mismatch,
|
||||
object("rsync://example.net/pp/rejected.roa", 0xee),
|
||||
],
|
||||
&[],
|
||||
10,
|
||||
64497,
|
||||
);
|
||||
std::fs::write(
|
||||
root.join("left.jsonl"),
|
||||
jsonl(&[
|
||||
@@ -845,7 +857,6 @@ mod tests {
|
||||
rejected: &[&str],
|
||||
) -> CanonicalInputRepresentation {
|
||||
let mut objects = objects.to_vec();
|
||||
objects.sort_by(|a, b| a.rsync_uri.cmp(&b.rsync_uri));
|
||||
let rejected_objects = rejected
|
||||
.iter()
|
||||
.map(|uri| CirRejectedObject {
|
||||
@@ -853,15 +864,26 @@ mod tests {
|
||||
reason: Some("test".to_string()),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
CanonicalInputRepresentation {
|
||||
version: CIR_VERSION_V3,
|
||||
hash_alg: CirHashAlgorithm::Sha256,
|
||||
validation_time: sample_time(seq),
|
||||
objects,
|
||||
trust_anchors: vec![sample_trust_anchor()],
|
||||
reject_list_sha256: compute_reject_list_sha256(rejected.iter().copied()),
|
||||
rejected_objects,
|
||||
for rejected_uri in rejected {
|
||||
if !objects
|
||||
.iter()
|
||||
.any(|object| object.rsync_uri == *rejected_uri)
|
||||
{
|
||||
objects.push(CirObject {
|
||||
rsync_uri: (*rejected_uri).to_string(),
|
||||
sha256: vec![0xee; 32],
|
||||
});
|
||||
}
|
||||
}
|
||||
objects.sort_by(|a, b| a.rsync_uri.cmp(&b.rsync_uri));
|
||||
CanonicalInputRepresentation::new_v4(
|
||||
sample_time(seq),
|
||||
objects,
|
||||
Vec::new(),
|
||||
vec![sample_trust_anchor()],
|
||||
rejected_objects,
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
fn sample_trust_anchor() -> CirTrustAnchor {
|
||||
|
||||
@@ -42,10 +42,12 @@ pub(super) fn load_sequence_meta(path: &Path, side: Side) -> Result<Vec<Sequence
|
||||
.transpose()?;
|
||||
let validation_time = cir.validation_time;
|
||||
samples.push(SequenceMeta {
|
||||
cir_object_count: raw.cir_object_count.or(Some(cir.objects.len() as u64)),
|
||||
cir_object_count: raw
|
||||
.cir_object_count
|
||||
.or(Some(cir.validated_object_count() as u64)),
|
||||
cir_reject_count: raw
|
||||
.cir_reject_count
|
||||
.or(Some(cir.rejected_objects.len() as u64)),
|
||||
.or(Some(cir.rejected_object_count() as u64)),
|
||||
cir_trust_anchor_count: raw
|
||||
.cir_trust_anchor_count
|
||||
.or(Some(cir.trust_anchors.len() as u64)),
|
||||
@@ -89,8 +91,7 @@ fn load_sample_parts(
|
||||
)
|
||||
})?;
|
||||
objects = cir
|
||||
.objects
|
||||
.iter()
|
||||
.validated_objects()
|
||||
.map(|item| (item.rsync_uri.clone(), hex::encode(&item.sha256)))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
object_hashes = objects
|
||||
@@ -98,8 +99,7 @@ fn load_sample_parts(
|
||||
.map(|(uri, hash)| object_hash_key(uri, hash))
|
||||
.collect::<BTreeSet<_>>();
|
||||
rejects = cir
|
||||
.rejected_objects
|
||||
.iter()
|
||||
.rejected_objects()
|
||||
.map(|item| item.object_uri.clone())
|
||||
.collect::<BTreeSet<_>>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user