fix(app): PrometheusHandle must be Data-wrapped before Fn closure capture
PrometheusHandle was moved into the HttpServer Fn closure but Fn closures require Clone (not FnOnce). Wrap in web::Data before cloning into the closure.
This commit is contained in:
parent
beae9bdea0
commit
4aaee59fa4
@ -1,19 +1,19 @@
|
|||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
use actix_web::cookie::time::Duration;
|
use actix_web::cookie::time::Duration;
|
||||||
use actix_web::middleware::Logger;
|
use actix_web::middleware::Logger;
|
||||||
use actix_web::{App, HttpResponse, HttpServer, cookie::Key, web};
|
use actix_web::{cookie::Key, web, App, HttpResponse, HttpServer};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use db::cache::AppCache;
|
use db::cache::AppCache;
|
||||||
use db::database::AppDatabase;
|
use db::database::AppDatabase;
|
||||||
use sea_orm::ConnectionTrait;
|
|
||||||
use service::AppService;
|
|
||||||
use session::SessionMiddleware;
|
|
||||||
use session::config::{PersistentSession, SessionLifecycle, TtlExtensionPolicy};
|
|
||||||
use session::storage::RedisClusterSessionStore;
|
|
||||||
use observability::{
|
use observability::{
|
||||||
init_tracing_subscriber, install_recorder, prometheus_handler, spawn_http_metrics_poller,
|
init_tracing_subscriber, install_recorder, prometheus_handler, spawn_http_metrics_poller,
|
||||||
MetricsMiddleware, HttpMetrics, TracingSpanMiddleware, HttpSnapshotGuard,
|
HttpMetrics, HttpSnapshotGuard, MetricsMiddleware, TracingSpanMiddleware,
|
||||||
};
|
};
|
||||||
|
use sea_orm::ConnectionTrait;
|
||||||
|
use service::AppService;
|
||||||
|
use session::config::{PersistentSession, SessionLifecycle, TtlExtensionPolicy};
|
||||||
|
use session::storage::RedisClusterSessionStore;
|
||||||
|
use session::SessionMiddleware;
|
||||||
|
|
||||||
mod args;
|
mod args;
|
||||||
|
|
||||||
@ -57,48 +57,40 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let args = ServerArgs::parse();
|
let args = ServerArgs::parse();
|
||||||
let service = AppService::new(cfg.clone()).await?;
|
let service = AppService::new(cfg.clone()).await?;
|
||||||
tracing::info!("AppService initialized");
|
tracing::info!("AppService initialized");
|
||||||
|
|
||||||
// Spawn background task: sync OpenRouter models immediately on startup,
|
|
||||||
// then every 10 minutes.
|
|
||||||
let _model_sync_handle = service.clone().start_sync_task();
|
let _model_sync_handle = service.clone().start_sync_task();
|
||||||
|
|
||||||
// Spawn background task: check workspace billing alerts every 30 minutes.
|
|
||||||
let _billing_alert_handle = service.clone().start_billing_alert_task();
|
let _billing_alert_handle = service.clone().start_billing_alert_task();
|
||||||
|
|
||||||
let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel::<()>(1);
|
let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel::<()>(1);
|
||||||
let worker_service = service.clone();
|
let worker_service = service.clone();
|
||||||
let worker_handle = tokio::spawn(async move {
|
let worker_handle =
|
||||||
worker_service
|
tokio::spawn(async move { worker_service.start_room_workers(shutdown_rx).await });
|
||||||
.start_room_workers(shutdown_rx)
|
|
||||||
.await
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Phase 6: OTLP tracing ──────────────────────────────────────────────
|
|
||||||
let _otel_guard = if cfg.otel_enabled().unwrap_or(false) {
|
let _otel_guard = if cfg.otel_enabled().unwrap_or(false) {
|
||||||
let endpoint = cfg.otel_endpoint().unwrap_or_else(|_| "http://localhost:4317".to_string());
|
let endpoint = cfg
|
||||||
let service_name = cfg.otel_service_name().unwrap_or_else(|_| "app".to_string());
|
.otel_endpoint()
|
||||||
let service_version = cfg.otel_service_version().unwrap_or_else(|_| "0.1.0".to_string());
|
.unwrap_or_else(|_| "http://localhost:4317".to_string());
|
||||||
|
let service_name = cfg
|
||||||
|
.otel_service_name()
|
||||||
|
.unwrap_or_else(|_| "app".to_string());
|
||||||
|
let service_version = cfg
|
||||||
|
.otel_service_version()
|
||||||
|
.unwrap_or_else(|_| "0.1.0".to_string());
|
||||||
tracing::info!(endpoint = %endpoint, service = %service_name, "OTLP tracing enabled");
|
tracing::info!(endpoint = %endpoint, service = %service_name, "OTLP tracing enabled");
|
||||||
let guard = observability::init_otlp(
|
let guard =
|
||||||
&endpoint,
|
observability::init_otlp(&endpoint, &service_name, &service_version, &log_level)
|
||||||
&service_name,
|
.map_err(|e| anyhow::anyhow!("OTLP init failed: {}", e))?;
|
||||||
&service_version,
|
|
||||||
&log_level,
|
|
||||||
)
|
|
||||||
.map_err(|e| anyhow::anyhow!("OTLP init failed: {}", e))?;
|
|
||||||
guard
|
guard
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Phase 6: Prometheus metrics ─────────────────────────────────────────
|
let prometheus_handle = install_recorder();
|
||||||
install_recorder();
|
let prometheus_handle_data = web::Data::new(prometheus_handle);
|
||||||
|
|
||||||
let http_metrics = std::sync::Arc::new(HttpMetrics::new());
|
let http_metrics = std::sync::Arc::new(HttpMetrics::new());
|
||||||
let http_snapshot: HttpSnapshotGuard =
|
let http_snapshot: HttpSnapshotGuard = std::sync::Arc::new(std::sync::RwLock::new(
|
||||||
std::sync::Arc::new(std::sync::RwLock::new(
|
observability::HttpMetricsSnapshot::default(),
|
||||||
observability::HttpMetricsSnapshot::default(),
|
));
|
||||||
));
|
|
||||||
let http_snapshot_for_poller = http_snapshot.clone();
|
let http_snapshot_for_poller = http_snapshot.clone();
|
||||||
spawn_http_metrics_poller(
|
spawn_http_metrics_poller(
|
||||||
http_metrics.clone(),
|
http_metrics.clone(),
|
||||||
@ -147,6 +139,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.app_data(web::Data::new(db.clone()))
|
.app_data(web::Data::new(db.clone()))
|
||||||
.app_data(web::Data::new(cache.clone()))
|
.app_data(web::Data::new(cache.clone()))
|
||||||
.app_data(http_snapshot_data.clone())
|
.app_data(http_snapshot_data.clone())
|
||||||
|
.app_data(prometheus_handle_data.clone())
|
||||||
.route("/health", web::get().to(health_check))
|
.route("/health", web::get().to(health_check))
|
||||||
.route("/metrics", web::get().to(prometheus_handler))
|
.route("/metrics", web::get().to(prometheus_handler))
|
||||||
.configure(api::route::init_routes)
|
.configure(api::route::init_routes)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user