From 45bed71c368fe3c72a182025505d6e1ca49bfdd9 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Wed, 25 Oct 2023 12:54:58 +0200 Subject: [PATCH] Include prometheus in default build, remove build feature (fixes #3558) (#4071) Co-authored-by: Dessalines --- Cargo.lock | 5 +- Cargo.toml | 7 ++- crates/apub/src/protocol/mod.rs | 2 +- crates/utils/src/settings/structs.rs | 8 ++-- src/lib.rs | 13 ++---- src/prometheus_metrics.rs | 68 +++++++++------------------- 6 files changed, 37 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af86b65d6..1d9b2a690 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,8 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "activitypub_federation" -version = "0.5.0-beta.3" -source = "git+https://github.com/LemmyNet/activitypub-federation-rust.git?branch=webfinger-alphabets#071218396b2b1254e12ad061362befe0f17e76c9" +version = "0.5.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a122cf2c2adf45b164134946bc069659cd93083fab294839a3f1d794b707c17" dependencies = [ "activitystreams-kinds", "actix-web", diff --git a/Cargo.toml b/Cargo.toml index 0a01644e7..ec3be45f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,6 @@ console = [ "reqwest-tracing/opentelemetry_0_16", ] json-log = ["tracing-subscriber/json"] -prometheus-metrics = ["prometheus", "actix-web-prom"] default = [] [workspace] @@ -70,7 +69,7 @@ lemmy_routes = { version = "=0.19.0-rc.3", path = "./crates/routes" } lemmy_db_views = { version = "=0.19.0-rc.3", path = "./crates/db_views" } lemmy_db_views_actor = { version = "=0.19.0-rc.3", path = "./crates/db_views_actor" } lemmy_db_views_moderator = { version = "=0.19.0-rc.3", path = "./crates/db_views_moderator" } -activitypub_federation = { git = "https://github.com/LemmyNet/activitypub-federation-rust.git", branch = "webfinger-alphabets", default-features = false, features = [ +activitypub_federation = { version = "0.5.0-beta.4", default-features = false, features = [ "actix-web", ] } diesel = "2.1.3" @@ -169,8 +168,8 @@ futures-util = { workspace = true } tokio-postgres = { workspace = true } tokio-postgres-rustls = { workspace = true } chrono = { workspace = true } -prometheus = { version = "0.13.3", features = ["process"], optional = true } -actix-web-prom = { version = "0.6.0", optional = true } +prometheus = { version = "0.13.3", features = ["process"] } +actix-web-prom = { version = "0.6.0" } serial_test = { workspace = true } clap = { version = "4.4.7", features = ["derive"] } actix-web-httpauth = "0.8.1" diff --git a/crates/apub/src/protocol/mod.rs b/crates/apub/src/protocol/mod.rs index dba21f99d..bcf949f02 100644 --- a/crates/apub/src/protocol/mod.rs +++ b/crates/apub/src/protocol/mod.rs @@ -74,7 +74,7 @@ impl IdOrNestedObject { pub(crate) async fn object(self, context: &Data) -> Result { match self { // TODO: move IdOrNestedObject struct to library and make fetch_object_http private - IdOrNestedObject::Id(i) => Ok(fetch_object_http(&i, context).await?), + IdOrNestedObject::Id(i) => Ok(fetch_object_http(&i, context).await?.object), IdOrNestedObject::NestedObject(o) => Ok(o), } } diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index aa3f852ce..c7d0cd3e6 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -170,11 +170,11 @@ pub struct SetupConfig { #[serde(deny_unknown_fields)] pub struct PrometheusConfig { // Address that the Prometheus metrics will be served on. - #[default(Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))))] + #[default(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))] #[doku(example = "127.0.0.1")] - pub bind: Option, + pub bind: IpAddr, // Port that the Prometheus metrics will be served on. - #[default(Some(10002))] + #[default(10002)] #[doku(example = "10002")] - pub port: Option, + pub port: i32, } diff --git a/src/lib.rs b/src/lib.rs index 64bfa802d..774857b95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ pub mod api_routes_http; pub mod code_migrations; -#[cfg(feature = "prometheus-metrics")] pub mod prometheus_metrics; pub mod root_span_builder; pub mod scheduled_tasks; @@ -52,6 +51,7 @@ use lemmy_utils::{ response::jsonify_plain_text_errors, settings::{structs::Settings, SETTINGS}, }; +use prometheus_metrics::serve_prometheus; use reqwest_middleware::{ClientBuilder, ClientWithMiddleware}; use reqwest_tracing::TracingMiddleware; use serde_json::json; @@ -63,12 +63,6 @@ use tracing_error::ErrorLayer; use tracing_log::LogTracer; use tracing_subscriber::{filter::Targets, layer::SubscriberExt, Layer, Registry}; use url::Url; -#[cfg(feature = "prometheus-metrics")] -use { - actix_web_prom::PrometheusMetricsBuilder, - prometheus::default_registry, - prometheus_metrics::serve_prometheus, -}; #[derive(Parser, Debug)] #[command( @@ -173,8 +167,9 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { let _scheduled_tasks = tokio::task::spawn(scheduled_tasks::setup(context.clone())); } - #[cfg(feature = "prometheus-metrics")] - serve_prometheus(SETTINGS.prometheus.as_ref(), context.clone()); + if let Some(prometheus) = SETTINGS.prometheus.clone() { + serve_prometheus(prometheus, context.clone())?; + } let federation_config = FederationConfig::builder() .domain(SETTINGS.hostname.clone()) diff --git a/src/prometheus_metrics.rs b/src/prometheus_metrics.rs index ad964263b..c4ab204e7 100644 --- a/src/prometheus_metrics.rs +++ b/src/prometheus_metrics.rs @@ -1,14 +1,9 @@ -// TODO: should really not unwrap everywhere here.... -#![allow(clippy::unwrap_used)] -use actix_web::{rt::System, web, App, HttpResponse, HttpServer, Responder}; +use actix_web::{rt::System, web, App, HttpServer}; use lemmy_api_common::context::LemmyContext; -use lemmy_utils::settings::structs::PrometheusConfig; +use lemmy_utils::{error::LemmyResult, settings::structs::PrometheusConfig}; use prometheus::{default_registry, Encoder, Gauge, Opts, TextEncoder}; -use std::{ - net::{IpAddr, Ipv4Addr}, - sync::Arc, - thread, -}; +use std::{sync::Arc, thread}; +use tracing::error; struct PromContext { lemmy: LemmyContext, @@ -21,23 +16,12 @@ struct DbPoolMetrics { available: Gauge, } -static DEFAULT_BIND: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); -static DEFAULT_PORT: i32 = 10002; - -pub fn serve_prometheus(config: Option<&PrometheusConfig>, lemmy_context: LemmyContext) { +pub fn serve_prometheus(config: PrometheusConfig, lemmy_context: LemmyContext) -> LemmyResult<()> { let context = Arc::new(PromContext { lemmy: lemmy_context, - db_pool_metrics: create_db_pool_metrics(), + db_pool_metrics: create_db_pool_metrics()?, }); - let (bind, port) = match config { - Some(config) => ( - config.bind.unwrap_or(DEFAULT_BIND), - config.port.unwrap_or(DEFAULT_PORT), - ), - None => (DEFAULT_BIND, DEFAULT_PORT), - }; - // spawn thread that blocks on handling requests // only mapping /metrics to a handler thread::spawn(move || { @@ -48,19 +32,20 @@ pub fn serve_prometheus(config: Option<&PrometheusConfig>, lemmy_context: LemmyC .app_data(web::Data::new(Arc::clone(&context))) .route("/metrics", web::get().to(metrics)) }) - .bind((bind, port as u16)) - .unwrap_or_else(|_| panic!("Cannot bind to {}:{}", bind, port)) + .bind((config.bind, config.port as u16)) + .unwrap_or_else(|e| panic!("Cannot bind to {}:{}: {e}", config.bind, config.port)) .run(); if let Err(err) = server.await { - eprintln!("Prometheus server error: {}", err); + error!("Prometheus server error: {err}"); } }) }); + Ok(()) } // handler for the /metrics path -async fn metrics(context: web::Data>) -> impl Responder { +async fn metrics(context: web::Data>) -> LemmyResult { // collect metrics collect_db_pool_metrics(&context).await; @@ -69,43 +54,34 @@ async fn metrics(context: web::Data>) -> impl Responder { // gather metrics from registry and encode in prometheus format let metric_families = prometheus::gather(); - encoder.encode(&metric_families, &mut buffer).unwrap(); - let output = String::from_utf8(buffer).unwrap(); + encoder.encode(&metric_families, &mut buffer)?; + let output = String::from_utf8(buffer)?; - HttpResponse::Ok().body(output) + Ok(output) } // create lemmy_db_pool_* metrics and register them with the default registry -fn create_db_pool_metrics() -> DbPoolMetrics { +fn create_db_pool_metrics() -> LemmyResult { let metrics = DbPoolMetrics { max_size: Gauge::with_opts(Opts::new( "lemmy_db_pool_max_connections", "Maximum number of connections in the pool", - )) - .unwrap(), + ))?, size: Gauge::with_opts(Opts::new( "lemmy_db_pool_connections", "Current number of connections in the pool", - )) - .unwrap(), + ))?, available: Gauge::with_opts(Opts::new( "lemmy_db_pool_available_connections", "Number of available connections in the pool", - )) - .unwrap(), + ))?, }; - default_registry() - .register(Box::new(metrics.max_size.clone())) - .unwrap(); - default_registry() - .register(Box::new(metrics.size.clone())) - .unwrap(); - default_registry() - .register(Box::new(metrics.available.clone())) - .unwrap(); + default_registry().register(Box::new(metrics.max_size.clone()))?; + default_registry().register(Box::new(metrics.size.clone()))?; + default_registry().register(Box::new(metrics.available.clone()))?; - metrics + Ok(metrics) } async fn collect_db_pool_metrics(context: &PromContext) {