feat(services): wire gRPC metrics Tower layer into all 7 gRPC services

Add GrpcMetricsLayer from common::metrics to every gRPC service's
Server::builder() chain, enabling automatic Prometheus instrumentation
(grpc_server_started_total, grpc_server_handled_total,
grpc_server_handling_seconds) for all RPC handlers.

Services wired:
- trading-service
- api-gateway
- ml-training-service
- backtesting-service
- broker-gateway
- data-acquisition-service
- trading-agent-service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-01 02:30:23 +01:00
parent a958582eaa
commit 980f5d33c1
7 changed files with 28 additions and 4 deletions

View File

@@ -11,6 +11,8 @@ use std::sync::Arc;
use std::time::Duration;
use tracing::{error, info, warn};
use common::metrics::GrpcMetricsLayer;
// Import all needed types from the library
use api_gateway::auth::jwt::JwtConfig;
use api_gateway::auth::{
@@ -496,12 +498,14 @@ async fn main() -> Result<()> {
// Build server with HTTP/2 optimizations
let mut server_builder = if let Some(ref tls) = tls_config {
tonic::transport::Server::builder()
.layer(GrpcMetricsLayer::new("api-gateway"))
.tls_config(tls.to_server_tls_config())?
.max_concurrent_streams(Some(10_000))
.http2_keepalive_interval(Some(Duration::from_secs(30)))
.http2_keepalive_timeout(Some(Duration::from_secs(10)))
} else {
tonic::transport::Server::builder()
.layer(GrpcMetricsLayer::new("api-gateway"))
.max_concurrent_streams(Some(10_000))
.http2_keepalive_interval(Some(Duration::from_secs(30)))
.http2_keepalive_timeout(Some(Duration::from_secs(10)))

View File

@@ -13,6 +13,8 @@ use std::net::SocketAddr;
use tonic::transport::Server;
use tracing::{error, info, warn};
use common::metrics::GrpcMetricsLayer;
mod health;
use backtesting_service::foxhunt;
@@ -173,7 +175,8 @@ async fn main() -> Result<()> {
}
// Start the server with HTTP/2 optimizations
let mut server_builder = Server::builder();
let mut server_builder = Server::builder()
.layer(GrpcMetricsLayer::new("backtesting-service"));
if enable_http2_opts {
server_builder = server_builder

View File

@@ -12,6 +12,8 @@ use tokio::signal;
use tonic::transport::Server;
use tracing::{error, info, warn};
use common::metrics::GrpcMetricsLayer;
// Service configuration
const DEFAULT_GRPC_PORT: u16 = 50056;
const DEFAULT_HEALTH_PORT: u16 = 8086;
@@ -142,6 +144,7 @@ async fn main() -> Result<()> {
// Build gRPC server
let server = Server::builder()
.layer(GrpcMetricsLayer::new("broker-gateway"))
.add_service(health_service)
.add_service(BrokerGatewayServiceServer::new(service))
.serve_with_shutdown(addr, shutdown_signal());

View File

@@ -11,6 +11,8 @@ use std::net::SocketAddr;
use tonic::transport::Server;
use tracing::info;
use common::metrics::GrpcMetricsLayer;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
@@ -99,6 +101,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Start gRPC server with graceful shutdown
Server::builder()
.layer(GrpcMetricsLayer::new("data-acquisition-service"))
.add_service(DataAcquisitionServiceServer::new(service))
.serve_with_shutdown(addr, shutdown_signal())
.await?;

View File

@@ -15,6 +15,8 @@ use clap::{Args, Parser, Subcommand};
use tonic::transport::Server;
use tonic_reflection::server::Builder as ReflectionBuilder;
use tracing::{debug, error, info, warn};
use common::metrics::GrpcMetricsLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
// Import from library instead of duplicating module declarations
@@ -454,7 +456,8 @@ async fn serve(args: ServeArgs) -> Result<()> {
.and_then(|v| v.parse().ok())
.unwrap_or(true);
let mut server_builder = Server::builder();
let mut server_builder = Server::builder()
.layer(GrpcMetricsLayer::new("ml-training-service"));
if enable_http2_opts {
info!("HTTP/2 optimizations enabled:");

View File

@@ -12,6 +12,8 @@ use tokio::sync::Mutex;
use tonic::transport::{Certificate, Identity, Server, ServerTlsConfig};
use tracing::{error, info};
use common::metrics::GrpcMetricsLayer;
use common::DatabasePool;
use config::manager::ConfigManager;
use config::DatabaseConfig;
@@ -93,11 +95,13 @@ async fn main() -> Result<()> {
info!("Starting gRPC server on {}", addr);
// Build server with optional TLS
let mut server_builder = Server::builder();
let mut server_builder = Server::builder()
.layer(GrpcMetricsLayer::new("trading-agent-service"));
if let Some(tls) = tls_config {
info!("🔒 TLS enabled for Trading Agent Service");
server_builder = Server::builder()
.layer(GrpcMetricsLayer::new("trading-agent-service"))
.tls_config(tls)
.context("Failed to apply TLS configuration")?;
} else {

View File

@@ -43,6 +43,8 @@ use trading_service::feedback_loop::{FeedbackLoop, FeedbackLoopConfig};
use trading_service::questdb_metrics::QuestDBMetricsProvider;
use trading_service::state::TradingServiceState;
use common::metrics::GrpcMetricsLayer;
/// Default configuration values
const DEFAULT_GRPC_PORT: u16 = 50052; // Trading Service port (API Gateway uses 50051)
const DEFAULT_HEALTH_PORT: u16 = 8081; // Health check port (separate from API Gateway 8080)
@@ -942,9 +944,11 @@ async fn main() -> Result<()> {
// Apply authentication interceptor to all gRPC services
let mut server_builder = match tls_config {
Some(tls) => Server::builder()
.layer(GrpcMetricsLayer::new("trading-service"))
.tls_config(tls)
.context("Failed to configure TLS")?,
None => Server::builder(),
None => Server::builder()
.layer(GrpcMetricsLayer::new("trading-service")),
};
// Apply HTTP/2 optimizations if enabled