Function traced_handler

Source
pub async fn traced_handler<T, R, F, Fut>(
    name: &'static str,
    event: LambdaEvent<T>,
    completion_handler: TelemetryCompletionHandler,
    handler_fn: F,
) -> Result<R, Error>
where T: SpanAttributesExtractor + DeserializeOwned + Serialize + Send + 'static, R: Serialize + Send + 'static, F: FnOnce(LambdaEvent<T>) -> Fut, Fut: Future<Output = Result<R, Error>> + Send,
Expand description

Wraps a Lambda handler function with OpenTelemetry tracing.

This function wraps a Lambda handler function to automatically create and configure OpenTelemetry spans for each invocation. It provides automatic instrumentation with minimal code changes required.

§Features

  • Creates spans for each invocation with configurable names
  • Extracts attributes from events implementing SpanAttributesExtractor
  • Propagates context from incoming requests via headers
  • Tracks response status codes for HTTP responses
  • Supports both sync and async span processing modes

§Span Attributes

The following attributes are automatically set:

  • otel.name: The handler name provided
  • otel.kind: “SERVER” by default, can be overridden by extractor
  • requestId: The Lambda request ID
  • faas.invocation_id: The Lambda request ID
  • cloud.resource_id: The Lambda function ARN
  • cloud.account.id: The AWS account ID (extracted from ARN)
  • faas.trigger: “http” or “other” based on event type
  • http.status_code: For HTTP responses

Additional attributes can be added through the SpanAttributesExtractor trait.

§Error Handling

The wrapper handles errors gracefully:

  • Extraction failures don’t fail the function
  • Invalid headers are skipped
  • Export errors are logged but don’t fail the function
  • 5xx status codes set the span status to ERROR

§Type Parameters

  • T - The event payload type that must be deserializable and serializable
  • R - The response type that must be serializable
  • F - The handler function type
  • Fut - The future returned by the handler function

§Arguments

  • name - Name of the handler/span
  • event - Lambda event containing both payload and context
  • completion_handler - Handler for managing span export
  • handler_fn - The actual Lambda handler function to wrap

§Returns

Returns the result from the handler function

§Examples

Basic usage:

use lambda_otel_lite::{init_telemetry, traced_handler, TelemetryConfig};
use lambda_runtime::{service_fn, Error, LambdaEvent};
use serde_json::Value;

async fn function_handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
    Ok(serde_json::json!({ "statusCode": 200 }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let completion_handler = init_telemetry(TelemetryConfig::default()).await?;
     
    let func = service_fn(|event| {
        traced_handler(
            "my-handler",
            event,
            completion_handler.clone(),
            function_handler,
        )
    });

    lambda_runtime::run(func).await
}

With custom event type implementing SpanAttributesExtractor:

use lambda_otel_lite::{init_telemetry, traced_handler, TelemetryConfig};
use lambda_otel_lite::{SpanAttributes, SpanAttributesExtractor};
use lambda_runtime::{service_fn, Error, LambdaEvent};
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use opentelemetry::Value;
#[derive(Serialize, Deserialize)]
struct CustomEvent {
    operation: String,
}

impl SpanAttributesExtractor for CustomEvent {
    fn extract_span_attributes(&self) -> SpanAttributes {
        let mut attributes = HashMap::new();
        attributes.insert("operation".to_string(), Value::String(self.operation.clone().into()));
        SpanAttributes::builder()
            .attributes(attributes)
            .build()
    }
}

async fn handler(event: LambdaEvent<CustomEvent>) -> Result<serde_json::Value, Error> {
    Ok(serde_json::json!({ "statusCode": 200 }))
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let completion_handler = init_telemetry(TelemetryConfig::default()).await?;
     
    let func = service_fn(|event| {
        traced_handler(
            "custom-handler",
            event,
            completion_handler.clone(),
            handler,
        )
    });

    lambda_runtime::run(func).await
}