Skip to content

Commit b634e4e

Browse files
authored
Merge pull request #927 from aws-powertools/chore/ptenv-ua
chore: Add missing PTENV to user agent
2 parents 43bfa78 + e0a6259 commit b634e4e

File tree

8 files changed

+325
-528
lines changed

8 files changed

+325
-528
lines changed

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

Lines changed: 0 additions & 62 deletions
This file was deleted.
Lines changed: 71 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Text;
34

45
namespace AWS.Lambda.Powertools.Common;
@@ -11,6 +12,16 @@ public class PowertoolsEnvironment : IPowertoolsEnvironment
1112
/// </summary>
1213
private static IPowertoolsEnvironment _instance;
1314

15+
/// <summary>
16+
/// Cached runtime environment string
17+
/// </summary>
18+
private static readonly string CachedRuntimeEnvironment = $"PTENV/AWS_LAMBDA_DOTNET{Environment.Version.Major}";
19+
20+
/// <summary>
21+
/// Cache for parsed assembly names to avoid repeated string operations
22+
/// </summary>
23+
private static readonly ConcurrentDictionary<string, string> ParsedAssemblyNameCache = new();
24+
1425
/// <summary>
1526
/// Gets the instance.
1627
/// </summary>
@@ -32,41 +43,72 @@ public void SetEnvironmentVariable(string variableName, string value)
3243
/// <inheritdoc />
3344
public string GetAssemblyName<T>(T type)
3445
{
46+
if (type is Type typeObject)
47+
{
48+
return typeObject.Assembly.GetName().Name;
49+
}
50+
3551
return type.GetType().Assembly.GetName().Name;
3652
}
3753

3854
/// <inheritdoc />
3955
public string GetAssemblyVersion<T>(T type)
4056
{
41-
var version = type.GetType().Assembly.GetName().Version;
57+
Version version;
58+
59+
if (type is Type typeObject)
60+
{
61+
version = typeObject.Assembly.GetName().Version;
62+
}
63+
else
64+
{
65+
version = type.GetType().Assembly.GetName().Version;
66+
}
67+
4268
return version != null ? $"{version.Major}.{version.Minor}.{version.Build}" : string.Empty;
4369
}
4470

4571
/// <inheritdoc />
4672
public void SetExecutionEnvironment<T>(T type)
4773
{
4874
const string envName = Constants.AwsExecutionEnvironmentVariableName;
49-
var envValue = new StringBuilder();
5075
var currentEnvValue = GetEnvironmentVariable(envName);
5176
var assemblyName = ParseAssemblyName(GetAssemblyName(type));
5277

53-
// If there is an existing execution environment variable add the annotations package as a suffix.
54-
if (!string.IsNullOrEmpty(currentEnvValue))
78+
// Check for duplication early
79+
if (!string.IsNullOrEmpty(currentEnvValue) && currentEnvValue.Contains(assemblyName))
5580
{
56-
// Avoid duplication - should not happen since the calling Instances are Singletons - defensive purposes
57-
if (currentEnvValue.Contains(assemblyName))
58-
{
59-
return;
60-
}
61-
62-
envValue.Append($"{currentEnvValue} ");
81+
return;
6382
}
6483

6584
var assemblyVersion = GetAssemblyVersion(type);
85+
var newEntry = $"{assemblyName}/{assemblyVersion}";
86+
87+
string finalValue;
88+
89+
if (string.IsNullOrEmpty(currentEnvValue))
90+
{
91+
// First entry: "PT/Assembly/1.0.0 PTENV/AWS_LAMBDA_DOTNET8"
92+
finalValue = $"{newEntry} {CachedRuntimeEnvironment}";
93+
}
94+
else
95+
{
96+
// Check if PTENV already exists in one pass
97+
var containsPtenv = currentEnvValue.Contains("PTENV/");
98+
99+
if (containsPtenv)
100+
{
101+
// Just append the new entry: "existing PT/Assembly/1.0.0"
102+
finalValue = $"{currentEnvValue} {newEntry}";
103+
}
104+
else
105+
{
106+
// Append new entry + PTENV: "existing PT/Assembly/1.0.0 PTENV/AWS_LAMBDA_DOTNET8"
107+
finalValue = $"{currentEnvValue} {newEntry} {CachedRuntimeEnvironment}";
108+
}
109+
}
66110

67-
envValue.Append($"{assemblyName}/{assemblyVersion}");
68-
69-
SetEnvironmentVariable(envName, envValue.ToString());
111+
SetEnvironmentVariable(envName, finalValue);
70112
}
71113

72114
/// <summary>
@@ -75,18 +117,26 @@ public void SetExecutionEnvironment<T>(T type)
75117
/// </summary>
76118
/// <param name="assemblyName"></param>
77119
/// <returns></returns>
78-
private string ParseAssemblyName(string assemblyName)
120+
internal static string ParseAssemblyName(string assemblyName)
79121
{
122+
// Use cache to avoid repeated string operations
80123
try
81124
{
82-
var parsedName = assemblyName.Substring(assemblyName.LastIndexOf(".", StringComparison.Ordinal) + 1);
83-
return $"{Constants.FeatureContextIdentifier}/{parsedName}";
125+
return ParsedAssemblyNameCache.GetOrAdd(assemblyName, name =>
126+
{
127+
var lastDotIndex = name.LastIndexOf('.');
128+
if (lastDotIndex >= 0 && lastDotIndex < name.Length - 1)
129+
{
130+
var parsedName = name.Substring(lastDotIndex + 1);
131+
return $"{Constants.FeatureContextIdentifier}/{parsedName}";
132+
}
133+
134+
return $"{Constants.FeatureContextIdentifier}/{name}";
135+
});
84136
}
85137
catch
86138
{
87-
//NOOP
139+
return string.Empty;
88140
}
89-
90-
return $"{Constants.FeatureContextIdentifier}/{assemblyName}";
91141
}
92-
}
142+
}

0 commit comments

Comments
 (0)