diff --git a/Cargo.lock b/Cargo.lock index be3c8eb..1874af3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,6 +461,9 @@ dependencies = [ "cave", "futures", "http", + "metrics", + "metrics-exporter-prometheus", + "metrics-util", "redis", "reqwest", "serde", diff --git a/sieve/Cargo.toml b/sieve/Cargo.toml index ba4ad6b..d7c92da 100644 --- a/sieve/Cargo.toml +++ b/sieve/Cargo.toml @@ -16,3 +16,6 @@ redis = { version = "0.23", features = ["tokio-comp", "connection-manager"] } reqwest = { version = "0.11" } http = "*" sigh = "*" +metrics = "0.20" +metrics-util = "0.14" +metrics-exporter-prometheus = "0.11" diff --git a/sieve/config.yaml b/sieve/config.yaml index 0e8efba..801d2bc 100644 --- a/sieve/config.yaml +++ b/sieve/config.yaml @@ -2,3 +2,4 @@ redis: "redis://fedi.buzz:6379/" redis_password_file: "redis_password.txt" in_topic: "relay-in" priv_key_file: private-key.pem +prometheus_port: 9102 diff --git a/sieve/src/config.rs b/sieve/src/config.rs index 157641b..5caa25e 100644 --- a/sieve/src/config.rs +++ b/sieve/src/config.rs @@ -8,6 +8,7 @@ pub struct Config { pub redis_password_file: String, pub in_topic: String, priv_key_file: String, + pub prometheus_port: u16, } impl Config { diff --git a/sieve/src/main.rs b/sieve/src/main.rs index 5c09246..8a4829e 100644 --- a/sieve/src/main.rs +++ b/sieve/src/main.rs @@ -13,6 +13,8 @@ use cave::{ config::LoadConfig, feed, }; +use metrics_util::MetricKindMask; +use metrics_exporter_prometheus::PrometheusBuilder; mod config; @@ -41,6 +43,14 @@ async fn main() { cave::init::init_logger(5557); let config = config::Config::load(); + + PrometheusBuilder::new() + .with_http_listener(([0; 8], config.prometheus_port)) + .add_global_label("application", env!("CARGO_PKG_NAME")) + .idle_timeout(MetricKindMask::ALL, Some(Duration::from_secs(600))) + .install() + .unwrap(); + let priv_key = Arc::new(config.priv_key()); let relay_in = connect_relay_in(config.redis_url(), &config.in_topic) .await @@ -71,6 +81,7 @@ async fn main() { relay_in.for_each(|action| async { // Filter by action type if ! allowed_action_types.contains(&action.action_type) { + metrics::counter!("sieve_activity", 1, "type" => "type_ignored"); return; } @@ -100,10 +111,13 @@ async fn main() { // fetch info for id tracing::debug!("GET {id}"); match authorized_fetch(&client, id, KEY_ID, &priv_key).await { - Ok(res) => - res, + Ok(res) => { + metrics::counter!("sieve_activity", 1, "type" => "fetch_object_ok"); + res + } Err(e) => { tracing::error!("{id} HTTP: {e:?}"); + metrics::counter!("sieve_activity", 1, "type" => "fetch_object_error"); return; } } @@ -117,21 +131,26 @@ async fn main() { post, Err(e) => { tracing::error!("JSON of {id}: {e:?}"); + metrics::counter!("sieve_activity", 1, "type" => "json_error"); return; } }; let author: activitypub::Actor = if let Some(author_url) = &post.attributed_to { match authorized_fetch(&client, author_url, KEY_ID, &priv_key).await { - Ok(author) => - author, + Ok(author) => { + metrics::counter!("sieve_activity", 1, "type" => "fetch_author_ok"); + author + } Err(e) => { tracing::error!("{author_url} HTTP: {e:?}"); + metrics::counter!("sieve_activity", 1, "type" => "fetch_author_error"); return; } } } else { tracing::error!("No attributedTo in {id}"); + metrics::counter!("sieve_activity", 1, "type" => "no_author"); return; }; // Translate ActivityPub post to Mastodon client API post format @@ -146,16 +165,23 @@ async fn main() { post } else { tracing::error!("Cannot serialize post {id}"); + metrics::counter!("sieve_activity", 1, "type" => "serialize_error"); return; }; match store.save_post(encodable_post).await { - Ok(true) => - tracing::info!("Post was new: {id}"), - Ok(false) => - tracing::info!("Post was already known: {id}"), - Err(e) => - tracing::error!("Error forwarding post {id}: {e:?}"), + Ok(true) => { + tracing::info!("Post was new: {id}"); + metrics::counter!("sieve_activity", 1, "type" => "post_new"); + } + Ok(false) => { + tracing::info!("Post was already known: {id}"); + metrics::counter!("sieve_activity", 1, "type" => "post_known"); + } + Err(e) => { + tracing::error!("Error forwarding post {id}: {e:?}"); + metrics::counter!("sieve_activity", 1, "type" => "post_error"); + } } }); }).await;