From 0bd48b1f68af6872e916a70bd2182859c6230a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Th=C3=A9bault?= Date: Fri, 28 Jun 2024 15:19:41 +0200 Subject: [PATCH 1/3] feat(otel): allow to configure the faas.trigger attribute of the span --- lambda-runtime/src/layers/otel.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lambda-runtime/src/layers/otel.rs b/lambda-runtime/src/layers/otel.rs index bcba399a..dc93583d 100644 --- a/lambda-runtime/src/layers/otel.rs +++ b/lambda-runtime/src/layers/otel.rs @@ -10,6 +10,7 @@ use tracing::{instrument::Instrumented, Instrument}; /// a function to flush OpenTelemetry after the end of the invocation. pub struct OpenTelemetryLayer { flush_fn: F, + otel_attribute_trigger: Option, } impl OpenTelemetryLayer @@ -18,7 +19,20 @@ where { /// Create a new [OpenTelemetryLayer] with the provided flush function. pub fn new(flush_fn: F) -> Self { - Self { flush_fn } + Self { + flush_fn, + otel_attribute_trigger: None, + } + } + + /// Configure the `faas.trigger` attribute of the OpenTelemetry span. + /// Defaults to `http` if not set. + /// See https://opentelemetry.io/docs/specs/semconv/attributes-registry/faas/ for the list of possible triggers. + pub fn with_trigger>(self, trigger: T) -> Self { + Self { + otel_attribute_trigger: Some(trigger.into()), + ..self + } } } @@ -33,6 +47,10 @@ where inner, flush_fn: self.flush_fn.clone(), coldstart: true, + otel_attribute_trigger: self + .otel_attribute_trigger + .clone() + .unwrap_or_else(|| "http".to_string()), } } } @@ -42,6 +60,7 @@ pub struct OpenTelemetryService { inner: S, flush_fn: F, coldstart: bool, + otel_attribute_trigger: String, } impl Service for OpenTelemetryService @@ -61,7 +80,7 @@ where let span = tracing::info_span!( "Lambda function invocation", "otel.name" = req.context.env_config.function_name, - { traceconv::FAAS_TRIGGER } = "http", + { traceconv::FAAS_TRIGGER } = &self.otel_attribute_trigger, { traceconv::FAAS_INVOCATION_ID } = req.context.request_id, { traceconv::FAAS_COLDSTART } = self.coldstart ); From 2842e60be3d7397057eb03747487b4e5ac1b43d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Th=C3=A9bault?= Date: Fri, 28 Jun 2024 15:38:25 +0200 Subject: [PATCH 2/3] fix: update opentelemetry-tracing example --- examples/opentelemetry-tracing/src/main.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/opentelemetry-tracing/src/main.rs b/examples/opentelemetry-tracing/src/main.rs index 4020d87c..b9756755 100644 --- a/examples/opentelemetry-tracing/src/main.rs +++ b/examples/opentelemetry-tracing/src/main.rs @@ -24,10 +24,15 @@ async fn main() -> Result<(), BoxError> { .init(); // Initialize the Lambda runtime and add OpenTelemetry tracing - let runtime = Runtime::new(service_fn(echo)).layer(OtelLayer::new(|| { - // Make sure that the trace is exported before the Lambda runtime is frozen - tracer_provider.force_flush(); - })); + let runtime = Runtime::new(service_fn(echo)).layer( + // Create a tracing span for each Lambda invocation + OtelLayer::new(|| { + // Make sure that the trace is exported before the Lambda runtime is frozen + tracer_provider.force_flush(); + }) + // Set the "faas.trigger" attribute of the span (defaults to "http" otherwise) + .with_trigger("datasource"), + ); runtime.run().await?; Ok(()) } From 5d824be86a88df31237638022c2fc67d9c7059ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Th=C3=A9bault?= Date: Sun, 30 Jun 2024 15:32:50 +0200 Subject: [PATCH 3/3] fix: use datasource as default faas.trigger + introduce enum OpenTelemetryFaasTrigger --- examples/opentelemetry-tracing/src/main.rs | 9 +++-- lambda-runtime/src/layers/mod.rs | 2 +- lambda-runtime/src/layers/otel.rs | 47 +++++++++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/examples/opentelemetry-tracing/src/main.rs b/examples/opentelemetry-tracing/src/main.rs index b9756755..85c3791c 100644 --- a/examples/opentelemetry-tracing/src/main.rs +++ b/examples/opentelemetry-tracing/src/main.rs @@ -1,4 +1,7 @@ -use lambda_runtime::{layers::OpenTelemetryLayer as OtelLayer, LambdaEvent, Runtime}; +use lambda_runtime::{ + layers::{OpenTelemetryFaasTrigger, OpenTelemetryLayer as OtelLayer}, + LambdaEvent, Runtime, +}; use opentelemetry::trace::TracerProvider; use opentelemetry_sdk::{runtime, trace}; use tower::{service_fn, BoxError}; @@ -30,8 +33,8 @@ async fn main() -> Result<(), BoxError> { // Make sure that the trace is exported before the Lambda runtime is frozen tracer_provider.force_flush(); }) - // Set the "faas.trigger" attribute of the span (defaults to "http" otherwise) - .with_trigger("datasource"), + // Set the "faas.trigger" attribute of the span to "pubsub" + .with_trigger(OpenTelemetryFaasTrigger::PubSub), ); runtime.run().await?; Ok(()) diff --git a/lambda-runtime/src/layers/mod.rs b/lambda-runtime/src/layers/mod.rs index 55fdccd3..1f07f199 100644 --- a/lambda-runtime/src/layers/mod.rs +++ b/lambda-runtime/src/layers/mod.rs @@ -14,4 +14,4 @@ pub use trace::TracingLayer; #[cfg(feature = "opentelemetry")] mod otel; #[cfg(feature = "opentelemetry")] -pub use otel::OpenTelemetryLayer; +pub use otel::{OpenTelemetryFaasTrigger, OpenTelemetryLayer}; diff --git a/lambda-runtime/src/layers/otel.rs b/lambda-runtime/src/layers/otel.rs index dc93583d..e6b7cfff 100644 --- a/lambda-runtime/src/layers/otel.rs +++ b/lambda-runtime/src/layers/otel.rs @@ -1,4 +1,4 @@ -use std::{future::Future, pin::Pin, task}; +use std::{fmt::Display, future::Future, pin::Pin, task}; use crate::LambdaInvocation; use opentelemetry_semantic_conventions::trace as traceconv; @@ -10,7 +10,7 @@ use tracing::{instrument::Instrumented, Instrument}; /// a function to flush OpenTelemetry after the end of the invocation. pub struct OpenTelemetryLayer { flush_fn: F, - otel_attribute_trigger: Option, + otel_attribute_trigger: OpenTelemetryFaasTrigger, } impl OpenTelemetryLayer @@ -21,16 +21,14 @@ where pub fn new(flush_fn: F) -> Self { Self { flush_fn, - otel_attribute_trigger: None, + otel_attribute_trigger: Default::default(), } } /// Configure the `faas.trigger` attribute of the OpenTelemetry span. - /// Defaults to `http` if not set. - /// See https://opentelemetry.io/docs/specs/semconv/attributes-registry/faas/ for the list of possible triggers. - pub fn with_trigger>(self, trigger: T) -> Self { + pub fn with_trigger(self, trigger: OpenTelemetryFaasTrigger) -> Self { Self { - otel_attribute_trigger: Some(trigger.into()), + otel_attribute_trigger: trigger, ..self } } @@ -47,10 +45,7 @@ where inner, flush_fn: self.flush_fn.clone(), coldstart: true, - otel_attribute_trigger: self - .otel_attribute_trigger - .clone() - .unwrap_or_else(|| "http".to_string()), + otel_attribute_trigger: self.otel_attribute_trigger.to_string(), } } } @@ -133,3 +128,33 @@ where task::Poll::Ready(ready) } } + +/// Represent the possible values for the OpenTelemetry `faas.trigger` attribute. +/// See https://opentelemetry.io/docs/specs/semconv/attributes-registry/faas/ for more details. +#[derive(Default, Clone, Copy)] +#[non_exhaustive] +pub enum OpenTelemetryFaasTrigger { + /// A response to some data source operation such as a database or filesystem read/write + #[default] + Datasource, + /// To provide an answer to an inbound HTTP request + Http, + /// A function is set to be executed when messages are sent to a messaging system + PubSub, + /// A function is scheduled to be executed regularly + Timer, + /// If none of the others apply + Other, +} + +impl Display for OpenTelemetryFaasTrigger { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OpenTelemetryFaasTrigger::Datasource => write!(f, "datasource"), + OpenTelemetryFaasTrigger::Http => write!(f, "http"), + OpenTelemetryFaasTrigger::PubSub => write!(f, "pubsub"), + OpenTelemetryFaasTrigger::Timer => write!(f, "timer"), + OpenTelemetryFaasTrigger::Other => write!(f, "other"), + } + } +}