Skip to content

Commit

Permalink
Merge pull request #613 from hjgraca/fix-metrics-resolution-context
Browse files Browse the repository at this point in the history
chore: Fix metrics lambda context and storage resolution
  • Loading branch information
hjgraca authored Jul 12, 2024
2 parents 33546b4 + 7f4d676 commit a1ae03a
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@
<ProjectReference Include="..\AWS.Lambda.Powertools.Common\AWS.Lambda.Powertools.Common.csproj" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Amazon.Lambda.Core;
using AspectInjector.Broker;
using AWS.Lambda.Powertools.Common;

Expand All @@ -34,11 +35,6 @@ public class MetricsAspect
/// </summary>
private static bool _isColdStart;

/// <summary>
/// Specify to clear Lambda Context on exit
/// </summary>
private bool _clearLambdaContext;

/// <summary>
/// Gets the metrics instance.
/// </summary>
Expand Down Expand Up @@ -100,14 +96,14 @@ public void Before(
var nameSpace = _metricsInstance.GetNamespace();
var service = _metricsInstance.GetService();
Dictionary<string, string> dimensions = null;

_clearLambdaContext = PowertoolsLambdaContext.Extract(eventArgs);

if (PowertoolsLambdaContext.Instance is not null)
var context = GetContext(eventArgs);
if (context is not null)
{
dimensions = new Dictionary<string, string>
{
{ "FunctionName", PowertoolsLambdaContext.Instance.FunctionName }
{ "FunctionName", context.FunctionName }
};
}

Expand All @@ -129,8 +125,6 @@ public void Before(
public void Exit()
{
_metricsInstance.Flush();
if (_clearLambdaContext)
PowertoolsLambdaContext.Clear();
}


Expand All @@ -142,6 +136,21 @@ internal static void ResetForTest()
_metricsInstance = null;
_isColdStart = true;
Metrics.ResetForTest();
PowertoolsLambdaContext.Clear();
}

/// <summary>
/// Gets the Lambda context
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private static ILambdaContext GetContext(AspectEventArgs args)
{
var index = Array.FindIndex(args.Method.GetParameters(), p => p.ParameterType == typeof(ILambdaContext));
if (index >= 0)
{
return (ILambdaContext)args.Args[index];
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using System.Text.Json.Serialization;

namespace AWS.Lambda.Powertools.Metrics;

/// <summary>
/// Enum MetricResolution
/// </summary>
[JsonConverter(typeof(MetricResolutionJsonConverter))]
public enum MetricResolution
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace AWS.Lambda.Powertools.Metrics;
#if NET8_0_OR_GREATER
[JsonConverter(typeof(JsonStringEnumConverter<MetricUnit>))]
#else
[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(JsonStringEnumConverter))]
#endif
public enum MetricUnit
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace AWS.Lambda.Powertools.Metrics;

/// <summary>
/// Class MetricResolutionJsonConverter.
/// Implements the <see cref="System.Text.Json.Serialization.JsonConverter{T}" />
/// </summary>
/// <seealso cref="System.Text.Json.Serialization.JsonConverter{T}" />
public class MetricResolutionJsonConverter : JsonConverter<MetricResolution>
{
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Utf8JsonReader" /> to read from.</param>
/// <param name="typeToConvert">The <see cref="T:System.Type" /> being converted.</param>
/// <param name="options">The <see cref="T:Utf8JsonSerializerOptions" /> being used.</param>
/// <returns>The object value.</returns>
public override MetricResolution Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var stringValue = reader.GetString();
if (int.TryParse(stringValue, out int value))
{
return (MetricResolution)value;
}
}
else if (reader.TokenType == JsonTokenType.Number)
{
return (MetricResolution)reader.GetInt32();
}

throw new JsonException();
}

/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="T:Utf8JsonWriter" /> to write to.</param>
/// <param name="value">The value to convert.</param>
/// <param name="options">The <see cref="T:Utf8JsonSerializerOptions" /> being used.</param>
public override void Write(Utf8JsonWriter writer, MetricResolution value, JsonSerializerOptions options)
{
writer.WriteNumberValue((int)value);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,14 @@ public void HandleWithLambdaContext(ILambdaContext context)
}

[Metrics(Namespace = "ns", Service = "svc")]
public void HandleWithLambdaContextAndMetrics(TestLambdaContext context)
public void HandleColdStartNoContext()
{
Metrics.AddMetric("MyMetric", 1);
}

[Metrics(Namespace = "ns", Service = "svc", CaptureColdStart = true)]
public void HandleWithParamAndLambdaContext(string input, ILambdaContext context)
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ public void When_LambdaContext_Should_Add_FunctioName_Dimension_CaptureColdStart
"\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\"],[\"Service\"]]}]}",
metricsOutput);
}

[Fact]
public void When_LambdaContext_And_Parameter_Should_Add_FunctioName_Dimension_CaptureColdStart()
{
// Arrange
var context = new TestLambdaContext
{
FunctionName = "My Function with context"
};

// Act
_handler.HandleWithParamAndLambdaContext("Hello",context);
var metricsOutput = _consoleOut.ToString();

// Assert
Assert.Contains(
"\"FunctionName\":\"My Function with context\"",
metricsOutput);

Assert.Contains(
"\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\"],[\"Service\"]]}]}",
metricsOutput);
}

[Fact]
public void When_No_LambdaContext_Should_Not_Add_FunctioName_Dimension_CaptureColdStart()
{
// Act
_handler.HandleColdStartNoContext();
var metricsOutput = _consoleOut.ToString();

// Assert
Assert.DoesNotContain(
"\"FunctionName\"",
metricsOutput);

Assert.Contains(
"\"Metrics\":[{\"Name\":\"MyMetric\",\"Unit\":\"None\"}],\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"svc\",\"MyMetric\":1}",
metricsOutput);
}

public void Dispose()
{
Expand Down
Loading

0 comments on commit a1ae03a

Please sign in to comment.