diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8a676be --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,99 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.0.0] - 2025-08-06 + +### โš ๏ธ BREAKING CHANGES + +**OpenTelemetry Layer Configuration:** +- **OpenTelemetry layer is now disabled by default** (was enabled by default in v1.x) +- Added new required interface properties: `Architecture` and `OtelLayerVersion` + +### โœจ Added + +- **Configurable OTEL layer architecture**: Support for both `amd64` and `arm64` architectures via `Architecture` property (default: "amd64") +- **Configurable OTEL layer version**: Control OTEL layer version via `OtelLayerVersion` property (default: "0-117-0") +- **Dynamic OTEL layer ARN format**: Now uses configurable architecture and version: `arn:aws:lambda:{region}:901920570463:layer:aws-otel-collector-{architecture}-ver-{version}:1` +- **Testing helpers**: New builder methods `WithOtelLayerVersion()` and `WithArchitecture()` for test configuration + +### ๐Ÿ”„ Changed + +- **`IncludeOtelLayer` default**: Changed from `true` to `false` **(BREAKING CHANGE)** +- **Updated OTEL layer version**: Now defaults to latest version (0-117-0, was 0-102-1) +- **Updated AWS CDK dependency**: Upgraded to v2.209.1 from v2.206.0 +- **Test defaults**: All test attributes and customizations now default to OTEL disabled + +### ๐Ÿ› Fixed + +- **Future-proof OTEL versioning**: No longer requires package updates when AWS releases new OTEL layer versions + +### ๐Ÿ“– Migration Guide + +#### For users upgrading from v1.x who want to maintain OTEL functionality: + +**Before (v1.x - OTEL enabled by default):** +```csharp +var lambda = new LambdaFunctionConstruct(this, "MyLambda", new LambdaFunctionConstructProps +{ + FunctionName = "my-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "my-api-role", + PolicyName = "my-api-policy" + // OTEL was enabled by default +}); +``` + +**After (v2.0+ - OTEL must be explicitly enabled):** +```csharp +var lambda = new LambdaFunctionConstruct(this, "MyLambda", new LambdaFunctionConstructProps +{ + FunctionName = "my-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "my-api-role", + PolicyName = "my-api-policy", + IncludeOtelLayer = true, // Must be explicitly enabled + Architecture = "amd64", // Optional: specify architecture (default: amd64) + OtelLayerVersion = "0-117-0" // Optional: specify version (default: latest) +}); +``` + +#### Benefits of the new approach: + +1. **Cost Control**: OTEL layer is now opt-in, preventing unexpected observability costs +2. **Architecture Flexibility**: Support for both x86_64 (amd64) and ARM64 architectures +3. **Version Control**: Specify exact OTEL layer versions for consistent deployments +4. **Future Proof**: No more package updates needed when AWS releases new OTEL versions + +#### Testing Updates: + +**Before:** +```csharp +[LambdaFunctionConstructAutoData] // OTEL enabled by default +public void Test_Lambda_With_OTEL(LambdaFunctionConstructProps props) +``` + +**After:** +```csharp +[LambdaFunctionConstructAutoData(includeOtelLayer: true)] // Must explicitly enable +public void Test_Lambda_With_OTEL(LambdaFunctionConstructProps props) +``` + +## [1.0.1] - Previous Release + +### ๐Ÿ”„ Changed +- Package dependency updates +- Documentation improvements + +--- + +## Support + +- **Issues**: [GitHub Issues](https://github.com/LayeredCraft/cdk-constructs/issues) +- **Discussions**: [GitHub Discussions](https://github.com/LayeredCraft/cdk-constructs/discussions) +- **Documentation**: [https://layeredcraft.github.io/cdk-constructs/](https://layeredcraft.github.io/cdk-constructs/) \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 84adee2..62b6559 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 2.0.0-beta + 2.0.0 MIT diff --git a/docs/examples/index.md b/docs/examples/index.md index b8fec49..ffd9012 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -49,6 +49,7 @@ public class ServerlessApiStack : Stack PolicyName = "user-api-policy", MemorySize = 1024, TimeoutInSeconds = 30, + IncludeOtelLayer = true, // Enable OpenTelemetry for observability PolicyStatements = [ new PolicyStatement(new PolicyStatementProps { @@ -277,6 +278,121 @@ var table = new DynamoDbTableConstruct(this, "ComplexTable", new DynamoDbTableCo }); ``` +## OpenTelemetry Configuration Examples + +### Basic OTEL Enablement + +```csharp +var lambda = new LambdaFunctionConstruct(this, "BasicOtelLambda", new LambdaFunctionConstructProps +{ + FunctionName = "my-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "my-api-role", + PolicyName = "my-api-policy", + IncludeOtelLayer = true // Enable OpenTelemetry (disabled by default in v2.0+) +}); +``` + +### ARM64 Architecture with OTEL + +```csharp +var lambda = new LambdaFunctionConstruct(this, "Arm64OtelLambda", new LambdaFunctionConstructProps +{ + FunctionName = "arm64-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "arm64-api-role", + PolicyName = "arm64-api-policy", + IncludeOtelLayer = true, + Architecture = "arm64", // Use ARM64 for better cost/performance + OtelLayerVersion = "0-117-0" // Specify exact OTEL version +}); +``` + +### Different OTEL Layer Versions + +```csharp +// Production with latest stable OTEL +var prodLambda = new LambdaFunctionConstruct(this, "ProdLambda", new LambdaFunctionConstructProps +{ + FunctionName = "prod-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "prod-api-role", + PolicyName = "prod-api-policy", + IncludeOtelLayer = true, + OtelLayerVersion = "0-117-0" // Latest stable version +}); + +// Development with specific OTEL version for consistency +var devLambda = new LambdaFunctionConstruct(this, "DevLambda", new LambdaFunctionConstructProps +{ + FunctionName = "dev-api", + FunctionSuffix = "dev", + AssetPath = "./lambda.zip", + RoleName = "dev-api-role", + PolicyName = "dev-api-policy", + IncludeOtelLayer = true, + OtelLayerVersion = "0-115-0" // Previous version for testing +}); +``` + +### Migration from v1.x Example + +```csharp +// v1.x approach (OTEL enabled by default) +// var lambda = new LambdaFunctionConstruct(this, "Lambda", props); + +// v2.0+ approach (OTEL must be explicitly enabled) +var lambda = new LambdaFunctionConstruct(this, "Lambda", new LambdaFunctionConstructProps +{ + FunctionName = "migrated-api", + FunctionSuffix = "prod", + AssetPath = "./lambda.zip", + RoleName = "migrated-api-role", + PolicyName = "migrated-api-policy", + IncludeOtelLayer = true, // Must be explicit in v2.0+ + Architecture = "amd64", // Default, but now configurable + OtelLayerVersion = "0-117-0" // Latest version +}); +``` + +### Environment-Specific OTEL Configuration + +```csharp +public class OtelConfig +{ + public bool EnableOtel { get; set; } + public string Architecture { get; set; } = "amd64"; + public string OtelVersion { get; set; } = "0-117-0"; +} + +public void CreateLambda(string environment, OtelConfig otelConfig) +{ + var lambda = new LambdaFunctionConstruct(this, $"{environment}Lambda", new LambdaFunctionConstructProps + { + FunctionName = "my-api", + FunctionSuffix = environment, + AssetPath = "./lambda.zip", + RoleName = $"my-api-{environment}-role", + PolicyName = $"my-api-{environment}-policy", + IncludeOtelLayer = otelConfig.EnableOtel, + Architecture = otelConfig.Architecture, + OtelLayerVersion = otelConfig.OtelVersion, + EnvironmentVariables = new Dictionary + { + { "ENVIRONMENT", environment }, + { "OTEL_ENABLED", otelConfig.EnableOtel.ToString() } + } + }); +} + +// Usage: +// CreateLambda("prod", new OtelConfig { EnableOtel = true, Architecture = "arm64" }); +// CreateLambda("dev", new OtelConfig { EnableOtel = false }); // No observability costs in dev +``` + ## Testing Examples ### Complete Test Suite @@ -373,7 +489,8 @@ public class MyStack : Stack PolicyName = $"my-function-{config.Environment}-policy", MemorySize = config.LambdaMemory, TimeoutInSeconds = config.LambdaTimeout, - IncludeOtelLayer = config.EnableTracing + IncludeOtelLayer = config.EnableTracing, + Architecture = "amd64" // Configurable architecture }); if (!string.IsNullOrEmpty(config.DomainName)) diff --git a/docs/index.md b/docs/index.md index 32dcafb..c146755 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ A comprehensive library of reusable AWS CDK constructs for .NET projects, design ## Key Features -- **๐Ÿš€ Lambda Functions**: Comprehensive Lambda construct with OpenTelemetry support, IAM management, and environment configuration +- **๐Ÿš€ Lambda Functions**: Comprehensive Lambda construct with configurable OpenTelemetry support, IAM management, and environment configuration - **๐ŸŒ Static Sites**: Complete static website hosting with S3, CloudFront, SSL certificates, and Route53 DNS management - **๐Ÿ“Š DynamoDB Tables**: Full-featured DynamoDB construct with streams, TTL, and global secondary indexes - **๐Ÿงช Testing Helpers**: Extensive testing utilities with fluent assertions and builders @@ -43,6 +43,7 @@ public class MyStack : Stack AssetPath = "./lambda-deployment.zip", RoleName = "my-api-role", PolicyName = "my-api-policy", + IncludeOtelLayer = true, // Enable OpenTelemetry (disabled by default in v2.0+) GenerateUrl = true // Creates a Function URL for HTTP access }); @@ -63,7 +64,7 @@ public class MyStack : Stack Full-featured Lambda functions with: -- OpenTelemetry integration +- Configurable OpenTelemetry integration - IAM roles and policies - Environment variables - Function URLs diff --git a/docs/testing/index.md b/docs/testing/index.md index 1aef47a..6558929 100644 --- a/docs/testing/index.md +++ b/docs/testing/index.md @@ -109,11 +109,30 @@ var props = CdkTestHelper.CreatePropsBuilder(AssetPathExtensions.GetTestLambdaZi .WithS3Access("my-bucket") .WithApiGatewayPermission("arn:aws:execute-api:us-east-1:123456789012:abcdef123/*") .WithOtelEnabled(true) + .WithOtelLayerVersion("0-117-0") + .WithArchitecture("arm64") .WithSnapStart(true) .WithGenerateUrl(true) .Build(); ``` +### OpenTelemetry Configuration (v2.0+) + +The props builder includes new methods for configuring OpenTelemetry settings: + +```csharp +var props = CdkTestHelper.CreatePropsBuilder(AssetPathExtensions.GetTestLambdaZipPath()) + .WithOtelEnabled(true) // Enable OTEL layer (disabled by default in v2.0+) + .WithOtelLayerVersion("0-117-0") // Specify OTEL layer version + .WithArchitecture("arm64") // Specify architecture (default: amd64) + .Build(); +``` + +**Available OTEL methods:** +- `WithOtelEnabled(bool)` - Enable/disable OpenTelemetry layer +- `WithOtelLayerVersion(string)` - Specify OTEL layer version (e.g., "0-117-0") +- `WithArchitecture(string)` - Specify Lambda architecture ("amd64" or "arm64") + ### Assertion Methods ```csharp @@ -239,10 +258,10 @@ public void Should_Create_Lambda_With_Custom_Settings(LambdaFunctionConstructPro ```csharp [Theory] -[InlineData(true, true)] // OTEL enabled, permissions included -[InlineData(true, false)] // OTEL enabled, no permissions -[InlineData(false, true)] // OTEL disabled, permissions included -[InlineData(false, false)] // OTEL disabled, no permissions +[InlineData(true, true)] // OTEL explicitly enabled, permissions included +[InlineData(true, false)] // OTEL explicitly enabled, no permissions +[InlineData(false, true)] // OTEL disabled (default in v2.0+), permissions included +[InlineData(false, false)] // OTEL disabled (default in v2.0+), no permissions public void Should_Handle_Different_Configurations(bool includeOtel, bool includePermissions) { var props = CdkTestHelper.CreatePropsBuilder(AssetPathExtensions.GetTestLambdaZipPath())