Skip to content

Commit 0915f13

Browse files
authored
UserAgentValue arch board feedback (Azure#27364)
* API for setting a dynamic UserAgent string
1 parent 26fd2e3 commit 0915f13

13 files changed

+147
-91
lines changed

sdk/core/Azure.Core/api/Azure.Core.net461.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,14 @@ public StatusCodeClassifier(System.ReadOnlySpan<ushort> successStatusCodes) { }
652652
public override bool IsErrorResponse(Azure.Core.HttpMessage message) { throw null; }
653653
}
654654
public delegate System.Threading.Tasks.Task SyncAsyncEventHandler<T>(T e) where T : Azure.SyncAsyncEventArgs;
655+
public partial class TelemetryDetails
656+
{
657+
public TelemetryDetails(System.Reflection.Assembly assembly, string? applicationId = null) { }
658+
public string? ApplicationId { get { throw null; } }
659+
public System.Reflection.Assembly Assembly { get { throw null; } }
660+
public void Apply(Azure.Core.HttpMessage message) { }
661+
public override string ToString() { throw null; }
662+
}
655663
public abstract partial class TokenCredential
656664
{
657665
protected TokenCredential() { }
@@ -902,10 +910,6 @@ public void Dispose() { }
902910
public override void Process(Azure.Core.HttpMessage message) { }
903911
public override System.Threading.Tasks.ValueTask ProcessAsync(Azure.Core.HttpMessage message) { throw null; }
904912
}
905-
public static partial class HttpMessageExtensions
906-
{
907-
public static void SetUserAgentString(this Azure.Core.HttpMessage message, Azure.Core.Pipeline.UserAgentValue userAgentValue) { }
908-
}
909913
public partial class HttpPipeline
910914
{
911915
public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.Core.Pipeline.HttpPipelinePolicy[]? policies = null, Azure.Core.ResponseClassifier? responseClassifier = null) { }
@@ -962,12 +966,6 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce
962966
public System.Security.Cryptography.X509Certificates.X509Chain? CertificateAuthorityChain { get { throw null; } }
963967
public System.Net.Security.SslPolicyErrors SslPolicyErrors { get { throw null; } }
964968
}
965-
public partial class UserAgentValue
966-
{
967-
public UserAgentValue(System.Type type, string? applicationId = null) { }
968-
public static Azure.Core.Pipeline.UserAgentValue FromType<T>(string? applicationId = null) { throw null; }
969-
public override string ToString() { throw null; }
970-
}
971969
}
972970
namespace Azure.Core.Serialization
973971
{

sdk/core/Azure.Core/api/Azure.Core.net5.0.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,14 @@ public StatusCodeClassifier(System.ReadOnlySpan<ushort> successStatusCodes) { }
652652
public override bool IsErrorResponse(Azure.Core.HttpMessage message) { throw null; }
653653
}
654654
public delegate System.Threading.Tasks.Task SyncAsyncEventHandler<T>(T e) where T : Azure.SyncAsyncEventArgs;
655+
public partial class TelemetryDetails
656+
{
657+
public TelemetryDetails(System.Reflection.Assembly assembly, string? applicationId = null) { }
658+
public string? ApplicationId { get { throw null; } }
659+
public System.Reflection.Assembly Assembly { get { throw null; } }
660+
public void Apply(Azure.Core.HttpMessage message) { }
661+
public override string ToString() { throw null; }
662+
}
655663
public abstract partial class TokenCredential
656664
{
657665
protected TokenCredential() { }
@@ -902,10 +910,6 @@ public void Dispose() { }
902910
public override void Process(Azure.Core.HttpMessage message) { }
903911
public override System.Threading.Tasks.ValueTask ProcessAsync(Azure.Core.HttpMessage message) { throw null; }
904912
}
905-
public static partial class HttpMessageExtensions
906-
{
907-
public static void SetUserAgentString(this Azure.Core.HttpMessage message, Azure.Core.Pipeline.UserAgentValue userAgentValue) { }
908-
}
909913
public partial class HttpPipeline
910914
{
911915
public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.Core.Pipeline.HttpPipelinePolicy[]? policies = null, Azure.Core.ResponseClassifier? responseClassifier = null) { }
@@ -962,12 +966,6 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce
962966
public System.Security.Cryptography.X509Certificates.X509Chain? CertificateAuthorityChain { get { throw null; } }
963967
public System.Net.Security.SslPolicyErrors SslPolicyErrors { get { throw null; } }
964968
}
965-
public partial class UserAgentValue
966-
{
967-
public UserAgentValue(System.Type type, string? applicationId = null) { }
968-
public static Azure.Core.Pipeline.UserAgentValue FromType<T>(string? applicationId = null) { throw null; }
969-
public override string ToString() { throw null; }
970-
}
971969
}
972970
namespace Azure.Core.Serialization
973971
{

sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,14 @@ public StatusCodeClassifier(System.ReadOnlySpan<ushort> successStatusCodes) { }
652652
public override bool IsErrorResponse(Azure.Core.HttpMessage message) { throw null; }
653653
}
654654
public delegate System.Threading.Tasks.Task SyncAsyncEventHandler<T>(T e) where T : Azure.SyncAsyncEventArgs;
655+
public partial class TelemetryDetails
656+
{
657+
public TelemetryDetails(System.Reflection.Assembly assembly, string? applicationId = null) { }
658+
public string? ApplicationId { get { throw null; } }
659+
public System.Reflection.Assembly Assembly { get { throw null; } }
660+
public void Apply(Azure.Core.HttpMessage message) { }
661+
public override string ToString() { throw null; }
662+
}
655663
public abstract partial class TokenCredential
656664
{
657665
protected TokenCredential() { }
@@ -902,10 +910,6 @@ public void Dispose() { }
902910
public override void Process(Azure.Core.HttpMessage message) { }
903911
public override System.Threading.Tasks.ValueTask ProcessAsync(Azure.Core.HttpMessage message) { throw null; }
904912
}
905-
public static partial class HttpMessageExtensions
906-
{
907-
public static void SetUserAgentString(this Azure.Core.HttpMessage message, Azure.Core.Pipeline.UserAgentValue userAgentValue) { }
908-
}
909913
public partial class HttpPipeline
910914
{
911915
public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.Core.Pipeline.HttpPipelinePolicy[]? policies = null, Azure.Core.ResponseClassifier? responseClassifier = null) { }
@@ -962,12 +966,6 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce
962966
public System.Security.Cryptography.X509Certificates.X509Chain? CertificateAuthorityChain { get { throw null; } }
963967
public System.Net.Security.SslPolicyErrors SslPolicyErrors { get { throw null; } }
964968
}
965-
public partial class UserAgentValue
966-
{
967-
public UserAgentValue(System.Type type, string? applicationId = null) { }
968-
public static Azure.Core.Pipeline.UserAgentValue FromType<T>(string? applicationId = null) { throw null; }
969-
public override string ToString() { throw null; }
970-
}
971969
}
972970
namespace Azure.Core.Serialization
973971
{

sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,14 @@ public StatusCodeClassifier(System.ReadOnlySpan<ushort> successStatusCodes) { }
652652
public override bool IsErrorResponse(Azure.Core.HttpMessage message) { throw null; }
653653
}
654654
public delegate System.Threading.Tasks.Task SyncAsyncEventHandler<T>(T e) where T : Azure.SyncAsyncEventArgs;
655+
public partial class TelemetryDetails
656+
{
657+
public TelemetryDetails(System.Reflection.Assembly assembly, string? applicationId = null) { }
658+
public string? ApplicationId { get { throw null; } }
659+
public System.Reflection.Assembly Assembly { get { throw null; } }
660+
public void Apply(Azure.Core.HttpMessage message) { }
661+
public override string ToString() { throw null; }
662+
}
655663
public abstract partial class TokenCredential
656664
{
657665
protected TokenCredential() { }
@@ -902,10 +910,6 @@ public void Dispose() { }
902910
public override void Process(Azure.Core.HttpMessage message) { }
903911
public override System.Threading.Tasks.ValueTask ProcessAsync(Azure.Core.HttpMessage message) { throw null; }
904912
}
905-
public static partial class HttpMessageExtensions
906-
{
907-
public static void SetUserAgentString(this Azure.Core.HttpMessage message, Azure.Core.Pipeline.UserAgentValue userAgentValue) { }
908-
}
909913
public partial class HttpPipeline
910914
{
911915
public HttpPipeline(Azure.Core.Pipeline.HttpPipelineTransport transport, Azure.Core.Pipeline.HttpPipelinePolicy[]? policies = null, Azure.Core.ResponseClassifier? responseClassifier = null) { }
@@ -962,12 +966,6 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce
962966
public System.Security.Cryptography.X509Certificates.X509Chain? CertificateAuthorityChain { get { throw null; } }
963967
public System.Net.Security.SslPolicyErrors SslPolicyErrors { get { throw null; } }
964968
}
965-
public partial class UserAgentValue
966-
{
967-
public UserAgentValue(System.Type type, string? applicationId = null) { }
968-
public static Azure.Core.Pipeline.UserAgentValue FromType<T>(string? applicationId = null) { throw null; }
969-
public override string ToString() { throw null; }
970-
}
971969
}
972970
namespace Azure.Core.Serialization
973971
{

sdk/core/Azure.Core/src/HttpMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public sealed class HttpMessage : IDisposable
1717
/// <summary>
1818
/// This dictionary is keyed with <c>Type</c> for a couple of reasons. Primarily, it allows values to be stored such that even if the accessor methods
1919
/// become public, storing values keyed by internal types make them inaccessible to other assemblies. This protects internal values from being overwritten
20-
/// by external code. See the <see cref="UserAgentValue"/> and <see cref="UserAgentValueKey"/> types for an example of this usage.
20+
/// by external code. See the <see cref="TelemetryDetails"/> and <see cref="UserAgentValueKey"/> types for an example of this usage.
2121
/// </summary>
2222
private Dictionary<Type, object>? _typeProperties;
2323

sdk/core/Azure.Core/src/Pipeline/HttpMessageExtensions.cs

Lines changed: 0 additions & 22 deletions
This file was deleted.

sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ void AddNonNullPolicies(HttpPipelinePolicy[] policiesToAdd)
187187
// internal for testing
188188
internal static TelemetryPolicy CreateTelemetryPolicy(ClientOptions options)
189189
{
190-
var userAgentValue = new UserAgentValue(options.GetType(), options.Diagnostics.ApplicationId);
190+
var type = options.GetType();
191+
var userAgentValue = new TelemetryDetails(type.Assembly, options.Diagnostics.ApplicationId);
191192
return new TelemetryPolicy(userAgentValue);
192193
}
193194
}

sdk/core/Azure.Core/src/Pipeline/Internal/TelemetryPolicy.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ internal class TelemetryPolicy : HttpPipelineSynchronousPolicy
77
{
88
private readonly string _defaultHeader;
99

10-
public TelemetryPolicy(UserAgentValue userAgentValue)
10+
public TelemetryPolicy(TelemetryDetails telemetryDetails)
1111
{
12-
_defaultHeader = userAgentValue.ToString();
12+
_defaultHeader = telemetryDetails.ToString();
1313
}
1414

1515
public override void OnSendingRequest(HttpMessage message)

sdk/core/Azure.Core/src/Pipeline/Internal/UserAgentValueKey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace Azure.Core.Pipeline
55
{
66
/// <summary>
7-
/// Class that serves as the key for <see cref="UserAgentValue"/> UserAgent strings on <see cref="HttpMessage"/>.
7+
/// Class that serves as the key for <see cref="TelemetryDetails"/> UserAgent strings on <see cref="HttpMessage"/>.
88
/// </summary>
99
internal class UserAgentValueKey { }
1010
}

sdk/core/Azure.Core/src/Pipeline/UserAgentValue.cs renamed to sdk/core/Azure.Core/src/TelemetryDetails.cs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,60 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.ComponentModel;
56
using System.Reflection;
67
using System.Runtime.InteropServices;
8+
using Azure.Core.Pipeline;
79

8-
namespace Azure.Core.Pipeline
10+
namespace Azure.Core
911
{
1012
/// <summary>
11-
/// Information about the package to be included in UserAgent telemetry
13+
/// Details about the package to be included in UserAgent telemetry
1214
/// </summary>
13-
public class UserAgentValue
15+
public class TelemetryDetails
1416
{
15-
private string _userAgent;
17+
private const int MaxApplicationIdLength = 24;
18+
private readonly string _userAgent;
1619

1720
/// <summary>
18-
/// Initialize an instance of <see cref="UserAgentValue"/> by extracting the name and version information from the <see cref="Assembly"/> associated with the <paramref name="type"/>.
21+
/// The package type represented by this <see cref="TelemetryDetails"/> instance.
1922
/// </summary>
20-
/// <param name="type">The <see cref="Type"/> used to generate the package name and version information for the <see cref="UserAgentValue"/> value.</param>
21-
/// <param name="applicationId">An optional value to be prepended to the <see cref="UserAgentValue"/>.
23+
public Assembly Assembly { get; }
24+
25+
/// <summary>
26+
/// The value of the applicationId used to initialize this <see cref="TelemetryDetails"/> instance.
27+
/// </summary>
28+
public string? ApplicationId { get; }
29+
30+
/// <summary>
31+
/// Initialize an instance of <see cref="TelemetryDetails"/> by extracting the name and version information from the <see cref="System.Reflection.Assembly"/> associated with the <paramref name="assembly"/>.
32+
/// </summary>
33+
/// <param name="assembly">The <see cref="System.Reflection.Assembly"/> used to generate the package name and version information for the <see cref="TelemetryDetails"/> value.</param>
34+
/// <param name="applicationId">An optional value to be prepended to the <see cref="TelemetryDetails"/>.
2235
/// This value overrides the behavior of the <see cref="DiagnosticsOptions.ApplicationId"/> property for the <see cref="HttpMessage"/> it is applied to.</param>
23-
public UserAgentValue(Type type, string? applicationId = null)
36+
public TelemetryDetails(Assembly assembly, string? applicationId = null)
2437
{
25-
var assembly = Assembly.GetAssembly(type);
26-
if (assembly == null) throw new ArgumentException($"The type parameter {type.FullName} does not have a valid Assembly");
38+
Argument.AssertNotNull(assembly, nameof(assembly));
39+
if ( applicationId?.Length > MaxApplicationIdLength)
40+
{
41+
throw new ArgumentOutOfRangeException(nameof(applicationId), $"{nameof(applicationId)} must be shorter than {MaxApplicationIdLength + 1} characters");
42+
}
43+
44+
Assembly = assembly;
45+
ApplicationId = applicationId;
2746
_userAgent = GenerateUserAgentString(assembly, applicationId);
2847
}
2948

3049
/// <summary>
31-
/// Creates an instance of a <see cref="UserAgentValue"/> based on the Type provided.
50+
/// Sets the package name and version portion of the UserAgent telemetry value for the context of the <paramref name="message"/>
51+
/// Note: If <see cref="DiagnosticsOptions.IsTelemetryEnabled"/> is false, this value is never used.
3252
/// </summary>
33-
/// <param name="applicationId"></param>
34-
/// <typeparam name="T">The type contained by the Assembly used to generate package name and version information.</typeparam>
35-
/// <returns></returns>
36-
public static UserAgentValue FromType<T>(string? applicationId = null)
53+
/// <param name="message">The <see cref="HttpMessage"/> that will use this <see cref="TelemetryDetails"/>.</param>
54+
public void Apply(HttpMessage message)
3755
{
38-
return new UserAgentValue(typeof(T), applicationId);
56+
message.SetInternalProperty(typeof(UserAgentValueKey), ToString());
3957
}
4058

41-
/// <summary>
42-
/// Returns a formatted UserAgent string
43-
/// </summary>
44-
public override string ToString() => _userAgent;
45-
4659
internal static string GenerateUserAgentString(Assembly clientAssembly, string? applicationId = null)
4760
{
4861
const string PackagePrefix = "Azure.";
@@ -73,5 +86,10 @@ internal static string GenerateUserAgentString(Assembly clientAssembly, string?
7386
? $"{applicationId} azsdk-net-{assemblyName}/{version} {platformInformation}"
7487
: $"azsdk-net-{assemblyName}/{version} {platformInformation}";
7588
}
89+
90+
/// <summary>
91+
/// The properly formatted UserAgent string based on this <see cref="TelemetryDetails"/> instance.
92+
/// </summary>
93+
public override string ToString() => _userAgent;
7694
}
7795
}

0 commit comments

Comments
 (0)