Skip to content

Commit 5cd8cae

Browse files
authored
Merge branch 'develop' into dependabot/github_actions/actions/setup-node-4.3.0
2 parents 4def3f9 + 58a6296 commit 5cd8cae

File tree

25 files changed

+521
-87
lines changed

25 files changed

+521
-87
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2525

2626
- name: Setup .NET SDK
27-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
27+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
2828
with:
2929
dotnet-version: |
3030
6.0.x

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
steps:
6060
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
6161
- name: Setup .NET 8.0
62-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
62+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
6363
with:
6464
dotnet-version: '8.x'
6565

.github/workflows/e2e-tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
mask-aws-account-id: true
4242

4343
- name: Set up .NET
44-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
44+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
4545
with:
4646
dotnet-version: '8.x'
4747

@@ -85,7 +85,7 @@ jobs:
8585
mask-aws-account-id: true
8686

8787
- name: Set up .NET
88-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
88+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
8989
with:
9090
dotnet-version: '8.x'
9191

@@ -126,7 +126,7 @@ jobs:
126126
mask-aws-account-id: true
127127

128128
- name: Set up .NET
129-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
129+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
130130
with:
131131
dotnet-version: '8.x'
132132

.github/workflows/examples-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2525

2626
- name: Setup .NET SDK
27-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
27+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
2828
with:
2929
dotnet-version: |
3030
6.0.x

.github/workflows/publish-artifacts-examples-tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3131

3232
- name: Setup .NET
33-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
33+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
3434
with:
3535
dotnet-version: |
3636
6.0.x
@@ -61,7 +61,7 @@ jobs:
6161
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
6262

6363
- name: Set up .NET
64-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
64+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
6565
with:
6666
dotnet-version: |
6767
6.0.x
@@ -120,7 +120,7 @@ jobs:
120120
path: ./packages/
121121

122122
- name: Setup .NET
123-
uses: actions/setup-dotnet@3951f0dfe7a07e2313ec93c75700083e2005cbab # 4.3.0
123+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # 4.3.1
124124
with:
125125
dotnet-version: |
126126
6.0.x

libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ namespace AWS.Lambda.Powertools.Common;
2020
/// </summary>
2121
internal static class Constants
2222
{
23+
/// <summary>
24+
/// Constant for AWS_LAMBDA_INITIALIZATION_TYPE environment variable
25+
/// This is used to determine if the Lambda function is running in provisioned concurrency mode
26+
/// or not. If the value is "provisioned-concurrency", it indicates that the function is running in provisioned
27+
/// concurrency mode. Otherwise, it is running in standard mode.
28+
/// </summary>
29+
internal const string AWSInitializationTypeEnv = "AWS_LAMBDA_INITIALIZATION_TYPE";
30+
2331
/// <summary>
2432
/// Constant for POWERTOOLS_SERVICE_NAME environment variable
2533
/// </summary>

libraries/src/AWS.Lambda.Powertools.Common/Core/IPowertoolsConfigurations.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,15 @@ public interface IPowertoolsConfigurations
167167
/// Gets a value indicating whether Metrics are disabled.
168168
/// </summary>
169169
bool MetricsDisabled { get; }
170+
171+
/// <summary>
172+
/// Indicates if the current execution is a cold start.
173+
/// </summary>
174+
bool IsColdStart { get; }
175+
176+
/// <summary>
177+
/// AWS Lambda initialization type.
178+
/// This is set to "on-demand" for on-demand Lambda functions and "provisioned-concurrency" for provisioned concurrency.
179+
/// </summary>
180+
string AwsInitializationType { get; }
170181
}

libraries/src/AWS.Lambda.Powertools.Common/Core/ISystemWrapper.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,4 @@ public interface ISystemWrapper
5959
/// </summary>
6060
/// <param name="type"></param>
6161
void SetExecutionEnvironment<T>(T type);
62-
63-
/// <summary>
64-
/// Sets console output
65-
/// Useful for testing and checking the console output
66-
/// <code>
67-
/// var consoleOut = new StringWriter();
68-
/// SystemWrapper.Instance.SetOut(consoleOut);
69-
/// </code>
70-
/// </summary>
71-
/// <param name="writeTo">The TextWriter instance where to write to</param>
72-
void SetOut(TextWriter writeTo);
7362
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Threading;
3+
4+
namespace AWS.Lambda.Powertools.Common.Core;
5+
6+
/// <summary>
7+
/// Tracks Lambda lifecycle state including cold starts
8+
/// </summary>
9+
internal static class LambdaLifecycleTracker
10+
{
11+
// Static flag that's true only for the first Lambda container initialization
12+
private static bool _isFirstContainer = true;
13+
14+
// Store the cold start state for the current invocation
15+
private static readonly AsyncLocal<bool?> CurrentInvocationColdStart = new AsyncLocal<bool?>();
16+
17+
private static string _lambdaInitType;
18+
private static string LambdaInitType => _lambdaInitType ?? Environment.GetEnvironmentVariable(Constants.AWSInitializationTypeEnv);
19+
20+
/// <summary>
21+
/// Returns true if the current Lambda invocation is a cold start
22+
/// </summary>
23+
public static bool IsColdStart
24+
{
25+
get
26+
{
27+
if(LambdaInitType == "provisioned-concurrency")
28+
{
29+
// If the Lambda is provisioned concurrency, it is not a cold start
30+
return false;
31+
}
32+
33+
// Initialize the cold start state for this invocation if not already set
34+
if (!CurrentInvocationColdStart.Value.HasValue)
35+
{
36+
// Capture the container's cold start state for this entire invocation
37+
CurrentInvocationColdStart.Value = _isFirstContainer;
38+
39+
// After detecting the first invocation, mark future ones as warm
40+
if (_isFirstContainer)
41+
{
42+
_isFirstContainer = false;
43+
}
44+
}
45+
46+
// Return the cold start state for this invocation (cannot change during the invocation)
47+
return CurrentInvocationColdStart.Value ?? false;
48+
}
49+
}
50+
51+
52+
53+
/// <summary>
54+
/// Resets the cold start state for testing
55+
/// </summary>
56+
/// <param name="resetContainer">Whether to reset the container state (defaults to true)</param>
57+
internal static void Reset(bool resetContainer = true)
58+
{
59+
if (resetContainer)
60+
{
61+
_isFirstContainer = true;
62+
}
63+
CurrentInvocationColdStart.Value = null;
64+
_lambdaInitType = null;
65+
}
66+
}

libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System.Globalization;
17+
using AWS.Lambda.Powertools.Common.Core;
1718

1819
namespace AWS.Lambda.Powertools.Common;
1920

@@ -222,4 +223,11 @@ public void SetExecutionEnvironment<T>(T type)
222223

223224
/// <inheritdoc />
224225
public bool MetricsDisabled => GetEnvironmentVariableOrDefault(Constants.PowertoolsMetricsDisabledEnv, false);
226+
227+
/// <inheritdoc />
228+
public bool IsColdStart => LambdaLifecycleTracker.IsColdStart;
229+
230+
/// <inheritdoc />
231+
public string AwsInitializationType =>
232+
GetEnvironmentVariable(Constants.AWSInitializationTypeEnv);
225233
}

libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ namespace AWS.Lambda.Powertools.Common;
2727
public class SystemWrapper : ISystemWrapper
2828
{
2929
private static IPowertoolsEnvironment _powertoolsEnvironment;
30+
private static bool _inTestMode = false;
31+
private static TextWriter _testOutputStream;
32+
private static bool _outputResetPerformed = false;
3033

3134
/// <summary>
3235
/// The instance
@@ -41,13 +44,11 @@ public SystemWrapper(IPowertoolsEnvironment powertoolsEnvironment)
4144
_powertoolsEnvironment = powertoolsEnvironment;
4245
_instance ??= this;
4346

44-
// Clear AWS SDK Console injected parameters StdOut and StdErr
45-
var standardOutput = new StreamWriter(Console.OpenStandardOutput());
46-
standardOutput.AutoFlush = true;
47-
Console.SetOut(standardOutput);
48-
var errordOutput = new StreamWriter(Console.OpenStandardError());
49-
errordOutput.AutoFlush = true;
50-
Console.SetError(errordOutput);
47+
if (!_inTestMode)
48+
{
49+
// Clear AWS SDK Console injected parameters in production only
50+
ResetConsoleOutput();
51+
}
5152
}
5253

5354
/// <summary>
@@ -72,7 +73,15 @@ public string GetEnvironmentVariable(string variable)
7273
/// <param name="value">The value.</param>
7374
public void Log(string value)
7475
{
75-
Console.Write(value);
76+
if (_inTestMode && _testOutputStream != null)
77+
{
78+
_testOutputStream.Write(value);
79+
}
80+
else
81+
{
82+
EnsureConsoleOutputOnce();
83+
Console.Write(value);
84+
}
7685
}
7786

7887
/// <summary>
@@ -81,7 +90,15 @@ public void Log(string value)
8190
/// <param name="value">The value.</param>
8291
public void LogLine(string value)
8392
{
84-
Console.WriteLine(value);
93+
if (_inTestMode && _testOutputStream != null)
94+
{
95+
_testOutputStream.WriteLine(value);
96+
}
97+
else
98+
{
99+
EnsureConsoleOutputOnce();
100+
Console.WriteLine(value);
101+
}
85102
}
86103

87104
/// <summary>
@@ -126,9 +143,20 @@ public void SetExecutionEnvironment<T>(T type)
126143
SetEnvironmentVariable(envName, envValue.ToString());
127144
}
128145

129-
/// <inheritdoc />
130-
public void SetOut(TextWriter writeTo)
146+
/// <summary>
147+
/// Sets console output
148+
/// Useful for testing and checking the console output
149+
/// <code>
150+
/// var consoleOut = new StringWriter();
151+
/// SystemWrapper.Instance.SetOut(consoleOut);
152+
/// </code>
153+
/// </summary>
154+
/// <param name="writeTo">The TextWriter instance where to write to</param>
155+
156+
public static void SetOut(TextWriter writeTo)
131157
{
158+
_testOutputStream = writeTo;
159+
_inTestMode = true;
132160
Console.SetOut(writeTo);
133161
}
134162

@@ -152,4 +180,33 @@ private string ParseAssemblyName(string assemblyName)
152180

153181
return $"{Constants.FeatureContextIdentifier}/{assemblyName}";
154182
}
183+
184+
private static void EnsureConsoleOutputOnce()
185+
{
186+
if (_outputResetPerformed) return;
187+
ResetConsoleOutput();
188+
_outputResetPerformed = true;
189+
}
190+
191+
private static void ResetConsoleOutput()
192+
{
193+
var standardOutput = new StreamWriter(Console.OpenStandardOutput());
194+
standardOutput.AutoFlush = true;
195+
Console.SetOut(standardOutput);
196+
var errorOutput = new StreamWriter(Console.OpenStandardError());
197+
errorOutput.AutoFlush = true;
198+
Console.SetError(errorOutput);
199+
}
200+
201+
public static void ClearOutputResetFlag()
202+
{
203+
_outputResetPerformed = false;
204+
}
205+
206+
// For test cleanup
207+
internal static void ResetTestMode()
208+
{
209+
_inTestMode = false;
210+
_testOutputStream = null;
211+
}
155212
}

libraries/src/AWS.Lambda.Powertools.Common/InternalsVisibleTo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Logging")]
1919
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Metrics")]
20+
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Tracing")]
2021
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Idempotency")]
2122
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Common.Tests")]
2223
[assembly: InternalsVisibleTo("AWS.Lambda.Powertools.Tracing.Tests")]

libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspect.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using System.Text.Json;
2222
using AspectInjector.Broker;
2323
using AWS.Lambda.Powertools.Common;
24+
using AWS.Lambda.Powertools.Common.Core;
2425
using AWS.Lambda.Powertools.Logging.Serializers;
2526
using Microsoft.Extensions.Logging;
2627

@@ -34,11 +35,6 @@ namespace AWS.Lambda.Powertools.Logging.Internal;
3435
[Aspect(Scope.Global, Factory = typeof(LoggingAspectFactory))]
3536
public class LoggingAspect
3637
{
37-
/// <summary>
38-
/// The is cold start
39-
/// </summary>
40-
private bool _isColdStart = true;
41-
4238
/// <summary>
4339
/// The initialize context
4440
/// </summary>
@@ -143,9 +139,8 @@ public void OnEntry(
143139
if (!_initializeContext)
144140
return;
145141

146-
Logger.AppendKey(LoggingConstants.KeyColdStart, _isColdStart);
142+
Logger.AppendKey(LoggingConstants.KeyColdStart, LambdaLifecycleTracker.IsColdStart);
147143

148-
_isColdStart = false;
149144
_initializeContext = false;
150145
_isContextInitialized = true;
151146

0 commit comments

Comments
 (0)