Skip to content

Commit cabad59

Browse files
daniel-nolandmvachhar
authored andcommitted
fix(stats): complete rework
This is a complete rework of the entire stats crate. The prior design was all but fundamentally broken in the thread model used. Note that while rate calculations are now supported in this crate, that feature is deliberately not yet activated. Signed-off-by: Daniel Noland <[email protected]> # Conflicts: # Cargo.toml
1 parent a9cab9b commit cabad59

File tree

24 files changed

+2306
-846
lines changed

24 files changed

+2306
-846
lines changed

Cargo.lock

Lines changed: 50 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ members = [
1818
"pipeline",
1919
"pkt-meta",
2020
"rekon",
21-
"routing", "stats",
21+
"routing",
22+
"stats",
2223
"test-utils",
2324
"vpcmap",
2425
]
@@ -35,7 +36,7 @@ config = { path = "./config", package = "dataplane-config" }
3536
dpdk = { path = "./dpdk", package = "dataplane-dpdk" }
3637
dpdk-sys = { path = "./dpdk-sys", package = "dataplane-dpdk-sys" }
3738
dpdk-sysroot-helper = { path = "./dpdk-sysroot-helper", package = "dataplane-dpdk-sysroot-helper" }
38-
dplane-rpc = { git = "https://github.com/githedgehog/dplane-rpc.git", version = "1.1.2"}
39+
dplane-rpc = { git = "https://github.com/githedgehog/dplane-rpc.git", version = "1.1.2" }
3940
errno = { path = "./errno", package = "dataplane-errno" }
4041
gateway_config = { git = "https://github.com/githedgehog/gateway-proto", tag = "v0.12.0", version = "0.12.0" }
4142
id = { path = "./id", package = "dataplane-id" }
@@ -58,7 +59,7 @@ ahash = { git = "https://github.com/githedgehog/aHash", branch = "pr/daniel-nola
5859
arc-swap = { version = "1.7.1", default-features = false, features = [] }
5960
arrayvec = { version = "0.7.6", default-features = false, features = [] }
6061
async-trait = { version = "0.1.88", default-features = false, features = [] }
61-
axum = { version = "0.8.4", default-features = false, features = ["http1", "json"] }
62+
axum = { version = "0.8.4", default-features = false, features = [] }
6263
axum-server = { version = "0.7.2", default-features = false, features = [] }
6364
bindgen = { version = "0.72.0", default-features = false, features = [] }
6465
bitflags = { version = "2.9.1", default-features = false, features = [] }
@@ -75,9 +76,11 @@ dyn-iter = { version = "1.0.1", default-features = false, features = [] }
7576
etherparse = { version = "0.19.0", default-features = false, features = [] }
7677
fixin = { git = "https://github.com/githedgehog/fixin", branch = "main" }
7778
futures = { version = "0.3.31", default-features = false, features = [] }
79+
hashbrown = { version = "0.15.5", default-features = false, features = [] }
7880
hyper = { version = "1.6.0", default-features = false, features = ["http1", "server"] }
79-
hyper-util = { version = "0.1.16", features = ["tokio"]}
81+
hyper-util = { version = "0.1.16", features = ["tokio"] }
8082
ipnet = { version = "2.11.0", default-features = false, features = [] }
83+
kanal = { version = "0.1.1", default-features = false, features = [] }
8184
left-right = { version = "0.11.5" }
8285
libc = { version = "1.0.0-alpha.1", default-features = false, features = [] }
8386
linux-raw-sys = { version = "0.10.0", default-features = false, features = [] }
@@ -96,13 +99,14 @@ parking_lot = { version = "0.12.4", default-features = false, features = [] }
9699
prefix-trie = { version = "0.8.1", default-features = false, features = [] }
97100
pretty_assertions = { version = "1.4.1", default-features = false, features = ["std"] }
98101
procfs = { version = "0.17.0", default-features = false, features = [] }
99-
rand = { version = "0.9.1", default-features = false, features = ["thread_rng"] }
102+
rand = { version = "0.9.2", default-features = false, features = ["thread_rng"] }
100103
roaring = { version = "0.11.0", default-features = false, features = [] }
101104
rtnetlink = { git = "https://github.com/githedgehog/rtnetlink.git", branch = "hh/tc-actions", default-features = false, features = [] }
102105
rustyline = { version = "17.0.0", default-features = false, features = [] }
103106
serde = { version = "1.0.219", default-features = false, features = [] }
104107
serde_yml = { version = "0.0.12", default-features = false, features = [] }
105108
shuttle = { version = "0.8.1", default-features = false, features = [] }
109+
small-map = { version = "0.1.3", default-features = false, features = [] }
106110
static_assertions = { version = "1.1.0", default-features = false, features = [] }
107111
strum = { version = "0.27.2", features = ["derive"] }
108112
thiserror = { version = "2.0.12", default-features = false, features = [] }

dataplane/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ license = "Apache-2.0"
88
[dependencies]
99
afpacket = { workspace = true }
1010
arrayvec = { workspace = true }
11-
axum = { workspace = true, features = ["http1", "json"] }
11+
axum = { workspace = true, features = ["http1", "tokio"] }
1212
axum-server = { workspace = true }
1313
clap = { workspace = true, features = ["std", "derive", "usage"] }
1414
ctrlc = { workspace = true, features = ["termination"] }
@@ -32,8 +32,8 @@ pkt-meta = { workspace = true }
3232
routing = { workspace = true }
3333
serde = { workspace = true, features = ["derive"] }
3434
serde_yml = { workspace = true }
35-
tokio = { workspace = true }
3635
stats = { workspace = true }
36+
tokio = { workspace = true }
3737
tracing = { workspace = true }
3838
tracing-subscriber = { workspace = true, features = ["default"] }
3939
vpcmap = { workspace = true }

dataplane/src/args.rs

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,10 @@ pub(crate) struct CmdArgs {
7878
#[arg(
7979
long,
8080
value_name = "Metrics Address and Port",
81-
default_value = "127.0.0.1:9090",
82-
help = "Bind address and port for Prometheus metrics HTTP endpoint (e.g., 127.0.0.1:9090, 0.0.0.0:8080)"
81+
default_value_t = SocketAddr::from(([127, 0, 0, 1], 9090)),
82+
help = "Bind address and port for Prometheus metrics HTTP endpoint"
8383
)]
84-
metrics_address: String,
85-
86-
/// Disable Prometheus metrics server
87-
#[arg(long, help = "Disable the Prometheus metrics HTTP endpoint")]
88-
disable_metrics: bool,
84+
metrics_address: SocketAddr,
8985
}
9086

9187
impl CmdArgs {
@@ -190,28 +186,7 @@ impl CmdArgs {
190186
}
191187

192188
/// Get the metrics bind address, returns None if metrics are disabled
193-
pub fn metrics_address(&self) -> Option<Result<SocketAddr, String>> {
194-
if self.disable_metrics {
195-
None
196-
} else {
197-
Some(self.parse_metrics_address())
198-
}
199-
}
200-
201-
/// Parse the metrics address string into a socket address
202-
fn parse_metrics_address(&self) -> Result<SocketAddr, String> {
189+
pub fn metrics_address(&self) -> SocketAddr {
203190
self.metrics_address
204-
.parse::<SocketAddr>()
205-
.map_err(|e| format!("Invalid metrics address '{}': {}", self.metrics_address, e))
206-
}
207-
208-
/// Check if metrics are enabled
209-
pub fn metrics_enabled(&self) -> bool {
210-
!self.disable_metrics
211-
}
212-
213-
/// Get the raw metrics address string
214-
pub fn metrics_address_string(&self) -> &str {
215-
&self.metrics_address
216191
}
217192
}

dataplane/src/main.rs

Lines changed: 16 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,18 @@ mod packet_processor;
1111
mod statistics; // Add statistics module
1212

1313
use crate::args::{CmdArgs, Parser};
14+
use crate::packet_processor::start_router;
15+
use crate::statistics::MetricsServer;
1416
use drivers::dpdk::DriverDpdk;
1517
use drivers::kernel::DriverKernel;
18+
use mgmt::processor::launch::start_mgmt;
1619
use net::buffer::PacketBufferMut;
1720
use net::packet::Packet;
1821
use pipeline::DynPipeline;
1922
use pipeline::sample_nfs::PacketDumper;
20-
#[allow(unused)]
21-
use tracing::{debug, error, info, warn};
22-
use tracing_subscriber::EnvFilter;
23-
24-
use crate::packet_processor::start_router;
25-
use mgmt::processor::launch::start_mgmt;
2623
use routing::RouterParamsBuilder;
27-
28-
// Import statistics functions
29-
use crate::statistics::start_metrics_server;
24+
use tracing::{error, info};
25+
use tracing_subscriber::EnvFilter;
3026

3127
fn init_logging() {
3228
tracing_subscriber::fmt()
@@ -78,6 +74,7 @@ fn main() {
7874

7975
/* router parameters */
8076
let Ok(config) = RouterParamsBuilder::default()
77+
.metrics_addr(args.metrics_address())
8178
.cli_sock_path(args.cli_sock_path())
8279
.cpi_sock_path(args.cpi_sock_path())
8380
.frr_agent_path(args.frr_agent_path())
@@ -89,61 +86,20 @@ fn main() {
8986

9087
// start the router and build a pipeline. `start_router` returns `InternalSetup` object
9188
// that we deconstruct here to feed different components.
92-
// TODO(fredi): reduce the number of args needed to start components by letting
93-
// `start_router` already provide those grouped in the proper types.
94-
let setup = match start_router(config) {
95-
Ok(setup) => setup,
96-
Err(e) => {
97-
error!("Failed to start router: {e}");
98-
panic!("Failed to start router: {e}");
99-
}
100-
};
101-
89+
let setup = start_router(config).expect("failed to start router");
90+
MetricsServer::new(args.metrics_address(), setup.stats);
10291
/* pipeline builder */
10392
let builder = move || setup.pipeline;
10493

105-
/* mgmt: router objects */
106-
let router = setup.router;
107-
let router_ctl = router.get_ctl_tx();
108-
109-
/* mgmt: nat table */
110-
let nattablew = setup.nattable;
111-
let vnitablesw = setup.vnitablesw;
112-
let vpcmapw = setup.vpcmapw;
113-
let statsr = setup.statsr;
114-
11594
/* start management */
116-
if let Err(e) = start_mgmt(grpc_addr, router_ctl, nattablew, vnitablesw, vpcmapw) {
117-
error!("Failed to start gRPC server: {e}");
118-
panic!("Failed to start gRPC server: {e}");
119-
} else {
120-
info!("Management gRPC server started successfully");
121-
}
122-
123-
// Start metrics server early in the process
124-
let _metrics_handle = if let Some(metrics_addr_result) = args.metrics_address() {
125-
match metrics_addr_result {
126-
Ok(metrics_addr) => match start_metrics_server(metrics_addr, statsr.clone()) {
127-
Ok(handle) => {
128-
info!("Metrics server started on http://{metrics_addr}/metrics");
129-
Some(handle)
130-
}
131-
Err(e) => {
132-
error!("Failed to start metrics server: {}", e);
133-
warn!("Continuing without metrics...");
134-
None
135-
}
136-
},
137-
Err(e) => {
138-
error!("Invalid metrics address configuration: {}", e);
139-
warn!("Continuing without metrics...");
140-
None
141-
}
142-
}
143-
} else {
144-
info!("Metrics server disabled");
145-
None
146-
};
95+
start_mgmt(
96+
grpc_addr,
97+
setup.router.get_ctl_tx(),
98+
setup.nattable,
99+
setup.vnitablesw,
100+
setup.vpcmapw,
101+
)
102+
.expect("Failed to start gRPC server");
147103

148104
/* start driver with the provided pipeline builder */
149105
match args.get_driver_name() {

0 commit comments

Comments
 (0)