Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions chutoro-core/src/batch_metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Bounded metrics emitted by the one-shot clustering execution path.
//!
//! This module owns the stable batch metric vocabulary. It accepts only
//! resource values and bounded labels, keeping source names and payload data
//! outside the metrics surface.

use crate::Result;

const RUNS_TOTAL: &str = "chutoro.batch.runs_total";
#[cfg(feature = "cpu")]
const MAX_CONNECTIONS: &str = "chutoro.batch.max_connections";
#[cfg(feature = "cpu")]
const EFFECTIVE_EF_CONSTRUCTION: &str = "chutoro.batch.effective_ef_construction";
#[cfg(feature = "cpu")]
const ESTIMATED_BYTES: &str = "chutoro.batch.estimated_bytes";
#[cfg(feature = "cpu")]
const MEMORY_LIMIT_BYTES: &str = "chutoro.batch.memory_limit_bytes";

/// Records the final outcome of a one-shot batch run.
pub(crate) fn record_outcome<T>(backend: &'static str, result: &Result<T>) {
let (outcome, error_code) = match result {
Ok(_) => ("success", "none"),
Err(error) => ("error", error.code().as_str()),
};

metrics::describe_counter!(
RUNS_TOTAL,
metrics::Unit::Count,
"Total one-shot batch runs by backend, outcome, and stable error code."
);
metrics::counter!(
RUNS_TOTAL,
"backend" => backend,
"outcome" => outcome,
"error_code" => error_code
)
.increment(1);
}

/// Records CPU HNSW and memory observations for a one-shot batch run.
#[cfg(feature = "cpu")]
pub(crate) fn record_cpu_resources(
max_connections: usize,
effective_ef_construction: usize,
estimated_bytes: u64,
memory_limit_bytes: Option<u64>,
) {
metrics::describe_histogram!(
MAX_CONNECTIONS,
metrics::Unit::Count,
"Configured CPU HNSW maximum connections for one-shot batch runs."
);
metrics::describe_histogram!(
EFFECTIVE_EF_CONSTRUCTION,
metrics::Unit::Count,
"Dataset-bounded CPU HNSW construction search width for one-shot batch runs."
);
metrics::describe_histogram!(
ESTIMATED_BYTES,
metrics::Unit::Bytes,
"Estimated peak bytes for one-shot CPU batch runs."
);
metrics::histogram!(MAX_CONNECTIONS, "backend" => "cpu").record(max_connections as f64);
metrics::histogram!(EFFECTIVE_EF_CONSTRUCTION, "backend" => "cpu")
.record(effective_ef_construction as f64);
metrics::histogram!(ESTIMATED_BYTES, "backend" => "cpu").record(estimated_bytes as f64);

if let Some(limit) = memory_limit_bytes {
metrics::describe_histogram!(
MEMORY_LIMIT_BYTES,
metrics::Unit::Bytes,
"Configured memory-limit bytes for one-shot CPU batch runs."
);
metrics::histogram!(MEMORY_LIMIT_BYTES, "backend" => "cpu").record(limit as f64);
}
}
20 changes: 11 additions & 9 deletions chutoro-core/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::sync::Arc;

#[cfg(feature = "cpu")]
use crate::{ClusteringSession, DataSource, HnswParams, SessionConfig, SessionRefreshPolicy};
use crate::{Result, chutoro::Chutoro, error::ChutoroError};
use crate::{Result, chutoro::Chutoro, error::ChutoroError, execution_config::ExecutionConfig};
#[cfg(feature = "cpu")]
use tracing::debug;
use tracing::warn;
Expand Down Expand Up @@ -200,7 +200,7 @@ impl ChutoroBuilder {
#[must_use]
pub fn max_bytes(&self) -> Option<u64> { self.max_bytes }

/// Sets the HNSW parameters used when constructing clustering sessions.
/// Sets the HNSW parameters used by CPU execution and sessions.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
///
/// # Examples
/// ```
Expand All @@ -217,7 +217,7 @@ impl ChutoroBuilder {
self
}

/// Returns the HNSW parameters used for session construction.
/// Returns the HNSW parameters used by CPU execution and sessions.
#[cfg(feature = "cpu")]
#[must_use]
pub fn hnsw_params(&self) -> &HnswParams {
Expand Down Expand Up @@ -266,8 +266,13 @@ impl ChutoroBuilder {
(!cfg!(feature = "gpu")).then_some(GpuRejectionReason::BackendNotCompiled);
self.validate_execution_strategy(gpu_rejection_reason)?;

#[cfg(feature = "cpu")]
let execution_config = ExecutionConfig::new(min_cluster_size, self.hnsw_params);
#[cfg(not(feature = "cpu"))]
let execution_config = ExecutionConfig::new(min_cluster_size);

Ok(Chutoro::new(
min_cluster_size,
execution_config,
self.execution_strategy,
self.max_bytes,
))
Expand Down Expand Up @@ -306,11 +311,8 @@ impl ChutoroBuilder {
) -> Result<ClusteringSession<D>> {
let min_cluster_size = self.validate_min_cluster_size()?;
self.validate_execution_strategy(Some(GpuRejectionReason::SessionsCpuOnly))?;
let config = SessionConfig::new(
min_cluster_size,
self.hnsw_params,
self.session_refresh_policy,
);
let execution_config = ExecutionConfig::new(min_cluster_size, self.hnsw_params);
let config = SessionConfig::new(execution_config, self.session_refresh_policy);
debug!(
min_cluster_size = %config.min_cluster_size(),
"build_session: constructing empty ClusteringSession"
Expand Down
Loading
Loading