Skip to content

Commit 96920ef

Browse files
author
Thomas Luijken
committed
Allow for multiple dns servers, and use TCP for more reliable connection
1 parent c5dafba commit 96920ef

File tree

2 files changed

+41
-30
lines changed

2 files changed

+41
-30
lines changed

oxybox/src/main.rs

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use config::model::Config;
22
use reqwest::Client;
3-
use std::time::{Duration, SystemTime, UNIX_EPOCH};
3+
use std::{net::IpAddr, time::{Duration, SystemTime, UNIX_EPOCH}};
44

55
use tokio::time::sleep;
66
use tokio_native_tls::TlsConnector as TokioTlsConnector;
7-
use trust_dns_resolver::{config::{NameServerConfigGroup, ResolverConfig, ResolverOpts}, TokioAsyncResolver};
7+
use trust_dns_resolver::{
8+
TokioAsyncResolver,
9+
config::{NameServerConfig, NameServerConfigGroup, Protocol, ResolverConfig, ResolverOpts},
10+
};
811

912
pub mod mimir;
1013
use mimir::{client::send_to_mimir, create_probe_metrics};
@@ -21,46 +24,54 @@ fn to_fixed_width(input: &str, width: usize) -> String {
2124

2225
#[tokio::main]
2326
async fn main() {
24-
let config_file_location = std::env::var("CONFIG_FILE").unwrap_or_else(|_| "config.yml".to_string());
25-
let config_str = std::fs::read_to_string(config_file_location).expect("Failed to read config.yaml");
26-
let dns_host = std::env::var("DNS_HOST").unwrap_or_else(|_| "1.1.1.1".to_string());
27-
let config: Config = serde_yaml::from_str(&config_str).expect("Invalid YAML");
27+
let config_file_location =
28+
std::env::var("CONFIG_FILE").unwrap_or_else(|_| "config.yml".to_string());
29+
let config_str =
30+
std::fs::read_to_string(config_file_location).expect("Failed to read config.yaml");
31+
let dns_hosts = std::env::var("DNS_HOST").unwrap_or_else(|_| "1.1.1.1, 8.8.8.8".to_string());
32+
33+
let dns_host_vec: Vec<&str> = dns_hosts.split(',').map(str::trim).collect();
2834

35+
let config: Config = serde_yaml::from_str(&config_str).expect("Invalid YAML");
2936

3037
let mut builder = native_tls::TlsConnector::builder();
3138
builder.danger_accept_invalid_certs(true);
3239

3340
let tls_connector = builder.build().expect("Failed to build TLS connector");
3441
let tls_connector = TokioTlsConnector::from(tls_connector);
3542
let mut opts = ResolverOpts::default();
36-
opts.attempts = 3; // Retry up to 3 times
37-
opts.timeout = std::time::Duration::from_millis(500); // Fast timeout
38-
39-
let name_servers = NameServerConfigGroup::from_ips_clear(
40-
&[std::net::IpAddr::V4(dns_host.parse().unwrap())],
41-
53,
42-
true,
43-
);
44-
43+
opts.attempts = 2;
44+
opts.timeout = std::time::Duration::from_millis(100);
45+
opts.cache_size = 1024;
46+
47+
let mut name_servers = NameServerConfigGroup::new();
48+
49+
for host in dns_host_vec {
50+
let ip: IpAddr = host.parse().expect("Invalid DNS host");
51+
let config = NameServerConfig {
52+
socket_addr: (ip, 53).into(),
53+
protocol: Protocol::Tcp, // TCP is more reliable then UDP for DNS queries
54+
tls_dns_name: None,
55+
trust_negative_responses: false,
56+
bind_addr: None,
57+
};
58+
name_servers.push(config);
59+
}
4560
let resolver_config = ResolverConfig::from_parts(None, vec![], name_servers);
4661

4762
let resolver = TokioAsyncResolver::tokio(resolver_config, opts);
48-
49-
let max_org_width = config
50-
.keys()
51-
.map(|org| org.len())
52-
.max()
53-
.unwrap_or(10); // fallback to 10 if empty
5463

64+
let max_org_width = config.keys().map(|org| org.len()).max().unwrap_or(10); // fallback to 10 if empty
5565

56-
let mimir_endpoint = std::env::var("MIMIR_ENDPOINT").unwrap_or_else(|_| "http://localhost:9009".to_string());
66+
let mimir_endpoint =
67+
std::env::var("MIMIR_ENDPOINT").unwrap_or_else(|_| "http://localhost:9009".to_string());
5768
println!("Using Mimir endpoint: {}", mimir_endpoint);
5869

5970
for (key, org_config) in config {
6071
let tls_connector = TokioTlsConnector::from(tls_connector.clone());
6172
let resolver = resolver.clone();
6273
let targets = org_config.targets.clone();
63-
let interval = org_config.polling_interval_seconds;
74+
let interval = org_config.polling_interval_seconds;
6475
let mimir_target = mimir_endpoint.clone();
6576

6677
tokio::spawn(async move {
@@ -116,12 +127,9 @@ async fn main() {
116127
}
117128

118129
let metrics = create_probe_metrics(&result, is_accepted);
119-
if let Err(e) = send_to_mimir(
120-
&mimir_target,
121-
Some(&organisation_id),
122-
metrics,
123-
)
124-
.await
130+
if let Err(e) =
131+
send_to_mimir(&mimir_target, Some(&organisation_id), metrics)
132+
.await
125133
{
126134
println!(
127135
"[{tenant_name}] Failed to send metrics for {url}: {e}"

oxybox/src/mimir/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ fn create_time_series(
4545
client::create_time_series(metric_name, &labels, value, None)
4646
}
4747

48-
pub fn create_probe_metrics(probe_result: &crate::ProbeResult, probe_success: bool) -> Vec<prompb::TimeSeries> {
48+
pub fn create_probe_metrics(
49+
probe_result: &crate::ProbeResult,
50+
probe_success: bool,
51+
) -> Vec<prompb::TimeSeries> {
4952
let mut metrics = Vec::new();
5053
let probe_successful = match probe_success {
5154
true => 1.0,

0 commit comments

Comments
 (0)