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

Enrich user-agent with runtime context #630

Merged
merged 12 commits into from
Aug 8, 2019
Merged
15 changes: 13 additions & 2 deletions Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,20 @@ public class CosmosClientOptions
private static readonly CosmosSerializer propertiesSerializer = new CosmosJsonSerializerWrapper(new CosmosJsonDotNetSerializer());

private readonly Collection<RequestHandler> customHandlers;
private readonly string currentEnvironmentInformation;

private int gatewayModeMaxConnectionLimit;
private string applicationName;

/// <summary>
/// Creates a new CosmosClientOptions
/// </summary>
public CosmosClientOptions()
{
this.UserAgentContainer = new UserAgentContainer();
this.EnvironmentInformation = new EnvironmentInformation();
ealsur marked this conversation as resolved.
Show resolved Hide resolved
this.currentEnvironmentInformation = this.EnvironmentInformation.ToString();
this.UserAgentContainer.Suffix = this.currentEnvironmentInformation;
kirankumarkolli marked this conversation as resolved.
Show resolved Hide resolved
this.GatewayModeMaxConnectionLimit = ConnectionPolicy.Default.MaxConnectionLimit;
this.RequestTimeout = ConnectionPolicy.Default.RequestTimeout;
this.ConnectionMode = CosmosClientOptions.DefaultConnectionMode;
Expand All @@ -65,8 +70,12 @@ public CosmosClientOptions()
/// </remarks>
public string ApplicationName
{
get => this.UserAgentContainer.Suffix;
set => this.UserAgentContainer.Suffix = value;
get => this.applicationName;
set
{
this.UserAgentContainer.Suffix = this.currentEnvironmentInformation + value;
ealsur marked this conversation as resolved.
Show resolved Hide resolved
this.applicationName = value;
}
}

/// <summary>
Expand Down Expand Up @@ -217,6 +226,8 @@ public Collection<RequestHandler> CustomHandlers

internal UserAgentContainer UserAgentContainer { get; private set; }

internal EnvironmentInformation EnvironmentInformation { get; private set; }

/// <summary>
/// The event handler to be invoked before the request is sent.
/// </summary>
Expand Down
53 changes: 53 additions & 0 deletions Microsoft.Azure.Cosmos/src/EnvironmentInformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Reflection;
using System.Runtime.InteropServices;

internal sealed class EnvironmentInformation
{
internal static readonly string clientId;
internal static readonly string clientSDKVersion;
internal static readonly string framework;
internal static readonly string architecture;

static EnvironmentInformation()
ealsur marked this conversation as resolved.
Show resolved Hide resolved
{
Version sdkVersion = Assembly.GetAssembly(typeof(CosmosClient)).GetName().Version;
kirankumarkolli marked this conversation as resolved.
Show resolved Hide resolved
EnvironmentInformation.clientSDKVersion = $"{sdkVersion.Major}.{sdkVersion.Minor}.{sdkVersion.Revision}";
ealsur marked this conversation as resolved.
Show resolved Hide resolved
EnvironmentInformation.framework = RuntimeInformation.FrameworkDescription;
EnvironmentInformation.architecture = RuntimeInformation.ProcessArchitecture.ToString();
EnvironmentInformation.clientId = DateTime.UtcNow.Ticks.ToString();
}

/// <summary>
/// Unique identifier of a client
/// </summary>
public string ClientId => EnvironmentInformation.clientId;

/// <summary>
/// Version of the current client.
/// </summary>
public string ClientVersion => EnvironmentInformation.clientSDKVersion;

/// <summary>
/// Identifier of the Framework.
/// </summary>
/// <seealso cref="RuntimeInformation.FrameworkDescription"/>
public string RuntimeFramework => EnvironmentInformation.framework;

/// <summary>
/// Type of architecture being used.
/// </summary>
/// <seealso cref="RuntimeInformation.ProcessArchitecture"/>
public string ProcessArchitecture => EnvironmentInformation.architecture;

public override string ToString()
{
return $" {this.ClientVersion}-{this.RuntimeFramework} {this.ProcessArchitecture} {this.ClientId}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated()
Assert.AreEqual(Protocol.Https, policy.ConnectionProtocol);
Assert.AreEqual(maxConnections, policy.MaxConnectionLimit);
Assert.AreEqual(requestTimeout, policy.RequestTimeout);
Assert.AreEqual(userAgentSuffix, policy.UserAgentSuffix);
Assert.IsTrue(policy.UserAgentSuffix.Contains(userAgentSuffix));
Assert.IsTrue(policy.UseMultipleWriteLocations);
Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, policy.RetryOptions.MaxRetryAttemptsOnThrottledRequests);
Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds);
Expand All @@ -116,6 +116,23 @@ public void ThrowOnNullEndpoint()
new CosmosClientBuilder(null, "testKey");
}

[TestMethod]
public void UserAgentContainsEnvironmentInformation()
{
var environmentInformation = new EnvironmentInformation();
var expectedValue = environmentInformation.ToString();
CosmosClientOptions cosmosClientOptions = new CosmosClientOptions();
string userAgentSuffix = "testSuffix";
cosmosClientOptions.ApplicationName = userAgentSuffix;

Assert.IsTrue(cosmosClientOptions.UserAgentContainer.Suffix.Contains(userAgentSuffix));
ealsur marked this conversation as resolved.
Show resolved Hide resolved
Assert.IsTrue(cosmosClientOptions.UserAgentContainer.Suffix.Contains(expectedValue));

ConnectionPolicy connectionPolicy = cosmosClientOptions.GetConnectionPolicy();
Assert.IsTrue(connectionPolicy.UserAgentSuffix.Contains(userAgentSuffix));
Assert.IsTrue(connectionPolicy.UserAgentSuffix.Contains(expectedValue));
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ThrowOnNullConnectionString()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Tests
{
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class EnvironmentInformationTests
{
[TestMethod]
public void ClientVersionIsNotNull()
{
var envInfo = new EnvironmentInformation();
Assert.IsNotNull(envInfo.ClientVersion);
ealsur marked this conversation as resolved.
Show resolved Hide resolved
}

[TestMethod]
public void ProcessArchitectureIsNotNull()
{
var envInfo = new EnvironmentInformation();
Assert.IsNotNull(envInfo.ProcessArchitecture);
}

[TestMethod]
public void FrameworkIsNotNull()
{
var envInfo = new EnvironmentInformation();
Assert.IsNotNull(envInfo.RuntimeFramework);
}

[TestMethod]
public void ClientIdIsNotNull()
{
var envInfo = new EnvironmentInformation();
Assert.IsNotNull(envInfo.ClientId);
}

[TestMethod]
public void ToStringContainsAll()
{
var envInfo = new EnvironmentInformation();
var serialization = envInfo.ToString();
Assert.IsTrue(serialization.Contains(envInfo.ClientVersion));
Assert.IsTrue(serialization.Contains(envInfo.ProcessArchitecture));
Assert.IsTrue(serialization.Contains(envInfo.RuntimeFramework));
Assert.IsTrue(serialization.Contains(envInfo.ClientId));
}
}
}