#![cfg(feature = "telemetry")]
use absurder_sql::telemetry::{Metrics, TelemetryConfig};
#[cfg(not(target_arch = "wasm32"))]
use absurder_sql::telemetry::TracerProvider;
#[test]
fn test_telemetry_full_stack_initialization() {
let config = TelemetryConfig::new("test-app".to_string(), "http://localhost:4317".to_string())
.with_prometheus_port(9091)
.with_traces_enabled(true)
.with_metrics_enabled(true);
assert!(config.validate().is_ok());
let metrics = Metrics::with_config(&config).expect("Failed to create metrics");
assert_eq!(metrics.registry().gather().len(), 19);
#[cfg(not(target_arch = "wasm32"))]
{
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
assert!(tracer_provider.is_initialized());
}
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_metrics_and_traces_integration() {
let config = TelemetryConfig::default();
let metrics = Metrics::new().expect("Failed to create metrics");
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
let tracer = tracer_provider.tracer("database");
let mut span = tracer.start_span("execute_query");
metrics.queries_total().inc();
span.add_event("query_started");
metrics.query_duration().observe(42.0);
span.add_event("query_executed");
metrics.cache_hits().inc();
span.add_event("cache_accessed");
span.end();
assert_eq!(metrics.queries_total().get(), 1.0);
assert_eq!(metrics.cache_hits().get(), 1.0);
assert_eq!(metrics.query_duration().get_sample_count(), 1);
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_telemetry_error_handling() {
let config = TelemetryConfig::default();
let metrics = Metrics::new().expect("Failed to create metrics");
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
let tracer = tracer_provider.tracer("database");
let mut span = tracer.start_span("failing_query");
metrics.errors_total().inc();
span.set_status_error("Query failed: table not found");
span.end();
assert_eq!(metrics.errors_total().get(), 1.0);
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_telemetry_multi_operation_scenario() {
let config = TelemetryConfig::default();
let metrics = Metrics::new().expect("Failed to create metrics");
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
let tracer = tracer_provider.tracer("database");
let mut span1 = tracer.start_span("query_users");
metrics.queries_total().inc();
metrics.cache_hits().inc();
metrics.query_duration().observe(15.0);
span1.add_event("cache_hit");
span1.end();
let mut span2 = tracer.start_span("query_posts");
metrics.queries_total().inc();
metrics.cache_misses().inc();
metrics.query_duration().observe(75.0);
metrics.indexeddb_duration().observe(50.0);
span2.add_event("cache_miss");
span2.add_event("indexeddb_read");
span2.end();
let mut span3 = tracer.start_span("query_invalid");
metrics.queries_total().inc();
metrics.errors_total().inc();
span3.set_status_error("Invalid SQL syntax");
span3.end();
assert_eq!(metrics.queries_total().get(), 3.0);
assert_eq!(metrics.cache_hits().get(), 1.0);
assert_eq!(metrics.cache_misses().get(), 1.0);
assert_eq!(metrics.errors_total().get(), 1.0);
assert_eq!(metrics.query_duration().get_sample_count(), 2);
assert_eq!(metrics.indexeddb_duration().get_sample_count(), 1);
let cache_ratio = metrics.cache_hit_ratio();
assert_eq!(cache_ratio, 0.5); }
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_telemetry_nested_operations() {
let config = TelemetryConfig::default();
let metrics = Metrics::new().expect("Failed to create metrics");
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
let tracer = tracer_provider.tracer("database");
let parent_span = tracer.start_span("transaction");
metrics.queries_total().inc();
let mut child_span1 = tracer.start_span("insert_user").with_parent(&parent_span);
metrics.indexeddb_duration().observe(25.0);
child_span1.add_event("data_inserted");
child_span1.end();
let mut child_span2 = tracer.start_span("update_index").with_parent(&parent_span);
metrics.indexeddb_duration().observe(15.0);
child_span2.add_event("index_updated");
child_span2.end();
let mut sync_span = tracer
.start_span("sync_to_storage")
.with_parent(&parent_span);
metrics.sync_duration().observe(100.0);
sync_span.add_event("sync_started");
sync_span.add_event("sync_completed");
sync_span.end();
assert_eq!(metrics.queries_total().get(), 1.0);
assert_eq!(metrics.indexeddb_duration().get_sample_count(), 2);
assert_eq!(metrics.sync_duration().get_sample_count(), 1);
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_telemetry_traces_disabled() {
let config = TelemetryConfig::default().with_traces_enabled(false);
let metrics = Metrics::new().expect("Failed to create metrics");
let tracer_provider =
TracerProvider::new(&config).expect("Should succeed even with traces disabled");
metrics.queries_total().inc();
assert_eq!(metrics.queries_total().get(), 1.0);
let tracer = tracer_provider.tracer("test");
let span = tracer.start_span("test_op");
assert!(span.is_recording());
}
#[cfg(not(target_arch = "wasm32"))]
#[tokio::test]
async fn test_telemetry_concurrent_operations() {
use std::sync::Arc;
let config = TelemetryConfig::default();
let metrics = Arc::new(Metrics::new().expect("Failed to create metrics"));
let tracer_provider = Arc::new(TracerProvider::new(&config).expect("Failed to create tracer"));
let mut handles = vec![];
for i in 0..10 {
let metrics_clone = Arc::clone(&metrics);
let tracer_provider_clone = Arc::clone(&tracer_provider);
let handle = tokio::spawn(async move {
let tracer = tracer_provider_clone.tracer("worker");
let mut span = tracer.start_span(&format!("task_{}", i));
metrics_clone.queries_total().inc();
metrics_clone.query_duration().observe(10.0 * i as f64);
span.add_event("work_done");
span.end();
});
handles.push(handle);
}
for handle in handles {
handle.await.expect("Task failed");
}
assert_eq!(metrics.queries_total().get(), 10.0);
assert_eq!(metrics.query_duration().get_sample_count(), 10);
}
#[test]
fn test_telemetry_gauge_tracking() {
let metrics = Metrics::new().expect("Failed to create metrics");
metrics.active_connections().inc();
metrics.active_connections().inc();
assert_eq!(metrics.active_connections().get(), 2.0);
metrics.active_connections().dec();
assert_eq!(metrics.active_connections().get(), 1.0);
metrics.memory_bytes().set(1024.0 * 1024.0 * 50.0); assert_eq!(metrics.memory_bytes().get(), 50.0 * 1024.0 * 1024.0);
metrics.storage_bytes().set(1024.0 * 1024.0 * 1024.0 * 2.0); assert_eq!(
metrics.storage_bytes().get(),
2.0 * 1024.0 * 1024.0 * 1024.0
);
}
#[test]
fn test_telemetry_prometheus_export() {
let metrics = Metrics::new().expect("Failed to create metrics");
metrics.queries_total().inc();
metrics.queries_total().inc();
metrics.errors_total().inc();
metrics.cache_hits().inc();
metrics.cache_misses().inc();
metrics.query_duration().observe(10.0);
metrics.query_duration().observe(20.0);
metrics.active_connections().set(5.0);
let metric_families = metrics.registry().gather();
assert!(!metric_families.is_empty());
assert_eq!(metric_families.len(), 19);
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn test_telemetry_cleanup() {
let config = TelemetryConfig::default();
let tracer_provider = TracerProvider::new(&config).expect("Failed to create tracer");
let tracer = tracer_provider.tracer("test");
let mut span = tracer.start_span("test_operation");
span.end();
assert!(tracer_provider.shutdown().is_ok());
}