A3S Lane
Observability
Metrics collection, latency histograms, and configurable alerts
Observability
A3S Lane provides built-in metrics collection and alerting for production monitoring. Track command throughput, latency percentiles, queue depth, and set threshold-based alerts.
Metrics
Enable Metrics
use a3s_lane::QueueMetrics;
let manager = QueueManagerBuilder::new(emitter)
.with_default_lanes()
.with_metrics(QueueMetrics::local())
.build()
.await?;QueueMetrics::local() uses an in-memory backend. For production, implement a custom MetricsBackend (e.g., Prometheus, Datadog).
Reading Metrics
let metrics = manager.metrics().unwrap();
let snapshot = metrics.snapshot().await;
// Counters
println!("Submitted: {:?}", snapshot.counters.get("lane.commands.submitted"));
println!("Completed: {:?}", snapshot.counters.get("lane.commands.completed"));
println!("Failed: {:?}", snapshot.counters.get("lane.commands.failed"));
// Gauges
println!("Queue depth: {:?}", snapshot.gauges.get("lane.queue.depth.query"));
println!("Active: {:?}", snapshot.gauges.get("lane.queue.active.query"));
// Histograms
if let Some(latency) = snapshot.histograms.get("lane.command.latency_ms.query") {
println!("Latency p50: {}ms", latency.percentiles.p50);
println!("Latency p95: {}ms", latency.percentiles.p95);
println!("Latency p99: {}ms", latency.percentiles.p99);
}Available Metrics
Counters (monotonically increasing):
Prop
Type
Gauges (point-in-time values):
Prop
Type
Histograms (distributions):
Prop
Type
Histogram Percentiles
pub struct HistogramStats {
pub count: u64,
pub sum: f64,
pub min: f64,
pub max: f64,
pub mean: f64,
pub percentiles: HistogramPercentiles,
}
pub struct HistogramPercentiles {
pub p50: f64,
pub p90: f64,
pub p95: f64,
pub p99: f64,
}Custom Metrics Backend
Implement the MetricsBackend trait to push metrics to your monitoring system:
use a3s_lane::MetricsBackend;
#[async_trait]
impl MetricsBackend for PrometheusBackend {
async fn increment_counter(&self, name: &str, value: u64) {
// Push to Prometheus
}
async fn set_gauge(&self, name: &str, value: f64) { /* ... */ }
async fn record_histogram(&self, name: &str, value: f64) { /* ... */ }
async fn get_counter(&self, name: &str) -> Option<u64> { /* ... */ }
async fn get_gauge(&self, name: &str) -> Option<f64> { /* ... */ }
async fn get_histogram_stats(&self, name: &str) -> Option<HistogramStats> { /* ... */ }
async fn reset(&self) { /* ... */ }
async fn snapshot(&self) -> MetricsSnapshot { /* ... */ }
}
let metrics = QueueMetrics::new(Arc::new(PrometheusBackend::new()));Alerts
Enable Alerts
use a3s_lane::AlertManager;
// Queue depth alerts
let alerts = Arc::new(AlertManager::with_queue_depth_alerts(100, 500));
// Latency alerts (in milliseconds)
let alerts = Arc::new(AlertManager::with_latency_alerts(500.0, 2000.0));
let manager = QueueManagerBuilder::new(emitter)
.with_default_lanes()
.with_alerts(alerts)
.build()
.await?;Alert Levels
Prop
Type
Alert Callbacks
Register callbacks to handle alerts (send to Slack, PagerDuty, etc.):
let alerts = Arc::new(AlertManager::with_queue_depth_alerts(100, 500));
alerts.add_callback(|alert| {
println!("[{:?}] Lane '{}': {}",
alert.level, alert.lane_id, alert.message);
}).await;Alert Fields
pub struct Alert {
pub lane_id: String,
pub level: AlertLevel, // Warning | Critical
pub message: String,
pub timestamp: DateTime<Utc>,
}Configure Thresholds at Runtime
use a3s_lane::{QueueDepthAlertConfig, LatencyAlertConfig};
let alerts = manager.alerts().unwrap();
alerts.set_queue_depth_config(QueueDepthAlertConfig {
warning_threshold: 200,
critical_threshold: 1000,
}).await;
alerts.set_latency_config(LatencyAlertConfig {
warning_threshold: 1000.0,
critical_threshold: 5000.0,
}).await;Monitoring
For continuous health monitoring, use QueueMonitor:
use a3s_lane::{QueueMonitor, MonitorConfig};
use std::time::Duration;
let monitor = QueueMonitor::with_config(
manager.queue(),
MonitorConfig {
interval: Duration::from_secs(5),
pending_warning_threshold: 50,
active_warning_threshold: 20,
},
);
// Start background monitoring
monitor.start().await;
// Check stats on demand
let stats = monitor.stats().await;