Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions Microsoft.Azure.Cosmos/src/DocumentClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Microsoft.Azure.Cosmos
using Microsoft.Azure.Cosmos.Query;
using Microsoft.Azure.Cosmos.Query.Core.QueryPlan;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Cosmos.Telemetry;
using Microsoft.Azure.Cosmos.Tracing;
using Microsoft.Azure.Cosmos.Tracing.TraceData;
using Microsoft.Azure.Documents;
Expand Down Expand Up @@ -897,6 +898,9 @@ internal virtual void Initialize(Uri serviceEndpoint,
this.sendingRequest,
this.receivedResponse);

// Loading VM Information (non blocking call and initialization won't fail if this call fails)
VmMetadataApiHandler.TryInitialize(this.httpClient);

if (sessionContainer != null)
{
this.sessionContainer = sessionContainer;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;

internal sealed class HttpTimeoutPolicyNoRetry : HttpTimeoutPolicy
{
public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyNoRetry();
private static readonly string Name = nameof(HttpTimeoutPolicyNoRetry);

private HttpTimeoutPolicyNoRetry()
{
}

private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelays = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>();

public override string TimeoutPolicyName => HttpTimeoutPolicyNoRetry.Name;

public override TimeSpan MaximumRetryTimeLimit => TimeSpan.Zero;

public override int TotalRetryCount => 0;

public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator()
{
return this.TimeoutsAndDelays.GetEnumerator();
}

// Always Unsafe to retry
public override bool IsSafeToRetry(HttpMethod httpMethod)
{
return false;
}

public override bool ShouldRetryBasedOnResponse(HttpMethod requestHttpMethod, HttpResponseMessage responseMessage)
{
return false;
}
}
}
14 changes: 7 additions & 7 deletions Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ internal class ClientTelemetry : IDisposable
private static readonly TimeSpan observingWindow = ClientTelemetryOptions.GetScheduledTimeSpan();

private readonly ClientTelemetryProperties clientTelemetryInfo;

private readonly DocumentClient documentClient;
private readonly CosmosHttpClient httpClient;
private readonly AuthorizationTokenProvider tokenProvider;
Expand Down Expand Up @@ -135,17 +134,18 @@ private async Task EnrichAndSendAsync()
this.clientTelemetryInfo.GlobalDatabaseAccountName = accountProperties?.Id;
}

// Load host information if not available (it caches the information)
AzureVMMetadata azMetadata = await ClientTelemetryHelper.LoadAzureVmMetaDataAsync(this.httpClient);

Compute vmInformation = azMetadata?.Compute;
// Load host information from cache
Compute vmInformation = VmMetadataApiHandler.GetMachineInfo();
if (vmInformation != null)
{
this.clientTelemetryInfo.ApplicationRegion = vmInformation.Location;
this.clientTelemetryInfo.HostEnvInfo = ClientTelemetryOptions.GetHostInformation(vmInformation);

//TODO: Set AcceleratingNetwork flag from instance metadata once it is available.
}

this.clientTelemetryInfo.MachineId = VmMetadataApiHandler.GetMachineId();

await Task.Delay(observingWindow, this.cancellationTokenSource.Token);

// If cancellation is requested after the delay then return from here.
Expand Down Expand Up @@ -329,7 +329,7 @@ await this.tokenProvider.AddAuthorizationHeaderAsync(

using HttpResponseMessage response = await this.httpClient.SendHttpAsync(CreateRequestMessage,
ResourceType.Telemetry,
HttpTimeoutPolicyDefault.Instance,
HttpTimeoutPolicyNoRetry.Instance,
null,
this.cancellationTokenSource.Token);

Expand Down Expand Up @@ -369,7 +369,7 @@ public void Dispose()
{
this.cancellationTokenSource.Cancel();
this.cancellationTokenSource.Dispose();

this.telemetryTask = null;
}
}
Expand Down
51 changes: 2 additions & 49 deletions Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry

internal static class ClientTelemetryHelper
{
internal static AzureVMMetadata azMetadata = null;

private static readonly Uri vmMetadataEndpointUrl = ClientTelemetryOptions.GetVmMetadataUrl();

/// <summary>
/// Task to get Account Properties from cache if available otherwise make a network call.
/// </summary>
Expand All @@ -42,50 +38,6 @@ internal static async Task<AccountProperties> SetAccountNameAsync(DocumentClient
return null;
}

/// <summary>
/// Task to collect virtual machine metadata information. using instance metedata service API.
/// ref: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=windows
/// Collects only application region and environment information
/// </summary>
/// <returns>Async Task</returns>
internal static async Task<AzureVMMetadata> LoadAzureVmMetaDataAsync(CosmosHttpClient httpClient)
{
if (azMetadata == null)
{
DefaultTrace.TraceVerbose("Getting VM Metadata Information for Telemetry.");
try
{
static ValueTask<HttpRequestMessage> CreateRequestMessage()
{
HttpRequestMessage request = new HttpRequestMessage()
{
RequestUri = vmMetadataEndpointUrl,
Method = HttpMethod.Get,
};
request.Headers.Add("Metadata", "true");

return new ValueTask<HttpRequestMessage>(request);
}

using HttpResponseMessage httpResponseMessage = await httpClient
.SendHttpAsync(createRequestMessageAsync: CreateRequestMessage,
resourceType: ResourceType.Telemetry,
timeoutPolicy: HttpTimeoutPolicyDefault.Instance,
clientSideRequestStatistics: null,
cancellationToken: new CancellationToken()); // Do not want to cancel the whole process if this call fails

azMetadata = await ClientTelemetryOptions.ProcessResponseAsync(httpResponseMessage);

}
catch (Exception ex)
{
DefaultTrace.TraceError("Exception in LoadAzureVmMetaDataAsync() {0}", ex.Message);
}
}

return azMetadata;
}

/// <summary>
/// Record System Usage and update passed system Info collection. Right now, it collects following metrics
/// 1) CPU Usage
Expand Down Expand Up @@ -118,7 +70,7 @@ internal static void RecordSystemUsage(
{
systemInfoCollection.Add(TelemetrySystemUsage.GetTcpConnectionCount(systemUsageHistory.Values));
}

}

/// <summary>
Expand Down Expand Up @@ -186,5 +138,6 @@ internal static string GetContactedRegions(CosmosDiagnostics cosmosDiagnostics)

return regionsContacted.ToString();
}

}
}
31 changes: 0 additions & 31 deletions Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
namespace Microsoft.Azure.Cosmos.Telemetry
{
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Documents;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

internal static class ClientTelemetryOptions
{
Expand Down Expand Up @@ -73,7 +70,6 @@ internal static class ClientTelemetryOptions
internal const string IsThreadStarvingName = "SystemPool_IsThreadStarving_True";
internal const string IsThreadStarvingUnit = "Count";

internal const string DefaultVmMetadataUrL = "http://169.254.169.254/metadata/instance?api-version=2020-06-01";
internal const double DefaultTimeStampInSeconds = 600;
internal const double Percentile50 = 50.0;
internal const double Percentile90 = 90.0;
Expand All @@ -92,7 +88,6 @@ internal static class ClientTelemetryOptions

internal static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };

private static Uri vmMetadataUrl;
private static Uri clientTelemetryEndpoint;
private static string environmentName;
private static TimeSpan scheduledTimeSpan = TimeSpan.Zero;
Expand All @@ -108,22 +103,6 @@ internal static bool IsClientTelemetryEnabled()
return isTelemetryEnabled;
}

internal static Uri GetVmMetadataUrl()
{
if (vmMetadataUrl == null)
{
string vmMetadataUrlProp = ConfigurationManager.GetEnvironmentVariable<string>(
EnvPropsClientTelemetryVmMetadataUrl, DefaultVmMetadataUrL);
if (!String.IsNullOrEmpty(vmMetadataUrlProp))
{
vmMetadataUrl = new Uri(vmMetadataUrlProp);
}

DefaultTrace.TraceInformation($"VM metadata URL for telemetry {vmMetadataUrlProp}");
}
return vmMetadataUrl;
}

internal static TimeSpan GetScheduledTimeSpan()
{
if (scheduledTimeSpan.Equals(TimeSpan.Zero))
Expand Down Expand Up @@ -154,16 +133,6 @@ internal static TimeSpan GetScheduledTimeSpan()
return scheduledTimeSpan;
}

internal static async Task<AzureVMMetadata> ProcessResponseAsync(HttpResponseMessage httpResponseMessage)
{
if (httpResponseMessage.Content == null)
{
return null;
}
string jsonVmInfo = await httpResponseMessage.Content.ReadAsStringAsync();
return JObject.Parse(jsonVmInfo).ToObject<AzureVMMetadata>();
}

internal static string GetHostInformation(Compute vmInformation)
{
return String.Concat(vmInformation?.OSType, "|",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ internal sealed class ClientTelemetryProperties
[JsonProperty(PropertyName = "clientId")]
internal string ClientId { get; }

[JsonProperty(PropertyName = "machineId")]
internal string MachineId { get; set; }

[JsonProperty(PropertyName = "processId")]
internal string ProcessId { get; }

Expand Down Expand Up @@ -97,7 +100,8 @@ public ClientTelemetryProperties(string dateTimeUtc,
IReadOnlyList<string> preferredRegions,
List<SystemInfo> systemInfo,
List<OperationInfo> cacheRefreshInfo,
List<OperationInfo> operationInfo)
List<OperationInfo> operationInfo,
string machineId)
{
this.DateTimeUtc = dateTimeUtc;
this.ClientId = clientId;
Expand All @@ -112,6 +116,7 @@ public ClientTelemetryProperties(string dateTimeUtc,
this.CacheRefreshInfo = cacheRefreshInfo;
this.OperationInfo = operationInfo;
this.PreferredRegions = preferredRegions;
this.MachineId = machineId;
}
}
}
13 changes: 12 additions & 1 deletion Microsoft.Azure.Cosmos/src/Telemetry/Compute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ namespace Microsoft.Azure.Cosmos.Telemetry
[Serializable]
internal sealed class Compute
{
public Compute(string location, string sKU, string azEnvironment, string oSType, string vMSize)
[JsonConstructor]
public Compute(
string vMId,
string location,
string sKU,
string azEnvironment,
string oSType,
string vMSize)
{
this.Location = location;
this.SKU = sKU;
this.AzEnvironment = azEnvironment;
this.OSType = oSType;
this.VMSize = vMSize;
this.VMId = "vmId:" + vMId;
}

[JsonProperty(PropertyName = "location")]
Expand All @@ -33,6 +41,9 @@ public Compute(string location, string sKU, string azEnvironment, string oSType,

[JsonProperty(PropertyName = "vmSize")]
internal string VMSize { get; }

[JsonProperty(PropertyName = "vmId")]
internal string VMId { get; }
}

}
Loading