diff --git a/crates/tracedecay-query/src/code_search.rs b/crates/tracedecay-query/src/code_search.rs index f5eace558..89fa2a259 100644 --- a/crates/tracedecay-query/src/code_search.rs +++ b/crates/tracedecay-query/src/code_search.rs @@ -208,6 +208,7 @@ impl CodeIndexSearchCoverageV1 { /// Build response coverage from the authenticated exact/lexical/graph /// fallback receipt instead of assuming every admitted lane completed. + #[hotpath::measure(label = "query.code_search.map_fallback_coverage")] pub fn from_fallback_lane_coverage( fallback: &BTreeMap< tracedecay_domain::RetrieverKind, @@ -313,8 +314,12 @@ impl CodeIndexSearchCoverageV1 { reason: CodeIndexSearchUnavailableReasonV1, ) -> std::result::Result { if self.any_servable() { + if self.is_degraded() { + hotpath::gauge!("query.code_search.degraded_total").inc(1u64); + } Ok(self) } else { + hotpath::gauge!("query.code_search.unavailable_total").inc(1u64); Err(reason) } } diff --git a/crates/tracedecay-query/src/retrieval/exact.rs b/crates/tracedecay-query/src/retrieval/exact.rs index 7532946ef..417b3906d 100644 --- a/crates/tracedecay-query/src/retrieval/exact.rs +++ b/crates/tracedecay-query/src/retrieval/exact.rs @@ -240,6 +240,7 @@ impl ExactAdmissionValidator for CentralExactAdmissionAuthorityV1 { } impl ExactAdmissionAuthority for CentralExactAdmissionAuthorityV1 { + #[hotpath::measure(label = "query.lane.exact.parse_literals")] fn parse_literals( &self, query_view: &EphemeralSanitizedQueryViewV1, @@ -617,6 +618,7 @@ where /// admission authority, then rebuild the committed deterministic prefix: /// canonical order, sequential ordinals, deterministic fixed-point /// scores, typed coverage, budget cutoff, and a checkpoint digest. + #[hotpath::measure(label = "query.lane.exact.enforce_batch")] fn enforce_batch( &self, request: &ExactLaneRequest<'_>, @@ -660,20 +662,23 @@ where .map_err(contract_error)?; // Only the central authority may mint a proof; re-admission // binds this lane to proofs it can never construct itself. - let minted = self - .authority - .admit( - evidence.admission_proof.field, - &evidence.admission_proof.original_bytes, - &request.base, - ) - .map_err(contract_error)? - .ok_or_else(|| { - RetrievalPortError::Contract( - "the central exact admission authority rejected the proof literal" - .to_owned(), + let minted = crate::hotpath_metrics::measure_frequent( + "query.lane.exact.readmit_row", + || { + self.authority.admit( + evidence.admission_proof.field, + &evidence.admission_proof.original_bytes, + &request.base, ) - })?; + }, + ) + .map_err(contract_error)? + .ok_or_else(|| { + RetrievalPortError::Contract( + "the central exact admission authority rejected the proof literal" + .to_owned(), + ) + })?; if minted != evidence.admission_proof { return Err(RetrievalPortError::Contract( "exact admission proof was not minted by the central authority" diff --git a/crates/tracedecay-query/src/retrieval/fusion.rs b/crates/tracedecay-query/src/retrieval/fusion.rs index 9bb29b3c9..54feaf7e4 100644 --- a/crates/tracedecay-query/src/retrieval/fusion.rs +++ b/crates/tracedecay-query/src/retrieval/fusion.rs @@ -374,6 +374,7 @@ impl RetrievalCursorKeyringV1 { keyed_mac(&material.secret, &bytes).map_err(map_cursor_key_error) } + #[hotpath::measure(label = "query.stream.verify_cursor")] pub(crate) fn verify_cursor(&self, cursor: &RetrievalCursor) -> Result<(), RetrievalError> { let material = self .key_material(&cursor.key_id, cursor.key_epoch) @@ -474,6 +475,7 @@ impl CompositionLaneInput { } } +#[hotpath::measure(label = "query.fusion.compact_lane")] fn compact_batch(batch: RetrieverBatch) -> Result, FusionStageError> { batch.validate()?; Ok(RetrieverBatch { @@ -773,6 +775,7 @@ struct AdmittedLanes { lane_checkpoints: Vec, } +#[hotpath::measure(label = "query.fusion.admit_lanes")] fn admitted_lanes( input: &FusionStageInput, required_lanes: &[RetrieverKind], @@ -1133,6 +1136,7 @@ fn decision_cmp(left: &RankingDecision, right: &RankingDecision) -> Ordering { .then_with(|| left.detail.cmp(&right.detail)) } +#[hotpath::measure(label = "query.fusion.attach_decisions")] fn attach_same_source_decisions( candidates: &mut [FusedCandidate], decisions: &[DedupeDecisionV1], @@ -1185,6 +1189,7 @@ fn attach_same_source_decisions( Ok(()) } +#[hotpath::measure(label = "query.stream.digest_set")] pub fn digest_candidate_set( candidates: &[RankedCandidate], ) -> Result { @@ -1194,6 +1199,7 @@ pub fn digest_candidate_set( } #[allow(clippy::too_many_arguments)] +#[hotpath::measure(label = "query.stream.build_cursor")] fn build_cursor( request: &RetrievalRequest, output: &CompositionOutputV1, diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/builder.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/builder.rs index f055838d2..730b7ff1b 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/builder.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/builder.rs @@ -3070,6 +3070,7 @@ fn sqlite_file_size(connection: &Connection) -> Result Result<(), CodeLexicalArtifactErrorV1> { connection .execute_batch( @@ -4107,6 +4108,7 @@ fn finish_section( /// counting/replaying every staged page on each bounded finalization wake. /// The final section receipts validate the full source-page cardinality before /// a sealed artifact is published. +#[hotpath::measure(label = "query.artifact.finalization.source_chain_verify")] fn verify_staged_source_chain( connection: &Connection, source: &VerifiedSealedLexicalSourceReceiptV1, diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/format.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/format.rs index 61cdf6269..dbf68feeb 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/format.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/format.rs @@ -227,6 +227,7 @@ pub(super) fn initial_base_section_receipt_fold() Ok((row_counts, accumulators)) } +#[hotpath::measure(label = "query.artifact.finalization.receipt_absorb")] pub(super) fn absorb_page_base_sections_receipt( page_ordinal: u64, bytes: &[u8], @@ -321,6 +322,7 @@ fn validate_page_base_sections( Ok(()) } +#[hotpath::measure(label = "query.artifact.index_verify")] pub(super) fn verify_required_artifact_indexes( connection: &Connection, ) -> Result<(), CodeLexicalArtifactErrorV1> { @@ -541,6 +543,7 @@ pub(super) fn verify_artifact_table_layout( Ok(()) } +#[hotpath::measure(label = "query.artifact.ngram.page_digest")] pub(super) fn ngram_page_digest<'a>( page_ordinal: u64, rows: impl IntoIterator, @@ -574,6 +577,14 @@ pub(super) fn ngram_page_digest<'a>( pub(super) fn encode_ngram_bitmap( bitmap: &RoaringBitmap, +) -> Result, CodeLexicalArtifactErrorV1> { + crate::hotpath_metrics::measure_frequent("query.artifact.ngram.encode_shard", || { + encode_ngram_bitmap_inner(bitmap) + }) +} + +fn encode_ngram_bitmap_inner( + bitmap: &RoaringBitmap, ) -> Result, CodeLexicalArtifactErrorV1> { let cardinality = bitmap.len(); let mut range_count = 0u64; @@ -650,6 +661,14 @@ pub(super) fn encode_ngram_bitmap( pub(super) fn decode_ngram_bitmap( encoded: &[u8], +) -> Result { + crate::hotpath_metrics::measure_frequent("query.artifact.ngram.decode_shard", || { + decode_ngram_bitmap_inner(encoded) + }) +} + +fn decode_ngram_bitmap_inner( + encoded: &[u8], ) -> Result { let header = encoded.get(..16).ok_or_else(|| { CodeLexicalArtifactErrorV1::Corrupt( @@ -982,6 +1001,7 @@ pub(super) fn decode_padded_receipt( /// Decode a fixed-size receipt while honoring the caller's canonical work /// control. Reopen paths use this version so a corrupt or cold artifact never /// turns an expired epoch into an unbounded padding scan. +#[hotpath::measure(label = "query.artifact.open.receipt_decode")] pub(super) fn decode_padded_receipt_with_control( bytes: &[u8], control: &dyn CodeIndexExecutionControlV1, diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/postings.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/postings.rs index d07561ea4..906dfb324 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/postings.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/postings.rs @@ -61,6 +61,15 @@ fn reserve_ngram_scratch( pub(super) fn document_ngrams( bytes: &[u8], control: &dyn CodeIndexExecutionControlV1, +) -> Result, CodeLexicalArtifactErrorV1> { + crate::hotpath_metrics::measure_frequent("query.artifact.ngram.project_document", || { + document_ngrams_inner(bytes, control) + }) +} + +fn document_ngrams_inner( + bytes: &[u8], + control: &dyn CodeIndexExecutionControlV1, ) -> Result, CodeLexicalArtifactErrorV1> { let (_, scratch_bytes) = document_ngram_scratch(bytes.len())?; if scratch_bytes > ARTIFACT_DOCUMENT_SCRATCH_LIMIT_BYTES { @@ -103,6 +112,7 @@ pub(super) fn document_ngrams( Ok(ngrams) } +#[hotpath::measure(label = "query.artifact.ngram.project_query")] pub(super) fn query_ngrams(bytes: &[u8]) -> BTreeSet { let width = bytes.len().min(3); if width == 0 { diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/prepared.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/prepared.rs index 3a97e51cb..12fe1ba3b 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/prepared.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/prepared.rs @@ -118,6 +118,7 @@ pub(super) struct PreparedTermPostingV1 { pub(super) frequency: i64, } +#[hotpath::measure(label = "query.artifact.prepare_page")] pub(super) fn prepare_page( metadata: &CodeLexicalProjectionMetadataV1, page: &VerifiedSealedLexicalPageV1, @@ -274,6 +275,7 @@ pub(super) fn prepare_page( Ok(prepared) } +#[hotpath::measure(label = "query.artifact.prepare_receipt")] fn prepare_base_sections_receipt( page_ordinal: u64, imports: &[PreparedImportV1], @@ -362,6 +364,18 @@ fn prepare_document( chunk: &tracedecay_domain::CodeSearchChunkV1, display: Option<&tracedecay_code_index::production::VerifiedSealedLexicalSymbolDisplayV1>, control: &dyn CodeIndexExecutionControlV1, +) -> Result<(PreparedDocumentV1, Vec<(i64, i64)>), CodeLexicalArtifactErrorV1> { + crate::hotpath_metrics::measure_frequent("query.artifact.prepare_document", || { + prepare_document_inner(metadata, document_id, chunk, display, control) + }) +} + +fn prepare_document_inner( + metadata: &CodeLexicalProjectionMetadataV1, + document_id: i64, + chunk: &tracedecay_domain::CodeSearchChunkV1, + display: Option<&tracedecay_code_index::production::VerifiedSealedLexicalSymbolDisplayV1>, + control: &dyn CodeIndexExecutionControlV1, ) -> Result<(PreparedDocumentV1, Vec<(i64, i64)>), CodeLexicalArtifactErrorV1> { u32::try_from(document_id).map_err(|_| { CodeLexicalArtifactErrorV1::Contract( diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/reader.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/reader.rs index de631022f..cf94e8da1 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/reader.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/artifact/reader.rs @@ -1553,6 +1553,7 @@ impl<'a> ArtifactQueryV1<'a> { decode_row(&bytes).map_err(map_query_artifact_error) } + #[hotpath::measure(label = "query.lane.lexical.select_documents")] fn lexical_documents( &self, request: &LexicalLaneRequest<'_>, @@ -1586,6 +1587,7 @@ impl<'a> ArtifactQueryV1<'a> { union_document_queries(sources) } + #[hotpath::measure(label = "query.lane.exact.select_documents")] fn exact_documents( &self, request: &ExactLaneRequest, diff --git a/crates/tracedecay-query/src/retrieval/lexical/projection/postings.rs b/crates/tracedecay-query/src/retrieval/lexical/projection/postings.rs index 877309082..973b53e3b 100644 --- a/crates/tracedecay-query/src/retrieval/lexical/projection/postings.rs +++ b/crates/tracedecay-query/src/retrieval/lexical/projection/postings.rs @@ -85,6 +85,17 @@ impl ByteNgramPostings { document: u32, bytes: &[u8], budget: &mut ByteNgramBudget, + ) -> Result<(), String> { + crate::hotpath_metrics::measure_frequent("query.artifact.ngram.insert_document", || { + self.insert_document_inner(document, bytes, budget) + }) + } + + fn insert_document_inner( + &mut self, + document: u32, + bytes: &[u8], + budget: &mut ByteNgramBudget, ) -> Result<(), String> { let scratch_entries = (1..=bytes.len().min(3)).try_fold(0usize, |entries, width| { entries @@ -241,6 +252,7 @@ impl ByteNgramPostings { Ok(postings) } + #[hotpath::measure(label = "query.artifact.ngram.candidate_documents")] pub(super) fn candidate_documents(&self, needle: &[u8]) -> RoaringBitmap { let width = needle.len().min(3); if width == 0 { @@ -391,6 +403,7 @@ pub(super) struct FuzzySearchSlice { } impl FuzzyTermIndex { + #[hotpath::measure(label = "query.lane.fuzzy.build_index")] pub(super) fn from_terms(terms: I, deadline: Option) -> Result where I: IntoIterator, @@ -414,6 +427,7 @@ impl FuzzyTermIndex { Ok(Self { terms }) } + #[hotpath::measure(label = "query.lane.fuzzy.terms_at_distance")] pub(super) fn terms_at_distance( &self, query: &str, diff --git a/crates/tracedecay-query/src/retrieval/ports.rs b/crates/tracedecay-query/src/retrieval/ports.rs index 7563698ca..37c12753d 100644 --- a/crates/tracedecay-query/src/retrieval/ports.rs +++ b/crates/tracedecay-query/src/retrieval/ports.rs @@ -85,6 +85,7 @@ pub(crate) fn contract_error(error: impl std::fmt::Display) -> RetrievalPortErro /// the payload differs between lanes, so only the payload is a lane's /// business. Cursor bytes are ephemeral; live cursors minted before this /// encoding are rejected as a set mismatch. +#[hotpath::measure(label = "query.lane.checkpoint_digest")] pub(crate) fn checkpoint_digest(payload: &T) -> Result where T: Serialize, @@ -149,6 +150,20 @@ pub(crate) fn lane_bound_evidence<'batch, E>( lane: RetrieverKind, rejections: &LaneEvidenceRejections, ) -> Result<&'batch E, RetrievalPortError> +where + E: LaneBoundEvidence, +{ + crate::hotpath_metrics::measure_frequent("query.lane.bind_evidence", || { + lane_bound_evidence_inner(batch, candidate, lane, rejections) + }) +} + +fn lane_bound_evidence_inner<'batch, E>( + batch: &'batch RetrieverBatch, + candidate: &CompactCandidate, + lane: RetrieverKind, + rejections: &LaneEvidenceRejections, +) -> Result<&'batch E, RetrievalPortError> where E: LaneBoundEvidence, { diff --git a/crates/tracedecay-query/src/retrieval/semantic.rs b/crates/tracedecay-query/src/retrieval/semantic.rs index 4f50099a2..46ff820a5 100644 --- a/crates/tracedecay-query/src/retrieval/semantic.rs +++ b/crates/tracedecay-query/src/retrieval/semantic.rs @@ -483,6 +483,7 @@ where /// are bit-identical to a flat scan's for every returned row. Coverage is /// candidate-bounded and the continuation never claims exhaustion: an /// index-bounded candidate set cannot prove no better row exists. + #[hotpath::measure(label = "query.lane.semantic.ann_rescore")] fn retrieve_ann_exact_rescore( &self, request: &SemanticRetrievalRequestV1<'_>, @@ -571,6 +572,7 @@ where } /// Exact-flat scan: visit and exactly score every published row. + #[hotpath::measure(label = "query.lane.semantic.exact_flat")] fn retrieve_exact_flat( &self, request: &SemanticRetrievalRequestV1<'_>, @@ -696,6 +698,7 @@ where /// full sort followed by truncation), bind evidence, and validate the /// batch. Shared by the exact-flat and ANN-rescore paths; only their /// coverage accounting and exhaustion claims differ. + #[hotpath::measure(label = "query.lane.semantic.assemble")] fn assemble_ranked_batch( &self, request: &SemanticRetrievalRequestV1<'_>, @@ -776,10 +779,12 @@ where self.control, ))); } - let query = match self.embedder.embed_query(SemanticQueryEmbeddingRequestV1 { - query_digest: &request.query_digest, - query_view: request.query_view, - projection: request.projection, + let query = match hotpath::measure_block!("query.lane.semantic.embed_query", { + self.embedder.embed_query(SemanticQueryEmbeddingRequestV1 { + query_digest: &request.query_digest, + query_view: request.query_view, + projection: request.projection, + }) }) { Ok(query) => query, Err(error) => {