Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding gauge to track total peers connected #80

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

gausnes
Copy link

@gausnes gausnes commented Oct 12, 2021

Adding a new gauge to monitor the number of peers connected to Wireguard. This metric provides low cardinality context to the number of peers connected to the process. Label cardinality becomes notable for DataDog pricing.

@@ -29,7 +29,7 @@ thiserror = "1.0"
hyper = { version = "0.14", features = ["stream"] }
http = "0.2"
tokio = { version = "1.0", features = ["macros", "rt"] }
prometheus_exporter_base = { version = "1.2", features = ["hyper_server"] }
prometheus_exporter_base = { git = "https://github.com/gausnes/prometheus_exporter_base", branch = "ContentType", features = ["hyper_server"] }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: update when MindFlavor/prometheus_exporter_base#25 is merged

@@ -194,7 +201,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
info!("using options: {:?}", options);

let bind = matches.value_of("port").unwrap();
let bind = (&bind).parse::<u16>().expect("port must be a valid number");
let bind = bind.parse::<u16>().expect("port must be a valid number");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed a number of issues the compiler complained about

src/metrics.rs Outdated
.render();
}

pub fn latest_handshake(&mut self, instance: &PrometheusInstance<u128, MissingValue>, latest: u128) {
Copy link
Author

@gausnes gausnes Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm been thinking decoupling these contracts from PrometheusInstance and instead define structs that contain labels. This would:

  • Decrease the amount of code in wireguard.rs
  • Make it easier to adopt a different exporter
    • After working with prom a bit it'd be nice for this to support statsd or dogstats for my usage, the wireguard integration code could be shared

# HELP wireguard_peers_total Total number of peers
# TYPE wireguard_peers_total gauge
wireguard_peers_total{interface=\"Pippo\"} 1
";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like a function could be created to generate the expected output, tried to hold off on what refactoring to make this concise

pub handshake_timeout_seconds: Option<u64>
}

pub struct EndpointMetrics<'a> {
Copy link
Author

@gausnes gausnes Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these classes in an attempt to not add clutter to existing method signatures

)
}

pub(self) fn populate_interface_metrics(
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method containers the core of the previous render_with_names implementation. Tried to create a distinction between the two classifications of metrics.

# HELP wireguard_peers_total Total number of peers
# TYPE wireguard_peers_total gauge
wireguard_peers_total{{interface=\"Pippo\",seen_recently=\"true\"}} 1
wireguard_peers_total{{interface=\"Pippo\",seen_recently=\"false\"}} 1
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on this label name? Feels like there a number of better options than what is initially defined:

  • connected
  • recent_handshake
  • timed_out

and/or have enumerated values e.g.

  • state: TIMED_OUT, RECENT_SEEN

@gausnes gausnes marked this pull request as draft October 12, 2021 21:58
@@ -155,6 +156,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.help("exports peer's remote ip and port as labels (if available)")
.takes_value(false),
)
.arg(
Arg::with_name("handshake_timeout_seconds")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

900 (15 minutes) was the value was the initial value I was going to configure, I can add that as the default if desired

src/wireguard.rs Outdated Show resolved Hide resolved
src/wireguard.rs Outdated Show resolved Hide resolved
src/wireguard.rs Outdated
Comment on lines 294 to 298
let tokens: Vec<&str> = ip_and_subnet.split('/').collect();
debug!("WireGuard::render_with_names tokens == {:?}", tokens);
let addr = tokens[0];
let subnet = tokens[1];
(addr, subnet)
Copy link

@BroderickCarlin BroderickCarlin Oct 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is the potential here for a panic if ip_and_subnet is malformed (as in, splitting on / yields only a single value). You may consider a .map_filter() just to safegaurd against bad data

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did at adding a bit of hardening to the data handling here

Comment on lines +317 to +331
if let Some(pehm) = pehm {
if let Some(ep_friendly_description) = pehm.get(&ep.public_key as &str) {
if let Some(friendly_description) =

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing inherently wrong with this, but another way this could be approached is through a .map() and .flatten() chain such as:

Suggested change
if let Some(pehm) = pehm {
if let Some(ep_friendly_description) = pehm.get(&ep.public_key as &str) {
if let Some(friendly_description) =
pehm
.map(|p| p.get(&ep.public_key as &str))
.flatten()
.map(|ep_friendly_desc| &ep_friendly_desc.friendly_description)
.flatten()
.map(|friendly_desc|
match friendly_description { ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally find the existing implementation is a bit more clear to what is happening, however I can appreciate the horizontal space savings on using .map 🤔

src/wireguard.rs Outdated Show resolved Hide resolved
src/wireguard.rs Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants