lambda_otel_lite/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
//! OpenTelemetry instrumentation optimized for AWS Lambda functions.
//!
//! This crate provides a lightweight, efficient implementation of OpenTelemetry tracing
//! specifically designed for AWS Lambda functions. It offers flexible processing modes,
//! automatic resource detection, and integration with the Lambda Extensions API.
//!
//! # Features
//!
//! - **Flexible Processing Modes**: Support for synchronous, asynchronous, and custom export strategies
//! - **Automatic Resource Detection**: Automatic extraction of Lambda environment attributes
//! - **Lambda Extension Integration**: Built-in extension for efficient telemetry export
//! - **Efficient Memory Usage**: Fixed-size ring buffer to prevent memory growth
//! - **AWS Event Support**: Automatic extraction of attributes from common AWS event types
//!
//! # Architecture
//!
//! The crate is organized into several modules, each handling a specific aspect of telemetry:
//!
//! - [`telemetry`]: Core initialization and configuration
//! - [`processor`]: Span processing and export strategies
//! - [`extension`]: Lambda extension implementation
//! - [`layer`]: Tower middleware for automatic instrumentation
//! - [`handler`]: Function wrapper for manual instrumentation
//!
//! # Quick Start
//!
//! ```no_run
//! use lambda_otel_lite::{init_telemetry, TelemetryConfig};
//! use lambda_runtime::{service_fn, Error, LambdaEvent};
//! use serde_json::Value;
//!
//! async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
//! Ok(event.payload)
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Error> {
//! // Initialize telemetry with default configuration
//! let completion_handler = init_telemetry(TelemetryConfig::default()).await?;
//!
//! // Run the Lambda function
//! lambda_runtime::run(service_fn(|event| async {
//! let result = handler(event).await;
//! completion_handler.complete();
//! result
//! })).await
//! }
//! ```
//!
//! # Processing Modes
//!
//! The crate supports three processing modes for telemetry data:
//!
//! - **Sync Mode**: Direct export in handler thread
//! - Simple execution path with no IPC overhead
//! - Efficient for small payloads and low resource environments
//! - Guarantees span delivery before response
//!
//! - **Async Mode**: Export via Lambda extension
//! - Requires coordination with extension process
//! - Additional overhead from IPC
//! - Best when advanced export features are needed
//! - Provides retry capabilities through extension
//!
//! - **Finalize Mode**: Custom export strategy
//! - Full control over export timing and behavior
//! - Compatible with BatchSpanProcessor
//! - Best for specialized export requirements
//!
//! See [`processor`] module for detailed documentation on processing modes.
//!
//! # Configuration
//!
//! Configuration is handled through environment variables:
//!
//! - `LAMBDA_EXTENSION_SPAN_PROCESSOR_MODE`: Controls processing mode
//! - "sync" for Sync mode (default)
//! - "async" for Async mode
//! - "finalize" for Finalize mode
//!
//! - `LAMBDA_SPAN_PROCESSOR_QUEUE_SIZE`: Controls buffer size
//! - Defaults to 2048 spans
//! - Should be tuned based on span volume
//!
//! - `OTEL_SERVICE_NAME`: Service name for spans
//! - Falls back to AWS_LAMBDA_FUNCTION_NAME
//! - Required for proper service identification
//!
//! See [`telemetry`] module for detailed configuration options.
//!
//! # Examples
//!
//! ## Using the Tower Layer
//!
//! ```no_run
//! use lambda_otel_lite::{init_telemetry, TelemetryConfig, OtelTracingLayer};
//! use lambda_runtime::{service_fn, Error, LambdaEvent};
//! use tower::ServiceBuilder;
//! use aws_lambda_events::apigw::ApiGatewayV2httpRequest;
//!
//! async fn handler(event: LambdaEvent<ApiGatewayV2httpRequest>) -> Result<serde_json::Value, Error> {
//! Ok(serde_json::json!({"status": "ok"}))
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Error> {
//! let completion_handler = init_telemetry(TelemetryConfig::default()).await?;
//!
//! let service = ServiceBuilder::new()
//! .layer(OtelTracingLayer::new(completion_handler.clone()))
//! .service_fn(handler);
//!
//! lambda_runtime::run(service).await
//! }
//! ```
//!
//! See [`layer`] module for more examples of automatic instrumentation.
//!
//! ## Manual Instrumentation
//!
//! ```no_run
//! use lambda_otel_lite::{init_telemetry, TelemetryConfig, traced_handler, TracedHandlerOptions};
//! use lambda_runtime::{service_fn, Error, LambdaEvent};
//! use serde_json::Value;
//!
//! async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
//! Ok(event.payload)
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Error> {
//! let completion_handler = init_telemetry(TelemetryConfig::default()).await?;
//!
//! lambda_runtime::run(service_fn(|event: LambdaEvent<Value>| {
//! traced_handler(
//! TracedHandlerOptions::default().with_name("my-handler"),
//! completion_handler.clone(),
//! handler,
//! )
//! })).await
//! }
//! ```
//!
//! See [`handler`] module for more examples of manual instrumentation.
pub use otlp_stdout_span_exporter::OtlpStdoutSpanExporter;
mod extension;
mod handler;
mod layer;
mod processor;
mod telemetry;
pub use extension::{register_extension, OtelInternalExtension};
pub use handler::{traced_handler, TracedHandlerOptions};
pub use layer::{OtelTracingLayer, SpanAttributes, SpanAttributesExtractor};
pub use processor::{LambdaSpanProcessor, ProcessorConfig, ProcessorMode};
pub use telemetry::{
init_telemetry, TelemetryCompletionHandler, TelemetryConfig, TelemetryConfigBuilder,
};
#[cfg(doctest)]
#[macro_use]
extern crate doc_comment;
#[cfg(doctest)]
use doc_comment::doctest;
#[cfg(doctest)]
doctest!("../README.md", readme);