Skip to content
Merged
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
36 changes: 34 additions & 2 deletions asap-common/dependencies/rs/asap_types/src/capability_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ pub enum StorageBackend {
/// cost-aware dispatcher picks per query (typically warm-tier for low-
/// latency approximate, archive for exact).
DoubleWrite,

/// Prometheus-remote: the metric's data is shipped raw to a
/// Prometheus instance via the native OTLP receiver. Phase ε.2
/// registers a `PrometheusForwardEngine` (HTTP-forwarder to
/// Prometheus's `/api/v1/query`) under this slot so the
/// controller's `RawAtEdgePrometheusArchive` mode can route a
/// metric's queries to Prometheus directly. Mirrors the
/// `GorillaS3Archive` slot's "single backend, no failover"
/// semantics — there is no warm-tier sketch to fall back on for a
/// Prometheus-remote metric.
PrometheusRemote,
}

impl StorageBackend {
Expand All @@ -65,6 +76,7 @@ impl StorageBackend {
StorageBackend::SketchWarmTier => "sketch_warm",
StorageBackend::GorillaS3Archive => "gorilla_archive",
StorageBackend::DoubleWrite => "double_write",
StorageBackend::PrometheusRemote => "prometheus_remote",
}
}
}
Expand Down Expand Up @@ -190,6 +202,16 @@ pub fn compatible_storage_backends(
StorageBackend::GorillaS3Archive,
],
},
// Phase ε.2: Prometheus-remote metrics route only to the
// Prometheus forwarder. There is no warm-tier sketch to fall
// back on (the metric's raw samples never landed in
// ASAP-managed storage), so the failover sequence is the
// single backend itself; a missing engine surfaces as a
// `NoEngineRegistered` 503 from the HTTP handler, which is
// the correct fail-loud behaviour for a misconfigured deploy.
StorageBackend::PrometheusRemote => {
vec![StorageBackend::PrometheusRemote]
}
}
}

Expand Down Expand Up @@ -1192,6 +1214,10 @@ mod tests {
StorageBackend::DoubleWrite.data_source_id(),
"double_write",
);
assert_eq!(
StorageBackend::PrometheusRemote.data_source_id(),
"prometheus_remote",
);
}

/// Source-of-truth agreement check, mirrors
Expand Down Expand Up @@ -1219,6 +1245,7 @@ mod tests {
StorageBackend::SketchWarmTier,
StorageBackend::GorillaS3Archive,
StorageBackend::DoubleWrite,
StorageBackend::PrometheusRemote,
];

for &stat in &stats {
Expand All @@ -1233,9 +1260,11 @@ mod tests {
let last = *backends.last().unwrap();
assert!(
last == StorageBackend::SketchWarmTier
|| last == StorageBackend::GorillaS3Archive,
|| last == StorageBackend::GorillaS3Archive
|| last == StorageBackend::PrometheusRemote,
"backend list for ({stat:?}, {acc:?}, {cfg:?}) must terminate in a \
dispatchable failover (SketchWarmTier or GorillaS3Archive); got {last:?}",
dispatchable failover (SketchWarmTier, GorillaS3Archive, or \
PrometheusRemote); got {last:?}",
);
// The expected head is determined by `(metric_storage_config, accuracy)`:
let expected_head = match (cfg, acc) {
Expand All @@ -1247,6 +1276,9 @@ mod tests {
(StorageBackend::DoubleWrite, AccuracyTarget::Approximate) => {
StorageBackend::SketchWarmTier
}
(StorageBackend::PrometheusRemote, _) => {
StorageBackend::PrometheusRemote
}
};
assert_eq!(
backends[0], expected_head,
Expand Down
28 changes: 28 additions & 0 deletions asap-query-engine/src/bin/precompute_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
}
}

// Phase ε.2: register a `PrometheusForwardEngine` under the
// `prometheus_remote` engine id when
// `ASAP_PROMETHEUS_QUERY_URL` is set. Mirrors the block in
// `src/main.rs` so the `precompute_engine` binary (used by
// the deploy/docker image) matches the full backend's
// behaviour.
match query_engine_rust::engines::prometheus::prometheus_engine_from_env() {
Ok(Some(prom)) => {
use query_engine_rust::routing::QueryEngine;
info!(
upstream = prom.base_url(),
"Phase ε.2: registering PrometheusForwardEngine on the capability router (data_source_id=prometheus_remote)",
);
http_server = http_server
.with_query_engine(Arc::new(prom) as Arc<dyn QueryEngine>);
}
Ok(None) => {
info!(
"ASAP_PROMETHEUS_QUERY_URL not set — PrometheusForwardEngine skipped; routing-table entries referencing `prometheus_remote` will surface NoEngineRegistered",
);
}
Err(e) => {
warn!(
"ASAP_PROMETHEUS_QUERY_URL set but PrometheusForwardEngine failed to build ({e}); router will not have a prometheus_remote engine",
);
}
}

tokio::spawn(async move {
if let Err(e) = http_server.run().await {
tracing::error!("Query server error: {}", e);
Expand Down
8 changes: 7 additions & 1 deletion asap-query-engine/src/engines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@
//!
//! ## Public surface
//!
//! Two engines + the shared error envelope:
//! Three engines + the shared error envelope:
//!
//! * [`simple::SimpleEngine`] — warm-tier sketch query engine.
//! * [`gorilla::GorillaQueryEngine`] — archive-tier exact query
//! engine over the [`gorilla::store::GorillaS3Store`].
//! * [`prometheus::PrometheusForwardEngine`] — HTTP-forwarder to a
//! Prometheus `/api/v1/query` endpoint, registered under the
//! `prometheus_remote` engine id when
//! `ASAP_PROMETHEUS_QUERY_URL` is set (Phase ε.2).
//! * [`EngineError`] — the trait-level error envelope every
//! `crate::routing::QueryEngine` impl returns.

pub mod gorilla;
pub mod logical;
pub mod physical;
pub mod prometheus;
pub mod query_result;
pub mod simple;
pub mod timeline_dispatch;
Expand All @@ -30,6 +35,7 @@ pub mod window_merger;
pub use gorilla::{
EngineError as GorillaEngineError, GorillaEngineConfig, GorillaQueryEngine,
};
pub use prometheus::{PrometheusForwardConfig, PrometheusForwardEngine, PrometheusForwardError};
pub use query_result::{InstantVector, QueryResult, RangeVector, RangeVectorElement, Sample};
pub use simple::SimpleEngine;
pub use timeline_dispatch::{combine_statistic, CombinedResult};
Expand Down
Loading