Skip to content
Draft
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
/.idea
/.worktrees

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ repository = "https://github.com/DataDog/serverless-components"

[profile.release]
opt-level = "z"
lto = true
lto = "fat"
codegen-units = 1
strip = true
strip = "symbols"
panic = "abort"
38 changes: 38 additions & 0 deletions crates/datadog-trace-agent/src/http_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ pub fn verify_request_content_length(
None
}

/// Environment variable set by the Lambda runtime to indicate the initialisation type.
/// Lambda Lite (web function / snap-start mode) sets this to `"native-http"`;
/// standard on-demand invocations set it to `"on-demand"`.
const ENV_LAMBDA_INIT_TYPE: &str = "AWS_LAMBDA_INITIALIZATION_TYPE";

/// Returns true if the current environment is Lambda Lite (web function / snap start mode).
///
/// Determined by checking [`ENV_LAMBDA_INIT_TYPE`]` == "native-http"`. This is used to gate
/// behaviour specific to long-running web server deployments on Lambda Lite.
pub fn is_lambda_lite() -> bool {
is_lambda_lite_from_env(std::env::var(ENV_LAMBDA_INIT_TYPE).ok().as_deref())
}

fn is_lambda_lite_from_env(val: Option<&str>) -> bool {
val == Some("native-http")
}

/// Builds a reqwest client with optional proxy configuration and timeout.
/// Uses rustls TLS by default. FIPS-compliant TLS is available via the fips feature
pub fn build_client(
Expand All @@ -135,8 +152,29 @@ mod tests {
use hyper::StatusCode;
use libdd_common::hyper_migration;

use super::is_lambda_lite_from_env;
use super::verify_request_content_length;

#[test]
fn test_is_lambda_lite_native_http() {
assert!(is_lambda_lite_from_env(Some("native-http")));
}

#[test]
fn test_is_lambda_lite_on_demand() {
assert!(!is_lambda_lite_from_env(Some("on-demand")));
}

#[test]
fn test_is_lambda_lite_empty_string() {
assert!(!is_lambda_lite_from_env(Some("")));
}

#[test]
fn test_is_lambda_lite_unset() {
assert!(!is_lambda_lite_from_env(None));
}

fn create_test_headers_with_content_length(val: &str) -> HeaderMap {
let mut map = HeaderMap::new();
map.insert(header::CONTENT_LENGTH, val.parse().unwrap());
Expand Down
16 changes: 16 additions & 0 deletions crates/datadog-trace-agent/src/mini_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const PROFILING_ENDPOINT_PATH: &str = "/profiling/v1/input";
const TRACER_PAYLOAD_CHANNEL_BUFFER_SIZE: usize = 10;
const STATS_PAYLOAD_CHANNEL_BUFFER_SIZE: usize = 10;
const PROXY_PAYLOAD_CHANNEL_BUFFER_SIZE: usize = 10;
/// Sentinel file written on startup in Lambda Lite mode.
/// dd-trace (Node.js) checks this path via DATADOG_MINI_AGENT_PATH in constants.js
/// to decide whether to switch from LogExporter (stdout) to AgentExporter (HTTP :8126).
const LAMBDA_LITE_SENTINEL_PATH: &str = "/tmp/datadog/mini_agent_ready";

pub struct MiniAgent {
pub config: Arc<config::Config>,
Expand Down Expand Up @@ -147,6 +151,18 @@ impl MiniAgent {
now.elapsed().as_millis()
);

// Write a sentinel file so that Node.js dd-trace detects a running agent and
// switches from LogExporter (stdout) to AgentExporter (HTTP :8126).
// Only written for Lambda Lite; standard Lambda invocations use the Lambda
// Extension path (/opt/extensions/datadog-agent) instead.
// /opt is read-only in Lambda Lite, so we use /tmp/datadog/ (created by the
// serverless-compat JS layer before spawning this binary).
if crate::http_utils::is_lambda_lite() {
if let Err(e) = std::fs::write(LAMBDA_LITE_SENTINEL_PATH, b"") {
debug!("Could not write mini agent sentinel file: {}", e);
}
}

if let Some(pipe_name) = pipe_name_opt {
// Windows named pipe transport
#[cfg(all(windows, feature = "windows-pipes"))]
Expand Down
Loading