Skip to content
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

Adding User Agent suffix when Bulk mode is on #922

Merged
merged 12 commits into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public class CosmosClientOptions
/// </summary>
public CosmosClientOptions()
{
this.UserAgentContainer = new Cosmos.UserAgentContainer();
this.GatewayModeMaxConnectionLimit = ConnectionPolicy.Default.MaxConnectionLimit;
this.RequestTimeout = ConnectionPolicy.Default.RequestTimeout;
this.ConnectionMode = CosmosClientOptions.DefaultConnectionMode;
Expand All @@ -83,11 +82,7 @@ public CosmosClientOptions()
/// <remarks>
/// Setting this property after sending any request won't have any effect.
/// </remarks>
public string ApplicationName
{
get => this.UserAgentContainer.Suffix;
set => this.UserAgentContainer.Suffix = value;
}
public string ApplicationName { get; set; }

/// <summary>
/// Get or set the preferred geo-replicated region to be used for Azure Cosmos DB service interaction.
Expand Down Expand Up @@ -398,8 +393,6 @@ internal Protocol ConnectionProtocol
}
}

internal UserAgentContainer UserAgentContainer { get; private set; }

/// <summary>
/// The event handler to be invoked before the request is sent.
/// </summary>
Expand Down Expand Up @@ -509,13 +502,15 @@ internal ConnectionPolicy GetConnectionPolicy()
{
this.ValidateDirectTCPSettings();
this.ValidateLimitToEndpointSettings();
UserAgentContainer userAgent = this.BuildUserAgentContainer();

ConnectionPolicy connectionPolicy = new ConnectionPolicy()
{
MaxConnectionLimit = this.GatewayModeMaxConnectionLimit,
RequestTimeout = this.RequestTimeout,
ConnectionMode = this.ConnectionMode,
ConnectionProtocol = this.ConnectionProtocol,
UserAgentContainer = this.UserAgentContainer,
UserAgentContainer = userAgent,
UseMultipleWriteLocations = true,
IdleTcpConnectionTimeout = this.IdleTcpConnectionTimeout,
OpenTcpConnectionTimeout = this.OpenTcpConnectionTimeout,
Expand Down Expand Up @@ -657,6 +652,40 @@ private void ValidateDirectTCPSettings()
}
}

internal UserAgentContainer BuildUserAgentContainer()
{
UserAgentContainer userAgent = new UserAgentContainer();
string features = this.GetUserAgentFeatures();

if (!string.IsNullOrEmpty(features))
{
userAgent.SetFeatures(features.ToString());
}

if (!string.IsNullOrEmpty(this.ApplicationName))
{
userAgent.Suffix = this.ApplicationName;
}

return userAgent;
}

private string GetUserAgentFeatures()
{
CosmosClientOptionsFeatures features = CosmosClientOptionsFeatures.NoFeatures;
if (this.AllowBulkExecution)
{
features |= CosmosClientOptionsFeatures.AllowBulkExecution;
}

if (features == CosmosClientOptionsFeatures.NoFeatures)
{
return null;
}

return Convert.ToString((int)features, 2).PadLeft(8, '0');
}

/// <summary>
/// Serialize the current configuration into a JSON string
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions Microsoft.Azure.Cosmos/src/CosmosClientOptionsFeatures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos
{
using System;

[Flags]
internal enum CosmosClientOptionsFeatures
{
NoFeatures = 0,
AllowBulkExecution = 1
}
}
2 changes: 1 addition & 1 deletion Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSeria
/// <param name="enabled">Whether <see cref="CosmosClientOptions.AllowBulkExecution"/> is enabled.</param>
/// <returns>The <see cref="CosmosClientBuilder"/> object</returns>
/// <seealso cref="CosmosClientOptions.AllowBulkExecution"/>
public CosmosClientBuilder WithBulkexecution(bool enabled)
public CosmosClientBuilder WithBulkExecution(bool enabled)
{
this.clientOptions.AllowBulkExecution = enabled;
return this;
Expand Down
17 changes: 15 additions & 2 deletions Microsoft.Azure.Cosmos/src/UserAgentContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ internal override string BaseUserAgent
}
}

private string CreateBaseUserAgentString()
internal void SetFeatures(string features)
{
// Regenerate base user agent to account for features
this.cosmosBaseUserAgent = this.CreateBaseUserAgentString(features);
}

private string CreateBaseUserAgentString(string features = null)
{
EnvironmentInformation environmentInformation = new EnvironmentInformation();
string operatingSystem = environmentInformation.OperatingSystem;
Expand All @@ -42,7 +48,14 @@ private string CreateBaseUserAgentString()

// Regex replaces all special characters with empty space except . - | since they do not cause format exception for the user agent string.
// Do not change the cosmos-netstandard-sdk as it is required for reporting
return $"cosmos-netstandard-sdk/{environmentInformation.ClientVersion}" + Regex.Replace($"|{environmentInformation.DirectVersion}|{environmentInformation.ClientId}|{environmentInformation.ProcessArchitecture}|{operatingSystem}|{environmentInformation.RuntimeFramework}|", @"[^0-9a-zA-Z\.\|\-]+", " ");
string baseUserAgent = $"cosmos-netstandard-sdk/{environmentInformation.ClientVersion}" + Regex.Replace($"|{environmentInformation.DirectVersion}|{environmentInformation.ClientId}|{environmentInformation.ProcessArchitecture}|{operatingSystem}|{environmentInformation.RuntimeFramework}|", @"[^0-9a-zA-Z\.\|\-]+", " ");

if (!string.IsNullOrEmpty(features))
{
baseUserAgent += $"F {features}|";
}

return baseUserAgent;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,44 @@ public void VerifyUserAgentContent(bool useMacOs)
Assert.AreEqual(envInfo.RuntimeFramework, values[5]);
}

[TestMethod]
[DataRow(true)]
[DataRow(false)]
public async Task VerifyUserAgentWithFeatures(bool useMacOs)
{
this.SetEnvironmentInformation(useMacOs);

const string suffix = " UserApplicationName/1.0";

string features = Convert.ToString((int)CosmosClientOptionsFeatures.AllowBulkExecution, 2).PadLeft(8, '0');

using (CosmosClient client = TestCommon.CreateCosmosClient(builder => builder.WithApplicationName(suffix).WithBulkExecution(true)))
{
Cosmos.UserAgentContainer userAgentContainer = client.ClientOptions.GetConnectionPolicy().UserAgentContainer;

string userAgentString = userAgentContainer.UserAgent;
Assert.IsTrue(userAgentString.Contains(suffix));
Assert.IsTrue(userAgentString.Contains($"|F {features}"));
if (useMacOs)
{
Assert.IsTrue(userAgentString.Contains("Darwin 18.0.0"));
}

Cosmos.Database db = await client.CreateDatabaseIfNotExistsAsync(Guid.NewGuid().ToString());
Assert.IsNotNull(db);
await db.DeleteAsync();
}

using (CosmosClient client = TestCommon.CreateCosmosClient(builder => builder.WithApplicationName(suffix).WithBulkExecution(false)))
{
Cosmos.UserAgentContainer userAgentContainer = client.ClientOptions.GetConnectionPolicy().UserAgentContainer;

string userAgentString = userAgentContainer.UserAgent;
Assert.IsTrue(userAgentString.Contains(suffix));
Assert.IsFalse(userAgentString.Contains($"|F {features}"));
}
}

private void SetEnvironmentInformation(bool useMacOs)
{
//This changes the runtime information to simulate a max os x response. Windows user agent are tested by every other emulator test.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated()
.AddCustomHandlers(preProcessHandler)
.WithApiType(apiType)
.WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests)
.WithBulkexecution(true)
.WithBulkExecution(true)
.WithSerializerOptions(cosmosSerializerOptions);

cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient());
Expand Down Expand Up @@ -180,9 +180,10 @@ public void UserAgentContainsEnvironmentInformation()
string userAgentSuffix = "testSuffix";
cosmosClientOptions.ApplicationName = userAgentSuffix;
Assert.AreEqual(userAgentSuffix, cosmosClientOptions.ApplicationName);
Assert.AreEqual(userAgentSuffix, cosmosClientOptions.UserAgentContainer.Suffix);
Assert.IsTrue(cosmosClientOptions.UserAgentContainer.UserAgent.StartsWith(expectedValue));
Assert.IsTrue(cosmosClientOptions.UserAgentContainer.UserAgent.EndsWith(userAgentSuffix));
UserAgentContainer userAgentContainer = cosmosClientOptions.BuildUserAgentContainer();
Assert.AreEqual(userAgentSuffix, userAgentContainer.Suffix);
Assert.IsTrue(userAgentContainer.UserAgent.StartsWith(expectedValue));
Assert.IsTrue(userAgentContainer.UserAgent.EndsWith(userAgentSuffix));

ConnectionPolicy connectionPolicy = cosmosClientOptions.GetConnectionPolicy();
Assert.AreEqual(userAgentSuffix, connectionPolicy.UserAgentSuffix);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1415,9 +1415,11 @@
"Attributes": [],
"MethodInfo": null
},
"System.String get_ApplicationName()": {
"System.String get_ApplicationName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [],
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "System.String get_ApplicationName()"
},
"System.String get_ApplicationRegion()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
Expand Down Expand Up @@ -1451,9 +1453,11 @@
],
"MethodInfo": "Void set_AllowBulkExecution(Boolean)"
},
"Void set_ApplicationName(System.String)": {
"Void set_ApplicationName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [],
"Attributes": [
"CompilerGeneratedAttribute"
],
"MethodInfo": "Void set_ApplicationName(System.String)"
},
"Void set_ApplicationRegion(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
Expand Down Expand Up @@ -2390,10 +2394,10 @@
"Attributes": [],
"MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithApplicationRegion(System.String)"
},
"Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithBulkexecution(Boolean)": {
"Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithBulkExecution(Boolean)": {
"Type": "Method",
"Attributes": [],
"MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithBulkexecution(Boolean)"
"MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithBulkExecution(Boolean)"
},
"Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithConnectionModeDirect()": {
"Type": "Method",
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- [#923](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/923) Bulk Support is now public
- [#922](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/922) Included information of bulk support usage in user agent

## <a name="3.3.2"/> [3.3.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.3.2) - 2019-10-16

Expand Down