-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Powertools User-Agent for Lambda execution environment #246
Changes from all commits
f613385
e620bef
65726aa
49f05e4
11c62bd
fef29e3
418c005
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
namespace AWS.Lambda.Powertools.Common; | ||
|
||
/// <summary> | ||
/// Interface for PowertoolsEnvironment | ||
/// </summary> | ||
public interface IPowertoolsEnvironment | ||
{ | ||
/// <summary> | ||
/// Get environment variable by variable name | ||
/// </summary> | ||
/// <param name="variableName"></param> | ||
/// <returns>Environment variable</returns> | ||
string GetEnvironmentVariable(string variableName); | ||
|
||
/// <summary> | ||
/// Set environment variable | ||
/// </summary> | ||
/// <param name="variableName"></param> | ||
/// <param name="value">Setting this to null will remove environment variable with that name</param> | ||
void SetEnvironmentVariable(string variableName, string value); | ||
|
||
/// <summary> | ||
/// Get the calling Type Assembly Name | ||
/// </summary> | ||
/// <param name="type"></param> | ||
/// <typeparam name="T"></typeparam> | ||
/// <returns>Assembly Name</returns> | ||
string GetAssemblyName<T>(T type); | ||
|
||
/// <summary> | ||
/// Get the calling Type Assembly Version | ||
/// </summary> | ||
/// <param name="type"></param> | ||
/// <typeparam name="T"></typeparam> | ||
/// <returns>Assembly Version in the Major.Minor.Build format</returns> | ||
string GetAssemblyVersion<T>(T type); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
|
||
namespace AWS.Lambda.Powertools.Common; | ||
|
||
/// <inheritdoc /> | ||
public class PowertoolsEnvironment : IPowertoolsEnvironment | ||
{ | ||
/// <summary> | ||
/// The instance | ||
/// </summary> | ||
private static IPowertoolsEnvironment _instance; | ||
|
||
/// <summary> | ||
/// Gets the instance. | ||
/// </summary> | ||
/// <value>The instance.</value> | ||
public static IPowertoolsEnvironment Instance => _instance ??= new PowertoolsEnvironment(); | ||
|
||
/// <inheritdoc /> | ||
public string GetEnvironmentVariable(string variableName) | ||
{ | ||
return Environment.GetEnvironmentVariable(variableName); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public void SetEnvironmentVariable(string variableName, string value) | ||
{ | ||
Environment.SetEnvironmentVariable(variableName, value); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string GetAssemblyName<T>(T type) | ||
{ | ||
return type.GetType().Assembly.GetName().Name; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string GetAssemblyVersion<T>(T type) | ||
{ | ||
var version = type.GetType().Assembly.GetName().Version; | ||
return version != null ? $"{version.Major}.{version.Minor}.{version.Build}" : string.Empty; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
*/ | ||
|
||
using System; | ||
using System.Text; | ||
|
||
namespace AWS.Lambda.Powertools.Common; | ||
|
||
|
@@ -24,6 +25,8 @@ namespace AWS.Lambda.Powertools.Common; | |
/// <seealso cref="ISystemWrapper" /> | ||
public class SystemWrapper : ISystemWrapper | ||
{ | ||
private static IPowertoolsEnvironment _powertoolsEnvironment; | ||
|
||
/// <summary> | ||
/// The instance | ||
/// </summary> | ||
|
@@ -32,15 +35,17 @@ public class SystemWrapper : ISystemWrapper | |
/// <summary> | ||
/// Prevents a default instance of the <see cref="SystemWrapper" /> class from being created. | ||
/// </summary> | ||
private SystemWrapper() | ||
public SystemWrapper(IPowertoolsEnvironment powertoolsEnvironment) | ||
{ | ||
_powertoolsEnvironment = powertoolsEnvironment; | ||
_instance ??= this; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the instance. | ||
/// </summary> | ||
/// <value>The instance.</value> | ||
public static ISystemWrapper Instance => _instance ??= new SystemWrapper(); | ||
public static ISystemWrapper Instance => _instance ??= new SystemWrapper(PowertoolsEnvironment.Instance); | ||
|
||
/// <summary> | ||
/// Gets the environment variable. | ||
|
@@ -49,7 +54,7 @@ private SystemWrapper() | |
/// <returns>System.String.</returns> | ||
public string GetEnvironmentVariable(string variable) | ||
{ | ||
return Environment.GetEnvironmentVariable(variable); | ||
return _powertoolsEnvironment.GetEnvironmentVariable(variable); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -78,4 +83,57 @@ public double GetRandom() | |
{ | ||
return new Random().NextDouble(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public void SetEnvironmentVariable(string variable, string value) | ||
{ | ||
_powertoolsEnvironment.SetEnvironmentVariable(variable, value); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public void SetExecutionEnvironment<T>(T type) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know the whole system so it might already being doing this but make sure this is only called once per power tools assembly. These assembly look up calls are can be costly and we don't want to it for every request. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the feedback @normj . The implementation prevents multiple instances of SystemWrapper to be created. The instances that create systemwrapper are singletons. The constructors are called once for the lambda lifetime. |
||
{ | ||
const string envName = Constants.AwsExecutionEnvironmentVariableName; | ||
var envValue = new StringBuilder(); | ||
var currentEnvValue = GetEnvironmentVariable(envName); | ||
var assemblyName = ParseAssemblyName(_powertoolsEnvironment.GetAssemblyName(type)); | ||
|
||
// If there is an existing execution environment variable add the annotations package as a suffix. | ||
if(!string.IsNullOrEmpty(currentEnvValue)) | ||
{ | ||
// Avoid duplication - should not happen since the calling Instances are Singletons - defensive purposes | ||
if (currentEnvValue.Contains(assemblyName)) | ||
{ | ||
return; | ||
} | ||
|
||
envValue.Append($"{currentEnvValue} "); | ||
} | ||
|
||
var assemblyVersion = _powertoolsEnvironment.GetAssemblyVersion(type); | ||
|
||
envValue.Append($"{assemblyName}/{assemblyVersion}"); | ||
|
||
SetEnvironmentVariable(envName, envValue.ToString()); | ||
} | ||
|
||
/// <summary> | ||
/// Parsing the name to conform with the required naming convention for the UserAgent header (PTFeature/Name/Version) | ||
/// Fallback to Assembly Name on exception | ||
/// </summary> | ||
/// <param name="assemblyName"></param> | ||
/// <returns></returns> | ||
private string ParseAssemblyName(string assemblyName) | ||
{ | ||
try | ||
{ | ||
var parsedName = assemblyName.Substring(assemblyName.LastIndexOf(".", StringComparison.Ordinal)+1); | ||
return $"{Constants.FeatureContextIdentifier}/{parsedName}"; | ||
} | ||
catch | ||
{ | ||
//NOOP | ||
} | ||
return $"{Constants.FeatureContextIdentifier}/{assemblyName}"; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one calls
SystemWrapper. SetExecutionEnvironment
and the system Wrapper I believe calls PowertoolsEnvironment, I believe there are too many layers of abstractions.