From ae26faa0450ea040cdf3fd8bf6491d1b8a4eb948 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Fri, 5 Dec 2025 00:46:09 -0700 Subject: [PATCH] separate signal-gateway binary from the library, and its deps --- Cargo.lock | 3 ++ Cargo.toml | 5 ++- signal-gateway/Cargo.toml | 20 ++++++++-- signal-gateway/src/{ => bin}/main.rs | 57 ++++++++++++++++++++++------ signal-gateway/src/config.rs | 18 --------- signal-gateway/src/gateway/mod.rs | 14 ++++--- signal-gateway/src/init_logging.rs | 32 ---------------- signal-gateway/src/lib.rs | 8 ++++ 8 files changed, 85 insertions(+), 72 deletions(-) rename signal-gateway/src/{ => bin}/main.rs (73%) delete mode 100644 signal-gateway/src/config.rs delete mode 100644 signal-gateway/src/init_logging.rs create mode 100644 signal-gateway/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 716f284..7794c11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1645,6 +1645,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" name = "signal-gateway" version = "0.1.0" dependencies = [ + "bytes", "chrono", "chrono-tz", "conf", @@ -1652,6 +1653,8 @@ dependencies = [ "displaydoc", "dotenvy", "futures-util", + "http", + "http-body", "http-body-util", "humantime", "hyper", diff --git a/Cargo.toml b/Cargo.toml index 023e59d..9bd6061 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ result_large_err = "allow" prometheus-http-client = { path = "prometheus-http-client", default-features = false } async-trait = "0.1" +bytes = "1" chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] } chrono-tz = "0.10" conf = "0.4" @@ -31,6 +32,8 @@ conf-extra = "0.1" displaydoc = "0.2" dotenvy = "0.15" futures-util = "0.3" +http = "1" +http-body = "1" http-body-util = "0.1" humantime = "2" hyper = { version = "1.7", features = ["server", "http1", "http2"] } @@ -43,7 +46,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" syslog_rfc5424 = "0.10" thiserror = "2" -tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync", "time"] } +tokio = { version = "1", features = ["io-util", "macros", "net", "rt-multi-thread", "signal", "sync", "time"] } tokio-util = { version = "0.7", features = ["codec"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/signal-gateway/Cargo.toml b/signal-gateway/Cargo.toml index 4c151d2..2d6ed86 100644 --- a/signal-gateway/Cargo.toml +++ b/signal-gateway/Cargo.toml @@ -10,20 +10,26 @@ workspace = true default = ["plot"] plot = ["prometheus-http-client/plot", "dep:chrono-tz", "dep:rand", "dep:walkdir"] rustls-tls = ["prometheus-http-client/rustls-tls"] +bin = ["dep:dotenvy", "dep:hyper", "dep:hyper-util", "dep:tracing-subscriber"] + +[[bin]] +name = "signal-gateway" +path = "src/bin/main.rs" +required-features = ["bin"] [dependencies] prometheus-http-client = { workspace = true, default-features = false } +bytes = { workspace = true } chrono = { workspace = true } conf = { workspace = true } conf-extra = { workspace = true } displaydoc = { workspace = true } -dotenvy = { workspace = true } futures-util = { workspace = true } +http = { workspace = true } +http-body = { workspace = true } http-body-util = { workspace = true } humantime = { workspace = true } -hyper = { workspace = true } -hyper-util = { workspace = true } jsonrpsee = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -32,9 +38,15 @@ thiserror = { workspace = true } tokio = { workspace = true } tokio-util = { workspace = true } tracing = { workspace = true } -tracing-subscriber = { workspace = true } url = { workspace = true } +# Optional dependencies for bin feature +dotenvy = { workspace = true, optional = true } +hyper = { workspace = true, optional = true } +hyper-util = { workspace = true, optional = true } +tracing-subscriber = { workspace = true, optional = true } + +# Optional dependencies for plot feature chrono-tz = { workspace = true, optional = true } rand = { workspace = true, optional = true } walkdir = { workspace = true, optional = true } diff --git a/signal-gateway/src/main.rs b/signal-gateway/src/bin/main.rs similarity index 73% rename from signal-gateway/src/main.rs rename to signal-gateway/src/bin/main.rs index 1c55c96..44ff867 100644 --- a/signal-gateway/src/main.rs +++ b/signal-gateway/src/bin/main.rs @@ -2,27 +2,60 @@ use conf::Conf; use hyper::service::service_fn; use hyper_util::rt::TokioIo; use hyper_util::server::conn::auto; -use std::{str::FromStr, sync::Arc, time::Duration}; +use signal_gateway::{Gateway, GatewayConfig}; +use std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration}; use syslog_rfc5424::SyslogMessage; use tokio::net::{TcpListener, UdpSocket}; use tokio_util::sync::CancellationToken; use tracing::{error, info, warn}; +use tracing_subscriber::EnvFilter; -pub mod config; -pub mod gateway; -pub mod http; -mod human_duration; -mod init_logging; -pub mod jsonrpc; -pub mod prometheus; -pub mod transports; +#[derive(Conf, Debug)] +struct Config { + /// If true, just validate config and don't start + #[conf(long)] + dry_run: bool, + /// Socket to listen for HTTP requests (GET /health, POST /alert) + #[conf(long, env, default_value = "0.0.0.0:8000")] + http_listen_addr: SocketAddr, + /// Socket to listen for UDP messages, in syslog RFC 5424 format + #[conf(long, env, default_value = "0.0.0.0:5424")] + udp_listen_addr: SocketAddr, + #[conf(flatten)] + gateway: GatewayConfig, +} -use config::Config; -use gateway::Gateway; +fn init_logging() { + // Build a default tracing subscriber, writing to STDERR + // Uses RUST_LOG env var for filtering, defaults to "info" if not set + tracing_subscriber::fmt() + .with_writer(std::io::stderr) + .with_file(true) + .with_line_number(true) + .with_env_filter( + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), + ) + .init(); + + // load dotenv file + match dotenvy::dotenv() { + Ok(path) => info!("Read dotenv file from: {}", path.display()), + Err(dotenvy::Error::Io(io_error)) => { + if matches!(io_error.kind(), std::io::ErrorKind::NotFound) { + info!("Couldn't find a dotenv file"); + } else { + panic!("Io error when reading dot env file: {io_error}") + } + } + Err(err) => { + panic!("Error reading dotenv file: {err}") + } + } +} #[tokio::main] async fn main() { - init_logging::init_logging(); + init_logging(); let config = Config::parse(); diff --git a/signal-gateway/src/config.rs b/signal-gateway/src/config.rs deleted file mode 100644 index 6d49914..0000000 --- a/signal-gateway/src/config.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::gateway::GatewayConfig; -use conf::Conf; -use std::net::SocketAddr; - -#[derive(Conf, Debug)] -pub struct Config { - /// If true, just validate config and don't start - #[conf(long)] - pub dry_run: bool, - /// Socket to listen for HTTP requests (GET /health, POST /alert) - #[conf(long, env, default_value = "0.0.0.0:8000")] - pub http_listen_addr: SocketAddr, - /// Socket to listen for UDP messages, in syslog RFC 5424 format - #[conf(long, env, default_value = "0.0.0.0:5424")] - pub udp_listen_addr: SocketAddr, - #[conf(flatten)] - pub gateway: GatewayConfig, -} diff --git a/signal-gateway/src/gateway/mod.rs b/signal-gateway/src/gateway/mod.rs index 69aa24f..be4487e 100644 --- a/signal-gateway/src/gateway/mod.rs +++ b/signal-gateway/src/gateway/mod.rs @@ -3,10 +3,12 @@ use crate::{ jsonrpc::{Envelope, RpcClient, RpcClientError, SignalMessage, connect_tcp}, prometheus::{Prometheus, PrometheusConfig}, }; +use bytes::Buf; use conf::{Conf, Subcommands}; use futures_util::FutureExt; +pub use http::{Method, Request, Response, StatusCode}; +use http_body::Body; use http_body_util::BodyExt; -use hyper::{Method, Request, Response, StatusCode, body::Incoming}; use prometheus_http_client::{AlertStatus, ExtractLabels}; //use jsonrpsee::async_client::{Client as JsonRpcClient, Error as JsonRpcError}; use chrono::Utc; @@ -393,10 +395,12 @@ impl Gateway { } // Handler function that processes incoming http requests (push's from alertmanager expected) - pub async fn handle_http_request( - &self, - req: Request, - ) -> Result, String> { + pub async fn handle_http_request(&self, req: Request) -> Result, String> + where + B: Body + Send, + B::Data: Buf + Send, + B::Error: std::fmt::Display, + { info!( "Received http request: {} {} (version: {:?})", req.method(), diff --git a/signal-gateway/src/init_logging.rs b/signal-gateway/src/init_logging.rs deleted file mode 100644 index 42ed221..0000000 --- a/signal-gateway/src/init_logging.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Logging initialization for signal-gateway - -use tracing::info; -use tracing_subscriber::EnvFilter; - -pub fn init_logging() { - // Build a default tracing subscriber, writing to STDERR - // Uses RUST_LOG env var for filtering, defaults to "info" if not set - tracing_subscriber::fmt() - .with_writer(std::io::stderr) - .with_file(true) - .with_line_number(true) - .with_env_filter( - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), - ) - .init(); - - // load dotenv file - match dotenvy::dotenv() { - Ok(path) => info!("Read dotenv file from: {}", path.display()), - Err(dotenvy::Error::Io(io_error)) => { - if matches!(io_error.kind(), std::io::ErrorKind::NotFound) { - info!("Couldn't find a dotenv file"); - } else { - panic!("Io error when reading dot env file: {io_error}") - } - } - Err(err) => { - panic!("Error reading dotenv file: {err}") - } - } -} diff --git a/signal-gateway/src/lib.rs b/signal-gateway/src/lib.rs new file mode 100644 index 0000000..b69c9b9 --- /dev/null +++ b/signal-gateway/src/lib.rs @@ -0,0 +1,8 @@ +pub mod gateway; +pub mod http; +pub mod human_duration; +pub mod jsonrpc; +pub mod prometheus; +pub mod transports; + +pub use gateway::{Gateway, GatewayConfig};