use crate::error::Result;
use opentelemetry::KeyValue;
use opentelemetry::metrics::{Counter, Histogram, Meter, UpDownCounter};
pub struct VectorMetrics {
pub read_count: Counter<u64>,
pub read_duration: Histogram<f64>,
pub features_read: Counter<u64>,
pub write_count: Counter<u64>,
pub write_duration: Histogram<f64>,
pub features_written: Counter<u64>,
pub buffer_count: Counter<u64>,
pub buffer_duration: Histogram<f64>,
pub intersection_count: Counter<u64>,
pub intersection_duration: Histogram<f64>,
pub union_count: Counter<u64>,
pub union_duration: Histogram<f64>,
pub simplify_count: Counter<u64>,
pub simplify_duration: Histogram<f64>,
pub spatial_index_build_count: Counter<u64>,
pub spatial_index_build_duration: Histogram<f64>,
pub spatial_query_count: Counter<u64>,
pub spatial_query_duration: Histogram<f64>,
pub spatial_join_count: Counter<u64>,
pub spatial_join_duration: Histogram<f64>,
pub reproject_count: Counter<u64>,
pub reproject_duration: Histogram<f64>,
pub transform_count: Counter<u64>,
pub transform_duration: Histogram<f64>,
pub active_layers: UpDownCounter<i64>,
pub feature_count: Histogram<f64>,
pub geometry_complexity: Histogram<f64>,
pub layer_size_bytes: Histogram<f64>,
}
impl VectorMetrics {
pub fn new(meter: Meter) -> Result<Self> {
Ok(Self {
read_count: meter
.u64_counter("oxigdal.vector.read.count")
.with_description("Number of vector read operations")
.build(),
read_duration: meter
.f64_histogram("oxigdal.vector.read.duration")
.with_description("Duration of vector read operations in milliseconds")
.build(),
features_read: meter
.u64_counter("oxigdal.vector.features.read")
.with_description("Number of features read")
.build(),
write_count: meter
.u64_counter("oxigdal.vector.write.count")
.with_description("Number of vector write operations")
.build(),
write_duration: meter
.f64_histogram("oxigdal.vector.write.duration")
.with_description("Duration of vector write operations in milliseconds")
.build(),
features_written: meter
.u64_counter("oxigdal.vector.features.written")
.with_description("Number of features written")
.build(),
buffer_count: meter
.u64_counter("oxigdal.vector.buffer.count")
.with_description("Number of buffer operations")
.build(),
buffer_duration: meter
.f64_histogram("oxigdal.vector.buffer.duration")
.with_description("Duration of buffer operations in milliseconds")
.build(),
intersection_count: meter
.u64_counter("oxigdal.vector.intersection.count")
.with_description("Number of intersection operations")
.build(),
intersection_duration: meter
.f64_histogram("oxigdal.vector.intersection.duration")
.with_description("Duration of intersection operations in milliseconds")
.build(),
union_count: meter
.u64_counter("oxigdal.vector.union.count")
.with_description("Number of union operations")
.build(),
union_duration: meter
.f64_histogram("oxigdal.vector.union.duration")
.with_description("Duration of union operations in milliseconds")
.build(),
simplify_count: meter
.u64_counter("oxigdal.vector.simplify.count")
.with_description("Number of simplify operations")
.build(),
simplify_duration: meter
.f64_histogram("oxigdal.vector.simplify.duration")
.with_description("Duration of simplify operations in milliseconds")
.build(),
spatial_index_build_count: meter
.u64_counter("oxigdal.vector.spatial_index.build.count")
.with_description("Number of spatial index builds")
.build(),
spatial_index_build_duration: meter
.f64_histogram("oxigdal.vector.spatial_index.build.duration")
.with_description("Duration of spatial index build in milliseconds")
.build(),
spatial_query_count: meter
.u64_counter("oxigdal.vector.spatial_query.count")
.with_description("Number of spatial queries")
.build(),
spatial_query_duration: meter
.f64_histogram("oxigdal.vector.spatial_query.duration")
.with_description("Duration of spatial queries in milliseconds")
.build(),
spatial_join_count: meter
.u64_counter("oxigdal.vector.spatial_join.count")
.with_description("Number of spatial joins")
.build(),
spatial_join_duration: meter
.f64_histogram("oxigdal.vector.spatial_join.duration")
.with_description("Duration of spatial joins in milliseconds")
.build(),
reproject_count: meter
.u64_counter("oxigdal.vector.reproject.count")
.with_description("Number of vector reprojection operations")
.build(),
reproject_duration: meter
.f64_histogram("oxigdal.vector.reproject.duration")
.with_description("Duration of vector reprojection in milliseconds")
.build(),
transform_count: meter
.u64_counter("oxigdal.vector.transform.count")
.with_description("Number of vector transform operations")
.build(),
transform_duration: meter
.f64_histogram("oxigdal.vector.transform.duration")
.with_description("Duration of vector transform in milliseconds")
.build(),
active_layers: meter
.i64_up_down_counter("oxigdal.vector.active_layers")
.with_description("Number of active vector layers")
.build(),
feature_count: meter
.f64_histogram("oxigdal.vector.feature_count")
.with_description("Number of features in layer")
.build(),
geometry_complexity: meter
.f64_histogram("oxigdal.vector.geometry.complexity")
.with_description("Geometry complexity (vertex count)")
.build(),
layer_size_bytes: meter
.f64_histogram("oxigdal.vector.layer.size.bytes")
.with_description("Layer size in bytes")
.build(),
})
}
pub fn record_read(&self, duration_ms: f64, features: u64, format: &str, success: bool) {
let attrs = vec![
KeyValue::new("format", format.to_string()),
KeyValue::new("success", success),
];
self.read_count.add(1, &attrs);
self.read_duration.record(duration_ms, &attrs);
if success {
self.features_read.add(features, &attrs);
}
}
pub fn record_write(&self, duration_ms: f64, features: u64, format: &str, success: bool) {
let attrs = vec![
KeyValue::new("format", format.to_string()),
KeyValue::new("success", success),
];
self.write_count.add(1, &attrs);
self.write_duration.record(duration_ms, &attrs);
if success {
self.features_written.add(features, &attrs);
}
}
pub fn record_buffer(&self, duration_ms: f64, distance: f64, success: bool) {
let attrs = vec![
KeyValue::new("distance", distance),
KeyValue::new("success", success),
];
self.buffer_count.add(1, &attrs);
self.buffer_duration.record(duration_ms, &attrs);
}
pub fn record_spatial_query(
&self,
duration_ms: f64,
query_type: &str,
_results: u64,
success: bool,
) {
let attrs = vec![
KeyValue::new("query_type", query_type.to_string()),
KeyValue::new("success", success),
];
self.spatial_query_count.add(1, &attrs);
self.spatial_query_duration.record(duration_ms, &attrs);
}
pub fn record_spatial_join(
&self,
duration_ms: f64,
left_features: u64,
right_features: u64,
result_features: u64,
success: bool,
) {
let attrs = vec![
KeyValue::new("left_features", left_features as i64),
KeyValue::new("right_features", right_features as i64),
KeyValue::new("result_features", result_features as i64),
KeyValue::new("success", success),
];
self.spatial_join_count.add(1, &attrs);
self.spatial_join_duration.record(duration_ms, &attrs);
}
pub fn inc_active_layers(&self) {
self.active_layers.add(1, &[]);
}
pub fn dec_active_layers(&self) {
self.active_layers.add(-1, &[]);
}
pub fn record_feature_count(&self, count: u64, layer_type: &str) {
let attrs = vec![KeyValue::new("layer_type", layer_type.to_string())];
self.feature_count.record(count as f64, &attrs);
}
}
#[cfg(test)]
mod tests {
use super::*;
use opentelemetry::global;
#[test]
fn test_vector_metrics_creation() {
let meter = global::meter("test");
let metrics = VectorMetrics::new(meter);
assert!(metrics.is_ok());
}
}