Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions opentelemetry-dotnet-contrib.sln
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.OpAmp.Client"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.OpAmp.Client.Tests", "test\OpenTelemetry.OpAmp.Client.Tests\OpenTelemetry.OpAmp.Client.Tests.csproj", "{044B896A-FDC6-422F-B349-483BDE19F685}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AWS", "AWS", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
ProjectSection(SolutionItems) = preProject
src\Shared\AWS\AWSSemanticConventions.Base.cs = src\Shared\AWS\AWSSemanticConventions.Base.cs
src\Shared\AWS\AWSSemanticConventions.cs = src\Shared\AWS\AWSSemanticConventions.cs
src\Shared\AWS\AWSSemanticConventions.Legacy.cs = src\Shared\AWS\AWSSemanticConventions.Legacy.cs
src\Shared\AWS\AWSSemanticConventions.v1.28.0.cs = src\Shared\AWS\AWSSemanticConventions.v1.28.0.cs
src\Shared\AWS\AWSSemanticConventions.v1.29.0.cs = src\Shared\AWS\AWSSemanticConventions.v1.29.0.cs
src\Shared\AWS\SemanticConventionVersion.cs = src\Shared\AWS\SemanticConventionVersion.cs
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -965,6 +975,7 @@ Global
{00C9F0B8-3D51-483C-821A-5889B38A144C} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
{B5AF4876-3970-4686-A4A9-4EA369843F1F} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}
{044B896A-FDC6-422F-B349-483BDE19F685} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {1FCC8EEC-9E75-4FEA-AFCF-363DD33FF0B9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B0816796-CDB3-47D7-8C3C-946434DE3B66}
Expand Down
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Instrumentation.AWSLambda/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Add `faas.instance` and `faas.max_memory` resource/span attributes.
([#2928](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2928))

## 1.12.0

Released 2025-May-06
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public Resource Detect()
.AddAttributeCloudRegion(AWSLambdaUtils.GetAWSRegion())
.AddAttributeFaasName(AWSLambdaUtils.GetFunctionName())
.AddAttributeFaasVersion(AWSLambdaUtils.GetFunctionVersion())
.AddAttributeFaasInstance(AWSLambdaUtils.GetFunctionInstance())
.AddAttributeFaasMaxMemory(AWSLambdaUtils.GetFunctionMemorySize())
.Build();

return new Resource(resourceAttributes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

using System.Diagnostics;
using System.Globalization;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.ApplicationLoadBalancerEvents;
using Amazon.Lambda.Core;
Expand All @@ -23,6 +24,8 @@ internal class AWSLambdaUtils
private const string AWSXRayTraceHeaderKey = "X-Amzn-Trace-Id";
private const string FunctionName = "AWS_LAMBDA_FUNCTION_NAME";
private const string FunctionVersion = "AWS_LAMBDA_FUNCTION_VERSION";
private const string FunctionMaxMemory = "AWS_LAMBDA_FUNCTION_MEMORY_SIZE";
private const string FunctionLogStreamName = "AWS_LAMBDA_LOG_STREAM_NAME";

private static readonly Func<IDictionary<string, string>, string, IEnumerable<string>> Getter = (headers, name) =>
{
Expand Down Expand Up @@ -101,6 +104,34 @@ internal static (ActivityContext ParentContext, IEnumerable<ActivityLink>? Links
return Environment.GetEnvironmentVariable(FunctionVersion);
}

internal static int? GetFunctionMemorySize(ILambdaContext? context = null)
{
int? memoryLimitInMB = context?.MemoryLimitInMB;

if (!memoryLimitInMB.HasValue)
{
var value = Environment.GetEnvironmentVariable(FunctionMaxMemory);

if (!string.IsNullOrWhiteSpace(value) && int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int valueMB))
{
memoryLimitInMB = valueMB;
}
}

if (memoryLimitInMB.HasValue)
{
// Convert to bytes to match semantic conventions (e.g. 128 to 134217728)
return memoryLimitInMB.Value * 1024 * 1024;
}

return null;
}

internal static string? GetFunctionInstance(ILambdaContext? context = null)
{
return context?.LogStreamName ?? Environment.GetEnvironmentVariable(FunctionLogStreamName);
}

internal static IEnumerable<string>? GetHeaderValues(APIGatewayProxyRequest request, string name)
{
var multiValueHeader = request.MultiValueHeaders?.GetValueByKeyIgnoringCase(name);
Expand Down Expand Up @@ -147,6 +178,8 @@ internal IEnumerable<KeyValuePair<string, object>> GetFunctionTags<TInput>(TInpu
.AddAttributeFaasName(GetFunctionName(context))
.AddAttributeFaasExecution(context.AwsRequestId)
.AddAttributeFaasID(GetFaasId(functionArn))
.AddAttributeFaasInstance(GetFunctionInstance(context))
.AddAttributeFaasMaxMemory(GetFunctionMemorySize(context))
.AddAttributeCloudAccountID(GetAccountId(functionArn))
.Build();

Expand Down
16 changes: 16 additions & 0 deletions src/Shared/AWS/AWSSemanticConventions.Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,22 @@ private abstract class AWSSemanticConventionsBase
/// FaasAttributes.AttributeFaasColdstart
/// </remarks>
public virtual string AttributeFaasColdStart => string.Empty;

/// <summary>
/// The execution environment ID as a string, that will be potentially reused for other invocations to the same function/function version.
/// </summary>
/// <remarks>
/// FaasAttributes.AttributeFaasInstance
/// </remarks>
public virtual string AttributeFaasInstance => string.Empty;

/// <summary>
/// The amount of memory available to the serverless function converted to Bytes.
/// </summary>
/// <remarks>
/// FaasAttributes.AttributeFaasMaxMemory
/// </remarks>
public virtual string AttributeFaasMaxMemory => string.Empty;
#endregion

#region GEN AI Attributes
Expand Down
2 changes: 2 additions & 0 deletions src/Shared/AWS/AWSSemanticConventions.Legacy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ private abstract class AWSSemanticConventionsLegacy : AWSSemanticConventionsBase
public override string AttributeFaasVersion => "faas.version";
public override string AttributeFaasTrigger => "faas.trigger";
public override string AttributeFaasColdStart => "faas.coldstart";
public override string AttributeFaasInstance => "faas.instance";
public override string AttributeFaasMaxMemory => "faas.max_memory";

// GEN AI Attributes
public override string AttributeGenAiModelId => "gen_ai.request.model";
Expand Down
8 changes: 8 additions & 0 deletions src/Shared/AWS/AWSSemanticConventions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ public AttributeBuilderImpl AddAttributeFaasTrigger(object? value, bool addIfEmp
public AttributeBuilderImpl AddAttributeFaasColdStart(object? value, bool addIfEmpty = false) =>
this.awsSemanticConventions.Add(this, x => x.AttributeFaasColdStart, value, addIfEmpty);

/// <inheritdoc cref="AWSSemanticConventionsBase.AttributeFaasInstance"/>
public AttributeBuilderImpl AddAttributeFaasInstance(object? value, bool addIfEmpty = false) =>
this.awsSemanticConventions.Add(this, x => x.AttributeFaasInstance, value, addIfEmpty);

/// <inheritdoc cref="AWSSemanticConventionsBase.AttributeFaasMaxMemory"/>
public AttributeBuilderImpl AddAttributeFaasMaxMemory(object? value, bool addIfEmpty = false) =>
this.awsSemanticConventions.Add(this, x => x.AttributeFaasMaxMemory, value, addIfEmpty);

#endregion

#region Host
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public AWSLambdaWrapperTests()
Environment.SetEnvironmentVariable("AWS_REGION", "us-east-1");
Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME", "testfunction");
Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_VERSION", "latest");
Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "128");
Environment.SetEnvironmentVariable("AWS_LAMBDA_LOG_STREAM_NAME", "2025/07/21/[$LATEST]7b176c212e954e62adfb9b5451cb5374");
}

public void Dispose()
Expand Down Expand Up @@ -322,6 +324,8 @@ private void AssertResourceAttributes(Resource? resource)
Assert.Equal("us-east-1", resourceAttributes[ExpectedSemanticConventions.AttributeCloudRegion]);
Assert.Equal("testfunction", resourceAttributes[ExpectedSemanticConventions.AttributeFaasName]);
Assert.Equal("latest", resourceAttributes[ExpectedSemanticConventions.AttributeFaasVersion]);
Assert.Equal("2025/07/21/[$LATEST]7b176c212e954e62adfb9b5451cb5374", resourceAttributes[ExpectedSemanticConventions.AttributeFaasInstance]);
Assert.Equal(134217728L, resourceAttributes[ExpectedSemanticConventions.AttributeFaasMaxMemory]);
}

private void AssertSpanAttributes(Activity activity)
Expand All @@ -331,6 +335,8 @@ private void AssertSpanAttributes(Activity activity)
Assert.Equal(this.sampleLambdaContext.FunctionName, activity.GetTagValue(ExpectedSemanticConventions.AttributeFaasName));
Assert.Equal("other", activity.GetTagValue(ExpectedSemanticConventions.AttributeFaasTrigger));
Assert.Equal("111111111111", activity.GetTagValue(ExpectedSemanticConventions.AttributeCloudAccountID));
Assert.Equal(this.sampleLambdaContext.LogStreamName, activity.GetTagValue(ExpectedSemanticConventions.AttributeFaasInstance));
Assert.Equal(this.sampleLambdaContext.MemoryLimitInMB * 1024 * 1024, activity.GetTagValue(ExpectedSemanticConventions.AttributeFaasMaxMemory));
}

private void AssertSpanException(Activity activity)
Expand All @@ -353,5 +359,7 @@ private static class ExpectedSemanticConventions
public const string AttributeFaasID = "cloud.resource_id";
public const string AttributeFaasTrigger = "faas.trigger";
public const string AttributeFaasVersion = "faas.version";
public const string AttributeFaasInstance = "faas.instance";
public const string AttributeFaasMaxMemory = "faas.max_memory";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ internal class SampleLambdaContext : ILambdaContext

public string? LogGroupName { get; set; }

public string? LogStreamName { get; set; }
public string? LogStreamName { get; set; } = "2025/07/21/[$LATEST]c53dd774881747b29e48cc58a46720e5";

public int MemoryLimitInMB { get; set; }
public int MemoryLimitInMB { get; set; } = 256;

public TimeSpan RemainingTime { get; set; }
}
Loading