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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ See the release page for the latest ARNs of the extension layers for each runtim

* `DASH0_DISABLE_TELEMETRY_LOG_COLLECTION` - When set to `true`, disables collecting logs from the [Lambda Telemetry API](https://docs.aws.amazon.com/lambda/latest/dg/telemetry-api.html). Default: `false`.

* `DASH0_DISABLE_TELEMETRY_METRICS` - When set to `true`, disables emission of the supplementary FaaS metrics (`faas.invoke_duration`, `faas.init_duration`, `dash0.faas.billed_duration`, `faas.mem_usage`). Default: `false`.

* `DASH0_DISABLE_TELEMETRY_TRACES` - When set to `true`, disables both auto-instrumentation and any synthetic spans created by the extension (including error-path synthetic traces). Stronger than `DASH0_DISABLE_AUTO_INSTRUMENTATION`, which only disables auto-instrumentation while still emitting synthetic spans. Default: `false`.

* `DASH0_DATASET` - When set, the extension adds a `Dash0-Dataset` header to all OTLP export requests, routing telemetry to the specified dataset in the Dash0 backend.

* `DASH0_XRAY_TRACES_ENABLED` - When set to `true`, the extension preserves the original X-Ray trace context instead of creating supplementary spans. Use this when AWS X-Ray active tracing is enabled on the Lambda function. Default: `false`.
Expand Down
6 changes: 4 additions & 2 deletions opt/java/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ source /opt/shared.sh
setup_otel_env
write_env_vars

# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION is set
if [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; then
# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION
# or DASH0_DISABLE_TELEMETRY_TRACES is set to a truthy value
if { [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; } \
&& { [ -z "$DASH0_DISABLE_TELEMETRY_TRACES" ] || [ "${DASH0_DISABLE_TELEMETRY_TRACES,,}" = "false" ]; }; then

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

Expand Down
6 changes: 4 additions & 2 deletions opt/node/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ source /opt/shared.sh
setup_otel_env
write_env_vars

# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION is set
if [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; then
# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION
# or DASH0_DISABLE_TELEMETRY_TRACES is set to a truthy value
if { [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; } \
&& { [ -z "$DASH0_DISABLE_TELEMETRY_TRACES" ] || [ "${DASH0_DISABLE_TELEMETRY_TRACES,,}" = "false" ]; }; then

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

Expand Down
6 changes: 4 additions & 2 deletions opt/python/wrapper
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ setup_otel_env
write_env_vars


# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION is set
if [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; then
# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION
# or DASH0_DISABLE_TELEMETRY_TRACES is set to a truthy value
if { [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; } \
&& { [ -z "$DASH0_DISABLE_TELEMETRY_TRACES" ] || [ "${DASH0_DISABLE_TELEMETRY_TRACES,,}" = "false" ]; }; then
export LAMBDA_LAYER_PKGS_DIR="/opt/python";
export PYTHONPATH="$LAMBDA_LAYER_PKGS_DIR:$PYTHONPATH";
export PYTHONPATH="$LAMBDA_RUNTIME_DIR:$PYTHONPATH";
Expand Down
2 changes: 2 additions & 0 deletions sls-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ All options are set under `custom.dash0` in your `serverless.yml`.
| `disableAutoInstrumentation` | `boolean` | `false` | `DASH0_DISABLE_AUTO_INSTRUMENTATION` | Disable auto-instrumentation. The extension will still create synthetic spans. |
| `sendOnInvocationEnd` | `boolean` | `true` | `DASH0_SEND_ON_INVOCATION_END` | Send telemetry at the end of the current invocation instead of the beginning of the next. |
| `disableTelemetryLogCollection` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_LOG_COLLECTION` | Disable Lambda Telemetry API log collection. |
| `disableTelemetryMetrics` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_METRICS` | Disable emission of supplementary FaaS metrics. |
| `disableTelemetryTraces` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_TRACES` | Disable both auto-instrumentation and synthetic spans (including error-path traces). |
| `createPayloadLogRecords` | `boolean` | `true` | `DASH0_CREATE_PAYLOAD_LOG_RECORDS` | Create log records for request/response payloads. |
| `requestTimeout` | `number` | `2000` | `DASH0_REQUEST_TIMEOUT` | HTTP request timeout in milliseconds. |
| `xrayTracesEnabled` | `boolean` | `false` | `DASH0_XRAY_TRACES_ENABLED` | Preserve X-Ray trace context. |
Expand Down
2 changes: 2 additions & 0 deletions sls-plugin/src/config-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface Dash0Config {
disableAutoInstrumentation?: boolean | string;
sendOnInvocationEnd?: boolean | string;
disableTelemetryLogCollection?: boolean | string;
disableTelemetryMetrics?: boolean | string;
disableTelemetryTraces?: boolean | string;
createPayloadLogRecords?: boolean | string;
requestTimeout?: number;
xrayTracesEnabled?: boolean | string;
Expand Down
2 changes: 2 additions & 0 deletions sls-plugin/src/env-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const OPTIONAL_MAPPINGS: Record<string, string> = {
disableAutoInstrumentation: 'DASH0_DISABLE_AUTO_INSTRUMENTATION',
sendOnInvocationEnd: 'DASH0_SEND_ON_INVOCATION_END',
disableTelemetryLogCollection: 'DASH0_DISABLE_TELEMETRY_LOG_COLLECTION',
disableTelemetryMetrics: 'DASH0_DISABLE_TELEMETRY_METRICS',
disableTelemetryTraces: 'DASH0_DISABLE_TELEMETRY_TRACES',
createPayloadLogRecords: 'DASH0_CREATE_PAYLOAD_LOG_RECORDS',
requestTimeout: 'DASH0_REQUEST_TIMEOUT',
xrayTracesEnabled: 'DASH0_XRAY_TRACES_ENABLED',
Expand Down
92 changes: 91 additions & 1 deletion src/config/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub fn is_auto_instrumented_disabled() -> bool {
return true;
}

if is_telemetry_traces_disabled() {
return true;
}

match std::env::var("DASH0_DISABLE_AUTO_INSTRUMENTATION") {
Ok(val) => matches!(
val.as_str(),
Expand Down Expand Up @@ -88,11 +92,32 @@ pub fn is_telemetry_log_collection_disabled() -> bool {
}
}

pub fn is_telemetry_metrics_disabled() -> bool {
match std::env::var("DASH0_DISABLE_TELEMETRY_METRICS") {
Ok(val) => matches!(
val.as_str(),
"1" | "true" | "TRUE" | "True" | "yes" | "YES" | "Yes" | "y" | "Y"
),
Err(_) => false,
}
}

pub fn is_telemetry_traces_disabled() -> bool {
match std::env::var("DASH0_DISABLE_TELEMETRY_TRACES") {
Ok(val) => matches!(
val.as_str(),
"1" | "true" | "TRUE" | "True" | "yes" | "YES" | "Yes" | "y" | "Y"
),
Err(_) => false,
}
}

#[cfg(test)]
mod tests {
use super::{
is_auto_instrumented_disabled, is_send_on_invocation_end,
is_telemetry_log_collection_disabled, max_event_payload_size,
is_telemetry_log_collection_disabled, is_telemetry_metrics_disabled,
is_telemetry_traces_disabled, max_event_payload_size,
};
use serial_test::serial;

Expand Down Expand Up @@ -198,4 +223,69 @@ mod tests {
}
std::env::remove_var("DASH0_DISABLE_TELEMETRY_LOG_COLLECTION");
}

#[test]
#[serial]
fn telemetry_metrics_enabled_by_default() {
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
assert!(!is_telemetry_metrics_disabled());
}

#[test]
#[serial]
fn telemetry_metrics_disabled_with_truthy_values() {
for val in ["1", "true", "TRUE", "True", "yes", "YES", "Yes", "y", "Y"] {
std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", val);
assert!(is_telemetry_metrics_disabled(), "value {}", val);
}
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
}

#[test]
#[serial]
fn telemetry_metrics_not_disabled_with_falsy_values() {
for val in ["0", "false", "no", "maybe", ""] {
std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", val);
assert!(!is_telemetry_metrics_disabled(), "value {}", val);
}
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
}

#[test]
#[serial]
fn telemetry_traces_enabled_by_default() {
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
assert!(!is_telemetry_traces_disabled());
}

#[test]
#[serial]
fn telemetry_traces_disabled_with_truthy_values() {
for val in ["1", "true", "TRUE", "True", "yes", "YES", "Yes", "y", "Y"] {
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", val);
assert!(is_telemetry_traces_disabled(), "value {}", val);
}
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
}

#[test]
#[serial]
fn telemetry_traces_not_disabled_with_falsy_values() {
for val in ["0", "false", "no", "maybe", ""] {
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", val);
assert!(!is_telemetry_traces_disabled(), "value {}", val);
}
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
}

#[test]
#[serial]
fn telemetry_traces_disabled_implies_auto_instrumentation_disabled() {
std::env::set_var("AWS_LAMBDA_EXEC_WRAPPER", "/opt/lumigo_wrapper");
std::env::remove_var("DASH0_DISABLE_AUTO_INSTRUMENTATION");
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", "true");
assert!(is_auto_instrumented_disabled());
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
std::env::remove_var("AWS_LAMBDA_EXEC_WRAPPER");
}
}
74 changes: 51 additions & 23 deletions src/otlp/metrics_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,22 @@ use opentelemetry_proto::tonic::resource::v1::Resource;
use prost::Message;

const DURATION_BOUNDS: &[f64] = &[
0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0,
10000.0,
0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0,
];

const MEMORY_BOUNDS: &[f64] = &[
0.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1536.0, 2048.0, 3072.0, 4096.0, 8192.0, 10240.0,
0.0,
67_108_864.0,
134_217_728.0,
268_435_456.0,
536_870_912.0,
1_073_741_824.0,
1_610_612_736.0,
2_147_483_648.0,
3_221_225_472.0,
4_294_967_296.0,
8_589_934_592.0,
10_737_418_240.0,
];

fn compute_bucket_counts(value: f64, bounds: &[f64]) -> Vec<u64> {
Expand Down Expand Up @@ -122,8 +132,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
metrics.push(create_histogram_metric(
"faas.invoke_duration",
"Duration of the invocation",
"ms",
data.duration,
"s",
data.duration / 1000.0,
get_metric_attributes(),
start_time_unix_nano,
time_unix_nano,
Expand All @@ -135,8 +145,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
metrics.push(create_histogram_metric(
"faas.init_duration",
"Duration of the cold start initialization",
"ms",
data.init_duration,
"s",
data.init_duration / 1000.0,
get_metric_attributes(),
start_time_unix_nano,
time_unix_nano,
Expand All @@ -148,8 +158,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
metrics.push(create_histogram_metric(
"dash0.faas.billed_duration",
"Billed duration of the invocation",
"ms",
data.billed_duration,
"s",
data.billed_duration / 1000.0,
get_metric_attributes(),
start_time_unix_nano,
time_unix_nano,
Expand All @@ -161,8 +171,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
metrics.push(create_histogram_metric(
"faas.mem_usage",
"Memory used by the invocation",
"MB",
data.memory_usage as f64,
"By",
data.memory_usage as f64 * 1024.0 * 1024.0,
get_metric_attributes(),
start_time_unix_nano,
time_unix_nano,
Expand Down Expand Up @@ -232,6 +242,9 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
}

pub fn create_supplementary_metrics(invocation_id: &str) {
if crate::config::user::is_telemetry_metrics_disabled() {
return;
}
if let Some(metric) = create_metrics(invocation_id) {
store_metric(metric);
}
Expand Down Expand Up @@ -282,21 +295,21 @@ mod tests {

// faas.invoke_duration
let duration_metric = find_metric_by_name(metrics, "faas.invoke_duration").unwrap();
assert_eq!(duration_metric.unit, "ms");
assert_eq!(duration_metric.unit, "s");
if let Some(Data::Histogram(h)) = &duration_metric.data {
assert_eq!(
h.aggregation_temporality,
AggregationTemporality::Delta as i32
);
let dp = &h.data_points[0];
assert_eq!(dp.count, 1);
assert_eq!(dp.sum, Some(200.0));
assert_eq!(dp.min, Some(200.0));
assert_eq!(dp.max, Some(200.0));
assert_eq!(dp.sum, Some(0.2));
assert_eq!(dp.min, Some(0.2));
assert_eq!(dp.max, Some(0.2));
assert_eq!(dp.explicit_bounds, DURATION_BOUNDS.to_vec());
// 200ms <= 250.0, which is bounds[7], so bucket index 7
// 0.2s <= 0.25, which is bounds[6], so bucket index 6
let mut expected_counts = vec![0u64; DURATION_BOUNDS.len() + 1];
expected_counts[7] = 1;
expected_counts[6] = 1;
assert_eq!(dp.bucket_counts, expected_counts);
assert_eq!(dp.start_time_unix_nano, 850_000_000); // (1000 - 150) * 1_000_000
assert_eq!(dp.time_unix_nano, 1_200_000_000); // 1200 * 1_000_000
Expand All @@ -314,27 +327,28 @@ mod tests {

// faas.init_duration
let init_metric = find_metric_by_name(metrics, "faas.init_duration").unwrap();
assert_eq!(init_metric.unit, "ms");
assert_eq!(init_metric.unit, "s");
if let Some(Data::Histogram(h)) = &init_metric.data {
assert_eq!(h.data_points[0].sum, Some(150.0));
assert_eq!(h.data_points[0].sum, Some(0.15));
} else {
panic!("Expected Histogram data for faas.init_duration");
}

// dash0.faas.billed_duration
let billed_metric = find_metric_by_name(metrics, "dash0.faas.billed_duration").unwrap();
assert_eq!(billed_metric.unit, "ms");
assert_eq!(billed_metric.unit, "s");
if let Some(Data::Histogram(h)) = &billed_metric.data {
assert_eq!(h.data_points[0].sum, Some(300.0));
assert_eq!(h.data_points[0].sum, Some(0.3));
} else {
panic!("Expected Histogram data for dash0.faas.billed_duration");
}

// faas.mem_usage
let memory_metric = find_metric_by_name(metrics, "faas.mem_usage").unwrap();
assert_eq!(memory_metric.unit, "MB");
assert_eq!(memory_metric.unit, "By");
if let Some(Data::Histogram(h)) = &memory_metric.data {
assert_eq!(h.data_points[0].sum, Some(128.0));
// 128 MB = 128 * 1024 * 1024 bytes
assert_eq!(h.data_points[0].sum, Some(134_217_728.0));
} else {
panic!("Expected Histogram data for faas.mem_usage");
}
Expand Down Expand Up @@ -396,6 +410,20 @@ mod tests {
}
}

#[test]
#[serial]
fn supplementary_metrics_skipped_when_disabled() {
reset_store();
let invocation_id = "inv-metric-1";
setup_invocation(invocation_id, 150.0);

std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", "true");
create_supplementary_metrics(invocation_id);
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");

assert!(crate::state::invocation_data::take_metrics().is_empty());
}

#[test]
#[serial]
fn skips_all_metrics_when_end_time_is_zero() {
Expand Down
8 changes: 6 additions & 2 deletions src/otlp/span_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ pub fn create_spans(
}

pub fn create_supplementary_spans(invocation_id: &str, store: bool) -> Option<StoredTrace> {
if crate::config::user::is_xray_traces_enabled() {
if crate::config::user::is_xray_traces_enabled()
|| crate::config::user::is_telemetry_traces_disabled()
{
return None;
}
let trace = create_spans(invocation_id, true, false);
Expand All @@ -235,7 +237,9 @@ pub fn create_supplementary_spans(invocation_id: &str, store: bool) -> Option<St
}

pub fn create_overhead_supplementary_span(invocation_id: &str) {
if crate::config::user::is_xray_traces_enabled() {
if crate::config::user::is_xray_traces_enabled()
|| crate::config::user::is_telemetry_traces_disabled()
{
return;
}
if let Some(trace) = create_spans(invocation_id, false, true) {
Expand Down
3 changes: 3 additions & 0 deletions src/otlp/span_mutations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub fn build_synthetic_trace(
return_value: Option<&str>,
existing_traces: &[StoredTrace],
) -> Option<StoredTrace> {
if crate::config::user::is_telemetry_traces_disabled() {
return None;
}
let (trace_id, span_id) = get_trace_span_ids(invocation_id, existing_traces);
let parent_span_id = invocation_entry::get_root_span_id(invocation_id)
.and_then(|id| hex::decode(&id).ok())
Expand Down
Loading