Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
295 changes: 230 additions & 65 deletions bottlecap/Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bottlecap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ libdd-trace-utils = { git = "https://github.com/DataDog/libdatadog", rev = "158b
libdd-trace-normalization = { git = "https://github.com/DataDog/libdatadog", rev = "158b59471f1132e3cb36023fa3c46ccb2dd0eda1" }
libdd-trace-obfuscation = { git = "https://github.com/DataDog/libdatadog", rev = "158b59471f1132e3cb36023fa3c46ccb2dd0eda1" }
libdd-trace-stats = { git = "https://github.com/DataDog/libdatadog", rev = "158b59471f1132e3cb36023fa3c46ccb2dd0eda1" }
dogstatsd = { git = "https://github.com/DataDog/serverless-components", rev = "18b49baba8bfef97060d7edd8b830584d0da3373", default-features = false }
datadog-fips = { git = "https://github.com/DataDog/serverless-components", rev = "18b49baba8bfef97060d7edd8b830584d0da3373", default-features = false }
dogstatsd = { git = "https://github.com/DataDog/serverless-components", rev = "2eb009a59ed07ffcaf174db1c31af413365e9bc6", default-features = false }
datadog-fips = { git = "https://github.com/DataDog/serverless-components", rev = "2eb009a59ed07ffcaf174db1c31af413365e9bc6", default-features = false }
libddwaf = { version = "1.28.1", git = "https://github.com/DataDog/libddwaf-rust", rev = "d1534a158d976bd4f747bf9fcc58e0712d2d17fc", default-features = false, features = ["serde"] }

[dev-dependencies]
Expand Down
14 changes: 14 additions & 0 deletions bottlecap/LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ h2,https://github.com/hyperium/h2,MIT,"Carl Lerche <me@carllerche.com>, Sean McA
hashbrown,https://github.com/rust-lang/hashbrown,MIT OR Apache-2.0,Amanieu d'Antras <amanieu@gmail.com>
headers,https://github.com/hyperium/headers,MIT,Sean McArthur <sean@seanmonstar.com>
headers-core,https://github.com/hyperium/headers,MIT,Sean McArthur <sean@seanmonstar.com>
heck,https://github.com/withoutboats/heck,MIT OR Apache-2.0,The heck Authors
hex,https://github.com/KokaKiwi/rust-hex,MIT OR Apache-2.0,KokaKiwi <kokakiwi@kokakiwi.net>
hmac,https://github.com/RustCrypto/MACs,MIT OR Apache-2.0,RustCrypto Developers
http,https://github.com/hyperium/http,MIT OR Apache-2.0,"Alex Crichton <alex@alexcrichton.com>, Carl Lerche <me@carllerche.com>, Sean McArthur <sean@seanmonstar.com>"
Expand All @@ -85,6 +86,7 @@ icu_normalizer_data,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X P
icu_properties,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers
icu_properties_data,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers
icu_provider,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers
id-arena,https://github.com/fitzgen/id-arena,MIT OR Apache-2.0,"Nick Fitzgerald <fitzgen@gmail.com>, Aleksey Kladov <aleksey.kladov@gmail.com>"
idna,https://github.com/servo/rust-url,MIT OR Apache-2.0,The rust-url developers
idna_adapter,https://github.com/hsivonen/idna_adapter,Apache-2.0 OR MIT,The rust-url developers
indexmap,https://github.com/bluss/indexmap,Apache-2.0 OR MIT,The indexmap Authors
Expand All @@ -97,6 +99,7 @@ itoa,https://github.com/dtolnay/itoa,MIT OR Apache-2.0,David Tolnay <dtolnay@gma
jobserver,https://github.com/rust-lang/jobserver-rs,MIT OR Apache-2.0,Alex Crichton <alex@alexcrichton.com>
js-sys,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/js-sys,MIT OR Apache-2.0,The wasm-bindgen Developers
lazy_static,https://github.com/rust-lang-nursery/lazy-static.rs,MIT OR Apache-2.0,Marvin Löbel <loebel.marvin@gmail.com>
leb128fmt,https://github.com/bluk/leb128fmt,MIT OR Apache-2.0,Bryant Luk <code@bryantluk.com>
libc,https://github.com/rust-lang/libc,MIT OR Apache-2.0,The Rust Project Developers
libdd-common,https://github.com/DataDog/libdatadog/tree/main/datadog-common,Apache-2.0,The libdd-common Authors
libdd-ddsketch,https://github.com/DataDog/libdatadog/tree/main/libdd-ddsketch,Apache-2.0,The libdd-ddsketch Authors
Expand Down Expand Up @@ -144,6 +147,7 @@ pin-utils,https://github.com/rust-lang-nursery/pin-utils,MIT OR Apache-2.0,Josef
potential_utf,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers
powerfmt,https://github.com/jhpratt/powerfmt,MIT OR Apache-2.0,Jacob Pratt <jacob@jhpratt.dev>
ppv-lite86,https://github.com/cryptocorrosion/cryptocorrosion,MIT OR Apache-2.0,The CryptoCorrosion Contributors
prettyplease,https://github.com/dtolnay/prettyplease,MIT OR Apache-2.0,David Tolnay <dtolnay@gmail.com>
proc-macro2,https://github.com/dtolnay/proc-macro2,MIT OR Apache-2.0,"David Tolnay <dtolnay@gmail.com>, Alex Crichton <alex@alexcrichton.com>"
proc-macro2-diagnostics,https://github.com/SergioBenitez/proc-macro2-diagnostics,MIT OR Apache-2.0,Sergio Benitez <sb@sergio.bz>
prost,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert <dan@danburkert.com>, Lucio Franco <luciofranco14@gmail.com>, Casper Meijn <casper@meijn.net>, Tokio Contributors <team@tokio.rs>"
Expand Down Expand Up @@ -182,6 +186,7 @@ schannel,https://github.com/steffengy/schannel-rs,MIT,"Steven Fackler <sfackler@
scopeguard,https://github.com/bluss/scopeguard,MIT OR Apache-2.0,bluss
security-framework,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler <sfackler@gmail.com>, Kornel <kornel@geekhood.net>"
security-framework-sys,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler <sfackler@gmail.com>, Kornel <kornel@geekhood.net>"
semver,https://github.com/dtolnay/semver,MIT OR Apache-2.0,David Tolnay <dtolnay@gmail.com>
serde,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar <erick.tryzelaar@gmail.com>, David Tolnay <dtolnay@gmail.com>"
serde-aux,https://github.com/iddm/serde-aux,MIT,Victor Polevoy <maintainer@vpolevoy.com>
serde-value,https://github.com/arcnmx/serde-value,MIT,arcnmx
Expand Down Expand Up @@ -253,11 +258,15 @@ value-bag,https://github.com/sval-rs/value-bag,Apache-2.0 OR MIT,Ashley Mannix <
want,https://github.com/seanmonstar/want,MIT,Sean McArthur <sean@seanmonstar.com>
wasi,https://github.com/bytecodealliance/wasi,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The Cranelift Project Developers
wasip2,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip2 Authors
wasip3,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip3 Authors
wasm-bindgen,https://github.com/wasm-bindgen/wasm-bindgen,MIT OR Apache-2.0,The wasm-bindgen Developers
wasm-bindgen-futures,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/futures,MIT OR Apache-2.0,The wasm-bindgen Developers
wasm-bindgen-macro,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro,MIT OR Apache-2.0,The wasm-bindgen Developers
wasm-bindgen-macro-support,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers
wasm-bindgen-shared,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers
wasm-encoder,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-encoder,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Nick Fitzgerald <fitzgen@gmail.com>
wasm-metadata,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-metadata,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasm-metadata Authors
wasmparser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmparser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Yury Delendik <ydelendik@mozilla.com>
web-sys,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/web-sys,MIT OR Apache-2.0,The wasm-bindgen Developers
web-time,https://github.com/daxpedda/web-time,MIT OR Apache-2.0,The web-time Authors
webpki-roots,https://github.com/rustls/webpki-roots,CDLA-Permissive-2.0,The webpki-roots Authors
Expand All @@ -283,6 +292,11 @@ windows_x86_64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0
windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft
windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_x86_64_msvc Authors
wit-bindgen,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
wit-bindgen-core,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
wit-bindgen-rust,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
wit-bindgen-rust-macro,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
wit-component,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Peter Huene <peter@huene.dev>
wit-parser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-parser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton <alex@alexcrichton.com>
writeable,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers
yansi,https://github.com/SergioBenitez/yansi,MIT OR Apache-2.0,Sergio Benitez <sb@sergio.bz>
yoke,https://github.com/unicode-org/icu4x,Unicode-3.0,Manish Goregaokar <manishsmail@gmail.com>
Expand Down
42 changes: 14 additions & 28 deletions bottlecap/src/bin/bottlecap/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,8 @@ async fn extension_loop_active(
// Wait for any pending flushes
flushing_service.await_handles().await;
// Final flush to capture any data that accumulated since the last
// spawn_non_blocking(). We pass force_stats=true since this is our
// last opportunity to send data before shutdown.
let mut locked_metrics = flushing_service.metrics_flushers().lock().await;
flushing_service.flush_blocking(true, &mut locked_metrics).await;
// spawn_non_blocking(). This is our last opportunity to send data.
flushing_service.flush_blocking_final().await;
break;
}
}
Expand Down Expand Up @@ -635,19 +633,13 @@ async fn extension_loop_active(
}
}
_ = race_flush_interval.tick() => {
let mut locked_metrics = metrics_flushers.lock().await;
flushing_service
.flush_blocking(false, &mut locked_metrics)
.await;
flushing_service.flush_blocking().await;
race_flush_interval.reset();
}
}
}
// flush
let mut locked_metrics = metrics_flushers.lock().await;
flushing_service
.flush_blocking(false, &mut locked_metrics)
.await;
flushing_service.flush_blocking().await;
race_flush_interval.reset();
let next_response =
extension::next_event(client, &aws_config.runtime_api, &r.extension_id).await;
Expand All @@ -664,10 +656,7 @@ async fn extension_loop_active(
}
}
FlushDecision::Periodic => {
let mut locked_metrics = metrics_flushers.lock().await;
flushing_service
.flush_blocking(false, &mut locked_metrics)
.await;
flushing_service.flush_blocking().await;
race_flush_interval.reset();
}
_ => {
Expand Down Expand Up @@ -695,10 +684,7 @@ async fn extension_loop_active(
}
_ = race_flush_interval.tick() => {
if flush_control.flush_strategy == FlushStrategy::Default {
let mut locked_metrics = metrics_flushers.lock().await;
flushing_service
.flush_blocking(false, &mut locked_metrics)
.await;
flushing_service.flush_blocking().await;
race_flush_interval.reset();
}
}
Expand Down Expand Up @@ -744,11 +730,8 @@ async fn extension_loop_active(
&lifecycle_listener_shutdown_token,
);

// Final flush with force_stats=true since this is our last opportunity
let mut locked_metrics = metrics_flushers.lock().await;
flushing_service
.flush_blocking(true, &mut locked_metrics)
.await;
// Final flush - this is our last opportunity to send data before shutdown
flushing_service.flush_blocking_final().await;

// Even though we're shutting down, we need to reset the flush interval to prevent any future flushes
race_flush_interval.reset();
Expand Down Expand Up @@ -1178,7 +1161,7 @@ async fn start_dogstatsd(
api_key_factory: Arc<ApiKeyFactory>,
config: &Arc<Config>,
) -> (
Arc<TokioMutex<Vec<MetricsFlusher>>>,
Arc<Vec<MetricsFlusher>>,
MetricsAggregatorHandle,
CancellationToken,
) {
Expand All @@ -1200,17 +1183,20 @@ async fn start_dogstatsd(
});

// Get flushers with aggregator handle
let flushers = Arc::new(TokioMutex::new(start_metrics_flushers(
let flushers = Arc::new(start_metrics_flushers(
Arc::clone(&api_key_factory),
&aggregator_handle,
config,
)));
));

// Create Dogstatsd server
let dogstatsd_config = DogStatsDConfig {
host: EXTENSION_HOST.to_string(),
port: DOGSTATSD_PORT,
metric_namespace: config.statsd_metric_namespace.clone(),
so_rcvbuf: config.dogstatsd_so_rcvbuf,
buffer_size: config.dogstatsd_buffer_size,
queue_size: config.dogstatsd_queue_size,
};
let cancel_token = tokio_util::sync::CancellationToken::new();
let dogstatsd_agent = DogStatsD::new(
Expand Down
70 changes: 70 additions & 0 deletions bottlecap/src/config/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,24 @@ pub struct EnvConfig {
#[serde(deserialize_with = "deserialize_optional_string")]
pub statsd_metric_namespace: Option<String>,

/// @env `DD_DOGSTATSD_SO_RCVBUF`
/// Size of the receive buffer for `DogStatsD` UDP packets, in bytes (`SO_RCVBUF`).
/// Increase to reduce packet loss under high-throughput metric bursts.
#[serde(deserialize_with = "deserialize_option_lossless")]
pub dogstatsd_so_rcvbuf: Option<usize>,

/// @env `DD_DOGSTATSD_BUFFER_SIZE`
/// Maximum size of a single read from any transport (UDP or named pipe), in bytes.
/// Defaults to 8192.
#[serde(deserialize_with = "deserialize_option_lossless")]
pub dogstatsd_buffer_size: Option<usize>,

/// @env `DD_DOGSTATSD_QUEUE_SIZE`
/// Internal queue capacity between the socket reader and metric processor.
/// Defaults to 1024. Increase if the processor can't keep up with burst traffic.
#[serde(deserialize_with = "deserialize_option_lossless")]
pub dogstatsd_queue_size: Option<usize>,

// OTLP
//
// - APM / Traces
Expand Down Expand Up @@ -554,6 +572,11 @@ fn merge_config(config: &mut Config, env_config: &EnvConfig) {
config.statsd_metric_namespace = parse_metric_namespace(namespace);
}

// DogStatsD
merge_option!(config, env_config, dogstatsd_so_rcvbuf);
merge_option!(config, env_config, dogstatsd_buffer_size);
merge_option!(config, env_config, dogstatsd_queue_size);

// OTLP
merge_option_to_value!(config, env_config, otlp_config_traces_enabled);
merge_option_to_value!(
Expand Down Expand Up @@ -830,6 +853,11 @@ mod tests {
);
jail.set_env("DD_OTLP_CONFIG_LOGS_ENABLED", "true");

// DogStatsD
jail.set_env("DD_DOGSTATSD_SO_RCVBUF", "1048576");
jail.set_env("DD_DOGSTATSD_BUFFER_SIZE", "65507");
jail.set_env("DD_DOGSTATSD_QUEUE_SIZE", "2048");

// AWS Lambda
jail.set_env(
"DD_API_KEY_SECRET_ARN",
Expand Down Expand Up @@ -984,6 +1012,9 @@ mod tests {
otlp_config_traces_probabilistic_sampler_sampling_percentage: Some(50),
otlp_config_logs_enabled: true,
statsd_metric_namespace: None,
dogstatsd_so_rcvbuf: Some(1048576),
dogstatsd_buffer_size: Some(65507),
dogstatsd_queue_size: Some(2048),
api_key_secret_arn: "arn:aws:secretsmanager:region:account:secret:datadog-api-key"
.to_string(),
kms_api_key: "test-kms-key".to_string(),
Expand Down Expand Up @@ -1170,4 +1201,43 @@ mod tests {
Ok(())
});
}

#[test]
fn test_dogstatsd_config_from_env() {
figment::Jail::expect_with(|jail| {
jail.clear_env();
jail.set_env("DD_DOGSTATSD_SO_RCVBUF", "1048576");
jail.set_env("DD_DOGSTATSD_BUFFER_SIZE", "65507");
jail.set_env("DD_DOGSTATSD_QUEUE_SIZE", "2048");

let mut config = Config::default();
let env_config_source = EnvConfigSource;
env_config_source
.load(&mut config)
.expect("Failed to load config");

assert_eq!(config.dogstatsd_so_rcvbuf, Some(1048576));
assert_eq!(config.dogstatsd_buffer_size, Some(65507));
assert_eq!(config.dogstatsd_queue_size, Some(2048));
Ok(())
});
}

#[test]
fn test_dogstatsd_config_defaults_to_none() {
figment::Jail::expect_with(|jail| {
jail.clear_env();

let mut config = Config::default();
let env_config_source = EnvConfigSource;
env_config_source
.load(&mut config)
.expect("Failed to load config");

assert_eq!(config.dogstatsd_so_rcvbuf, None);
assert_eq!(config.dogstatsd_buffer_size, None);
assert_eq!(config.dogstatsd_queue_size, None);
Ok(())
});
}
}
19 changes: 19 additions & 0 deletions bottlecap/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,17 @@ pub struct Config {
// Metrics
pub metrics_config_compression_level: i32,
pub statsd_metric_namespace: Option<String>,
/// Size of the receive buffer for `DogStatsD` UDP packets, in bytes (`SO_RCVBUF`).
/// Increase to reduce packet loss under high-throughput metric bursts.
/// If None, uses the OS default.
pub dogstatsd_so_rcvbuf: Option<usize>,
/// Maximum size of a single read from any transport (UDP or named pipe), in bytes.
/// Defaults to 8192. For UDP, the client must batch metrics into packets of
/// this size for the increase to take effect.
pub dogstatsd_buffer_size: Option<usize>,
/// Internal queue capacity between the socket reader and metric processor.
/// Defaults to 1024. Increase if the processor can't keep up with burst traffic.
pub dogstatsd_queue_size: Option<usize>,

// OTLP
//
Expand Down Expand Up @@ -421,6 +432,14 @@ impl Default for Config {
metrics_config_compression_level: 3,
statsd_metric_namespace: None,

// DogStatsD
// Defaults to None, which uses the OS default.
dogstatsd_so_rcvbuf: None,
// Defaults to 8192 internally.
dogstatsd_buffer_size: None,
// Defaults to 1024 internally.
dogstatsd_queue_size: None,

// OTLP
otlp_config_traces_enabled: true,
otlp_config_traces_span_name_as_resource_name: false,
Expand Down
Loading
Loading