Skip to content

Commit da04438

Browse files
authored
fix(download): Tune HostDenyList (#1775)
* Increased the failure threshold default value to 60 * Decreased the block time default to 1h * Added the error to download failure and block logs * Short-circuit `register_download_failure` for already blocked hosts
1 parent d30b907 commit da04438

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

crates/symbolicator-service/src/config.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,18 +498,26 @@ pub struct Config {
498498
///
499499
/// Hosts will be put on the deny list if a certain number of downloads
500500
/// fail within this time window.
501+
///
502+
/// Defaults to 60s.
501503
#[serde(with = "humantime_serde")]
502504
pub deny_list_time_window: Duration,
503505

504506
/// The granularity at which download failures are tracked in the host deny list.
507+
///
508+
/// Defaults to 5s.
505509
#[serde(with = "humantime_serde")]
506510
pub deny_list_bucket_size: Duration,
507511

508512
/// The number of failures that must occur in the configured time window for a
509513
/// server to be put on the deny list.
514+
///
515+
/// Defaults to 60.
510516
pub deny_list_threshold: usize,
511517

512518
/// The duration for which a host will remain on the deny list.
519+
///
520+
/// Defaults to 1h.
513521
#[serde(with = "humantime_serde")]
514522
pub deny_list_block_time: Duration,
515523

@@ -616,8 +624,8 @@ impl Default for Config {
616624
deny_list_enabled: true,
617625
deny_list_time_window: Duration::from_secs(60),
618626
deny_list_bucket_size: Duration::from_secs(5),
619-
deny_list_threshold: 20,
620-
deny_list_block_time: Duration::from_secs(24 * 60 * 60),
627+
deny_list_threshold: 60,
628+
deny_list_block_time: Duration::from_secs(60 * 60),
621629
deny_list_never_block_hosts: Vec::new(),
622630
timeouts: DownloadTimeouts::default(),
623631
// This value is tuned according to Symbolicator's observed real-world performance.

crates/symbolicator-service/src/download/mod.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ impl HostDenyList {
135135
block_time: config.deny_list_block_time,
136136
never_block: config.deny_list_never_block_hosts.clone(),
137137
failures: moka::sync::Cache::builder()
138+
// If a host hasn't had download failures for an entire `deny_list_time_window`
139+
// we can remove it from the `failures` cache.
138140
.time_to_idle(config.deny_list_time_window)
139141
.build(),
140142
blocked_hosts: moka::sync::Cache::builder()
@@ -161,12 +163,19 @@ impl HostDenyList {
161163
///
162164
/// If that puts the host over the threshold, it is added
163165
/// to the blocked servers.
164-
fn register_failure(&self, source_name: &str, host: String) {
166+
fn register_failure(&self, source_name: &str, host: String, error: &CacheError) {
165167
let current_ts = SystemTime::now();
166168

169+
// Sanity check: we don't need to count failures for hosts which are currently blocked.
170+
// This can happen if multiple download requests fail around the same time.
171+
if self.is_blocked(&host) {
172+
return;
173+
}
174+
167175
tracing::trace!(
168176
host = %host,
169177
time = %humantime::format_rfc3339(current_ts),
178+
%error,
170179
"Registering download failure"
171180
);
172181

@@ -205,6 +214,7 @@ impl HostDenyList {
205214
tracing::info!(
206215
%host,
207216
block_time = %humantime::format_duration(self.block_time),
217+
%error,
208218
"Blocking host due to too many download failures"
209219
);
210220

@@ -386,7 +396,7 @@ impl DownloadService {
386396
if let Some(ref deny_list) = self.host_deny_list
387397
&& source_can_be_blocked
388398
{
389-
deny_list.register_failure(&source_metric_key, host);
399+
deny_list.register_failure(&source_metric_key, host, e);
390400
}
391401
}
392402

@@ -1211,12 +1221,20 @@ mod tests {
12111221
let deny_list = HostDenyList::from_config(&config);
12121222
let host = String::from("test");
12131223

1214-
deny_list.register_failure("test", host.clone());
1224+
deny_list.register_failure(
1225+
"test",
1226+
host.clone(),
1227+
&CacheError::DownloadError("Test error".to_owned()),
1228+
);
12151229

12161230
// shouldn't be blocked after one failure
12171231
assert!(!deny_list.is_blocked(&host));
12181232

1219-
deny_list.register_failure("test", host.clone());
1233+
deny_list.register_failure(
1234+
"test",
1235+
host.clone(),
1236+
&CacheError::DownloadError("Test error".to_owned()),
1237+
);
12201238

12211239
// should be blocked after two failures
12221240
assert!(deny_list.is_blocked(&host));
@@ -1240,8 +1258,16 @@ mod tests {
12401258
let deny_list = HostDenyList::from_config(&config);
12411259
let host = String::from("test");
12421260

1243-
deny_list.register_failure("test", host.clone());
1244-
deny_list.register_failure("test", host.clone());
1261+
deny_list.register_failure(
1262+
"test",
1263+
host.clone(),
1264+
&CacheError::DownloadError("Test error".to_owned()),
1265+
);
1266+
deny_list.register_failure(
1267+
"test",
1268+
host.clone(),
1269+
&CacheError::DownloadError("Test error".to_owned()),
1270+
);
12451271

12461272
assert!(!deny_list.is_blocked(&host));
12471273
}

0 commit comments

Comments
 (0)