Skip to content

Commit 8c8bbfa

Browse files
fix: units for otel metrics in the extension (#59)
1 parent c9d2db6 commit 8c8bbfa

11 files changed

Lines changed: 173 additions & 32 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ See the release page for the latest ARNs of the extension layers for each runtim
6262

6363
* `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`.
6464

65+
* `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`.
66+
67+
* `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`.
68+
6569
* `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.
6670

6771
* `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`.

opt/java/wrapper

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ source /opt/shared.sh
55
setup_otel_env
66
write_env_vars
77

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

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

opt/node/wrapper

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ source /opt/shared.sh
55
setup_otel_env
66
write_env_vars
77

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

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

opt/python/wrapper

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ setup_otel_env
66
write_env_vars
77

88

9-
# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION is set
10-
if [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; then
9+
# enable auto instrumentation unless DASH0_DISABLE_AUTO_INSTRUMENTATION
10+
# or DASH0_DISABLE_TELEMETRY_TRACES is set to a truthy value
11+
if { [ -z "$DASH0_DISABLE_AUTO_INSTRUMENTATION" ] || [ "${DASH0_DISABLE_AUTO_INSTRUMENTATION,,}" = "false" ]; } \
12+
&& { [ -z "$DASH0_DISABLE_TELEMETRY_TRACES" ] || [ "${DASH0_DISABLE_TELEMETRY_TRACES,,}" = "false" ]; }; then
1113
export LAMBDA_LAYER_PKGS_DIR="/opt/python";
1214
export PYTHONPATH="$LAMBDA_LAYER_PKGS_DIR:$PYTHONPATH";
1315
export PYTHONPATH="$LAMBDA_RUNTIME_DIR:$PYTHONPATH";

sls-plugin/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ All options are set under `custom.dash0` in your `serverless.yml`.
7070
| `disableAutoInstrumentation` | `boolean` | `false` | `DASH0_DISABLE_AUTO_INSTRUMENTATION` | Disable auto-instrumentation. The extension will still create synthetic spans. |
7171
| `sendOnInvocationEnd` | `boolean` | `true` | `DASH0_SEND_ON_INVOCATION_END` | Send telemetry at the end of the current invocation instead of the beginning of the next. |
7272
| `disableTelemetryLogCollection` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_LOG_COLLECTION` | Disable Lambda Telemetry API log collection. |
73+
| `disableTelemetryMetrics` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_METRICS` | Disable emission of supplementary FaaS metrics. |
74+
| `disableTelemetryTraces` | `boolean` | `false` | `DASH0_DISABLE_TELEMETRY_TRACES` | Disable both auto-instrumentation and synthetic spans (including error-path traces). |
7375
| `createPayloadLogRecords` | `boolean` | `true` | `DASH0_CREATE_PAYLOAD_LOG_RECORDS` | Create log records for request/response payloads. |
7476
| `requestTimeout` | `number` | `2000` | `DASH0_REQUEST_TIMEOUT` | HTTP request timeout in milliseconds. |
7577
| `xrayTracesEnabled` | `boolean` | `false` | `DASH0_XRAY_TRACES_ENABLED` | Preserve X-Ray trace context. |

sls-plugin/src/config-validator.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export interface Dash0Config {
1111
disableAutoInstrumentation?: boolean | string;
1212
sendOnInvocationEnd?: boolean | string;
1313
disableTelemetryLogCollection?: boolean | string;
14+
disableTelemetryMetrics?: boolean | string;
15+
disableTelemetryTraces?: boolean | string;
1416
createPayloadLogRecords?: boolean | string;
1517
requestTimeout?: number;
1618
xrayTracesEnabled?: boolean | string;

sls-plugin/src/env-injector.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const OPTIONAL_MAPPINGS: Record<string, string> = {
66
disableAutoInstrumentation: 'DASH0_DISABLE_AUTO_INSTRUMENTATION',
77
sendOnInvocationEnd: 'DASH0_SEND_ON_INVOCATION_END',
88
disableTelemetryLogCollection: 'DASH0_DISABLE_TELEMETRY_LOG_COLLECTION',
9+
disableTelemetryMetrics: 'DASH0_DISABLE_TELEMETRY_METRICS',
10+
disableTelemetryTraces: 'DASH0_DISABLE_TELEMETRY_TRACES',
911
createPayloadLogRecords: 'DASH0_CREATE_PAYLOAD_LOG_RECORDS',
1012
requestTimeout: 'DASH0_REQUEST_TIMEOUT',
1113
xrayTracesEnabled: 'DASH0_XRAY_TRACES_ENABLED',

src/config/user.rs

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ pub fn is_auto_instrumented_disabled() -> bool {
1515
return true;
1616
}
1717

18+
if is_telemetry_traces_disabled() {
19+
return true;
20+
}
21+
1822
match std::env::var("DASH0_DISABLE_AUTO_INSTRUMENTATION") {
1923
Ok(val) => matches!(
2024
val.as_str(),
@@ -88,11 +92,32 @@ pub fn is_telemetry_log_collection_disabled() -> bool {
8892
}
8993
}
9094

95+
pub fn is_telemetry_metrics_disabled() -> bool {
96+
match std::env::var("DASH0_DISABLE_TELEMETRY_METRICS") {
97+
Ok(val) => matches!(
98+
val.as_str(),
99+
"1" | "true" | "TRUE" | "True" | "yes" | "YES" | "Yes" | "y" | "Y"
100+
),
101+
Err(_) => false,
102+
}
103+
}
104+
105+
pub fn is_telemetry_traces_disabled() -> bool {
106+
match std::env::var("DASH0_DISABLE_TELEMETRY_TRACES") {
107+
Ok(val) => matches!(
108+
val.as_str(),
109+
"1" | "true" | "TRUE" | "True" | "yes" | "YES" | "Yes" | "y" | "Y"
110+
),
111+
Err(_) => false,
112+
}
113+
}
114+
91115
#[cfg(test)]
92116
mod tests {
93117
use super::{
94118
is_auto_instrumented_disabled, is_send_on_invocation_end,
95-
is_telemetry_log_collection_disabled, max_event_payload_size,
119+
is_telemetry_log_collection_disabled, is_telemetry_metrics_disabled,
120+
is_telemetry_traces_disabled, max_event_payload_size,
96121
};
97122
use serial_test::serial;
98123

@@ -198,4 +223,69 @@ mod tests {
198223
}
199224
std::env::remove_var("DASH0_DISABLE_TELEMETRY_LOG_COLLECTION");
200225
}
226+
227+
#[test]
228+
#[serial]
229+
fn telemetry_metrics_enabled_by_default() {
230+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
231+
assert!(!is_telemetry_metrics_disabled());
232+
}
233+
234+
#[test]
235+
#[serial]
236+
fn telemetry_metrics_disabled_with_truthy_values() {
237+
for val in ["1", "true", "TRUE", "True", "yes", "YES", "Yes", "y", "Y"] {
238+
std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", val);
239+
assert!(is_telemetry_metrics_disabled(), "value {}", val);
240+
}
241+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
242+
}
243+
244+
#[test]
245+
#[serial]
246+
fn telemetry_metrics_not_disabled_with_falsy_values() {
247+
for val in ["0", "false", "no", "maybe", ""] {
248+
std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", val);
249+
assert!(!is_telemetry_metrics_disabled(), "value {}", val);
250+
}
251+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
252+
}
253+
254+
#[test]
255+
#[serial]
256+
fn telemetry_traces_enabled_by_default() {
257+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
258+
assert!(!is_telemetry_traces_disabled());
259+
}
260+
261+
#[test]
262+
#[serial]
263+
fn telemetry_traces_disabled_with_truthy_values() {
264+
for val in ["1", "true", "TRUE", "True", "yes", "YES", "Yes", "y", "Y"] {
265+
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", val);
266+
assert!(is_telemetry_traces_disabled(), "value {}", val);
267+
}
268+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
269+
}
270+
271+
#[test]
272+
#[serial]
273+
fn telemetry_traces_not_disabled_with_falsy_values() {
274+
for val in ["0", "false", "no", "maybe", ""] {
275+
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", val);
276+
assert!(!is_telemetry_traces_disabled(), "value {}", val);
277+
}
278+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
279+
}
280+
281+
#[test]
282+
#[serial]
283+
fn telemetry_traces_disabled_implies_auto_instrumentation_disabled() {
284+
std::env::set_var("AWS_LAMBDA_EXEC_WRAPPER", "/opt/lumigo_wrapper");
285+
std::env::remove_var("DASH0_DISABLE_AUTO_INSTRUMENTATION");
286+
std::env::set_var("DASH0_DISABLE_TELEMETRY_TRACES", "true");
287+
assert!(is_auto_instrumented_disabled());
288+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_TRACES");
289+
std::env::remove_var("AWS_LAMBDA_EXEC_WRAPPER");
290+
}
201291
}

src/otlp/metrics_creation.rs

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,22 @@ use opentelemetry_proto::tonic::resource::v1::Resource;
1313
use prost::Message;
1414

1515
const DURATION_BOUNDS: &[f64] = &[
16-
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,
17-
10000.0,
16+
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,
1817
];
1918

2019
const MEMORY_BOUNDS: &[f64] = &[
21-
0.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1536.0, 2048.0, 3072.0, 4096.0, 8192.0, 10240.0,
20+
0.0,
21+
67_108_864.0,
22+
134_217_728.0,
23+
268_435_456.0,
24+
536_870_912.0,
25+
1_073_741_824.0,
26+
1_610_612_736.0,
27+
2_147_483_648.0,
28+
3_221_225_472.0,
29+
4_294_967_296.0,
30+
8_589_934_592.0,
31+
10_737_418_240.0,
2232
];
2333

2434
fn compute_bucket_counts(value: f64, bounds: &[f64]) -> Vec<u64> {
@@ -122,8 +132,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
122132
metrics.push(create_histogram_metric(
123133
"faas.invoke_duration",
124134
"Duration of the invocation",
125-
"ms",
126-
data.duration,
135+
"s",
136+
data.duration / 1000.0,
127137
get_metric_attributes(),
128138
start_time_unix_nano,
129139
time_unix_nano,
@@ -135,8 +145,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
135145
metrics.push(create_histogram_metric(
136146
"faas.init_duration",
137147
"Duration of the cold start initialization",
138-
"ms",
139-
data.init_duration,
148+
"s",
149+
data.init_duration / 1000.0,
140150
get_metric_attributes(),
141151
start_time_unix_nano,
142152
time_unix_nano,
@@ -148,8 +158,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
148158
metrics.push(create_histogram_metric(
149159
"dash0.faas.billed_duration",
150160
"Billed duration of the invocation",
151-
"ms",
152-
data.billed_duration,
161+
"s",
162+
data.billed_duration / 1000.0,
153163
get_metric_attributes(),
154164
start_time_unix_nano,
155165
time_unix_nano,
@@ -161,8 +171,8 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
161171
metrics.push(create_histogram_metric(
162172
"faas.mem_usage",
163173
"Memory used by the invocation",
164-
"MB",
165-
data.memory_usage as f64,
174+
"By",
175+
data.memory_usage as f64 * 1024.0 * 1024.0,
166176
get_metric_attributes(),
167177
start_time_unix_nano,
168178
time_unix_nano,
@@ -232,6 +242,9 @@ pub fn create_metrics(invocation_id: &str) -> Option<StoredMetric> {
232242
}
233243

234244
pub fn create_supplementary_metrics(invocation_id: &str) {
245+
if crate::config::user::is_telemetry_metrics_disabled() {
246+
return;
247+
}
235248
if let Some(metric) = create_metrics(invocation_id) {
236249
store_metric(metric);
237250
}
@@ -282,21 +295,21 @@ mod tests {
282295

283296
// faas.invoke_duration
284297
let duration_metric = find_metric_by_name(metrics, "faas.invoke_duration").unwrap();
285-
assert_eq!(duration_metric.unit, "ms");
298+
assert_eq!(duration_metric.unit, "s");
286299
if let Some(Data::Histogram(h)) = &duration_metric.data {
287300
assert_eq!(
288301
h.aggregation_temporality,
289302
AggregationTemporality::Delta as i32
290303
);
291304
let dp = &h.data_points[0];
292305
assert_eq!(dp.count, 1);
293-
assert_eq!(dp.sum, Some(200.0));
294-
assert_eq!(dp.min, Some(200.0));
295-
assert_eq!(dp.max, Some(200.0));
306+
assert_eq!(dp.sum, Some(0.2));
307+
assert_eq!(dp.min, Some(0.2));
308+
assert_eq!(dp.max, Some(0.2));
296309
assert_eq!(dp.explicit_bounds, DURATION_BOUNDS.to_vec());
297-
// 200ms <= 250.0, which is bounds[7], so bucket index 7
310+
// 0.2s <= 0.25, which is bounds[6], so bucket index 6
298311
let mut expected_counts = vec![0u64; DURATION_BOUNDS.len() + 1];
299-
expected_counts[7] = 1;
312+
expected_counts[6] = 1;
300313
assert_eq!(dp.bucket_counts, expected_counts);
301314
assert_eq!(dp.start_time_unix_nano, 850_000_000); // (1000 - 150) * 1_000_000
302315
assert_eq!(dp.time_unix_nano, 1_200_000_000); // 1200 * 1_000_000
@@ -314,27 +327,28 @@ mod tests {
314327

315328
// faas.init_duration
316329
let init_metric = find_metric_by_name(metrics, "faas.init_duration").unwrap();
317-
assert_eq!(init_metric.unit, "ms");
330+
assert_eq!(init_metric.unit, "s");
318331
if let Some(Data::Histogram(h)) = &init_metric.data {
319-
assert_eq!(h.data_points[0].sum, Some(150.0));
332+
assert_eq!(h.data_points[0].sum, Some(0.15));
320333
} else {
321334
panic!("Expected Histogram data for faas.init_duration");
322335
}
323336

324337
// dash0.faas.billed_duration
325338
let billed_metric = find_metric_by_name(metrics, "dash0.faas.billed_duration").unwrap();
326-
assert_eq!(billed_metric.unit, "ms");
339+
assert_eq!(billed_metric.unit, "s");
327340
if let Some(Data::Histogram(h)) = &billed_metric.data {
328-
assert_eq!(h.data_points[0].sum, Some(300.0));
341+
assert_eq!(h.data_points[0].sum, Some(0.3));
329342
} else {
330343
panic!("Expected Histogram data for dash0.faas.billed_duration");
331344
}
332345

333346
// faas.mem_usage
334347
let memory_metric = find_metric_by_name(metrics, "faas.mem_usage").unwrap();
335-
assert_eq!(memory_metric.unit, "MB");
348+
assert_eq!(memory_metric.unit, "By");
336349
if let Some(Data::Histogram(h)) = &memory_metric.data {
337-
assert_eq!(h.data_points[0].sum, Some(128.0));
350+
// 128 MB = 128 * 1024 * 1024 bytes
351+
assert_eq!(h.data_points[0].sum, Some(134_217_728.0));
338352
} else {
339353
panic!("Expected Histogram data for faas.mem_usage");
340354
}
@@ -396,6 +410,20 @@ mod tests {
396410
}
397411
}
398412

413+
#[test]
414+
#[serial]
415+
fn supplementary_metrics_skipped_when_disabled() {
416+
reset_store();
417+
let invocation_id = "inv-metric-1";
418+
setup_invocation(invocation_id, 150.0);
419+
420+
std::env::set_var("DASH0_DISABLE_TELEMETRY_METRICS", "true");
421+
create_supplementary_metrics(invocation_id);
422+
std::env::remove_var("DASH0_DISABLE_TELEMETRY_METRICS");
423+
424+
assert!(crate::state::invocation_data::take_metrics().is_empty());
425+
}
426+
399427
#[test]
400428
#[serial]
401429
fn skips_all_metrics_when_end_time_is_zero() {

src/otlp/span_creation.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,9 @@ pub fn create_spans(
222222
}
223223

224224
pub fn create_supplementary_spans(invocation_id: &str, store: bool) -> Option<StoredTrace> {
225-
if crate::config::user::is_xray_traces_enabled() {
225+
if crate::config::user::is_xray_traces_enabled()
226+
|| crate::config::user::is_telemetry_traces_disabled()
227+
{
226228
return None;
227229
}
228230
let trace = create_spans(invocation_id, true, false);
@@ -235,7 +237,9 @@ pub fn create_supplementary_spans(invocation_id: &str, store: bool) -> Option<St
235237
}
236238

237239
pub fn create_overhead_supplementary_span(invocation_id: &str) {
238-
if crate::config::user::is_xray_traces_enabled() {
240+
if crate::config::user::is_xray_traces_enabled()
241+
|| crate::config::user::is_telemetry_traces_disabled()
242+
{
239243
return;
240244
}
241245
if let Some(trace) = create_spans(invocation_id, false, true) {

0 commit comments

Comments
 (0)