diff --git a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs index 876ac6dcd9..3c9b36a552 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs @@ -105,7 +105,7 @@ private set /// | /// +-----------------------------+ /// | | - /// | RetryHandler |-> RetryPolicy -> ResetSessionTokenRetryPolicyFactory -> ClientRetryPolicy -> ResourceThrottleRetryPolicy + /// | TelemetryHandler |-> Trigger a thread to monitor system usage/operation information and sends to an API /// | | /// +-----------------------------+ /// | @@ -113,7 +113,7 @@ private set /// | /// +-----------------------------+ /// | | - /// | Telemetry Handler |-> Trigger a thread to monitor system usage/operation information and send it to juno + /// | RetryHandler |-> RetryPolicy -> ResetSessionTokenRetryPolicyFactory -> ClientRetryPolicy -> ResourceThrottleRetryPolicy /// | | /// +-----------------------------+ /// | @@ -176,16 +176,16 @@ public RequestInvokerHandler Build() current = current.InnerHandler; } - Debug.Assert(this.retryHandler != null, nameof(this.retryHandler)); - current.InnerHandler = this.retryHandler; - current = current.InnerHandler; - if (this.telemetryHandler != null) { current.InnerHandler = this.telemetryHandler; current = current.InnerHandler; } + Debug.Assert(this.retryHandler != null, nameof(this.retryHandler)); + current.InnerHandler = this.retryHandler; + current = current.InnerHandler; + // Have a router handler RequestHandler feedHandler = this.CreateDocumentFeedPipeline(); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 339d758693..80b58bb788 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -148,10 +148,10 @@ private async Task EnrichAndSendAsync() return; } - this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); - this.RecordSystemUtilization(); + this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); + ConcurrentDictionary operationInfoSnapshot = Interlocked.Exchange(ref this.operationInfoMap, new ConcurrentDictionary()); @@ -216,21 +216,19 @@ internal void Collect(CosmosDiagnostics cosmosDiagnostics, statusCode: (int)statusCode); (LongConcurrentHistogram latency, LongConcurrentHistogram requestcharge) = this.operationInfoMap - .GetOrAdd(payloadKey, x => (latency: new LongConcurrentHistogram(1, + .GetOrAdd(payloadKey, x => (latency: new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, ClientTelemetryOptions.RequestLatencyMax, ClientTelemetryOptions.RequestLatencyPrecision), requestcharge: new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, ClientTelemetryOptions.RequestChargeMax, ClientTelemetryOptions.RequestChargePrecision))); - - long totalElapsedTimeInMs = (long)cosmosDiagnostics.GetClientElapsedTime().TotalMilliseconds; try { - latency.RecordValue(totalElapsedTimeInMs * ClientTelemetryOptions.HistogramPrecisionFactor); + latency.RecordValue(cosmosDiagnostics.GetClientElapsedTime().Ticks); } catch (Exception ex) { - DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Latency Value : " + totalElapsedTimeInMs + " Exception : " + ex.Message); + DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : " + ex.Message); } long requestChargeToRecord = (long)(requestCharge * ClientTelemetryOptions.HistogramPrecisionFactor); @@ -282,11 +280,11 @@ private void RecordSystemUtilization() { DefaultTrace.TraceVerbose("Started Recording System Usage for telemetry."); - SystemUsageHistory systemUsageRecorder = this.diagnosticsHelper.GetClientTelemtrySystemHistory(); + SystemUsageHistory systemUsageHistory = this.diagnosticsHelper.GetClientTelemtrySystemHistory(); - if (systemUsageRecorder != null ) + if (systemUsageHistory != null ) { - (SystemInfo cpuUsagePayload, SystemInfo memoryUsagePayload) = ClientTelemetryHelper.RecordSystemUsage(systemUsageRecorder); + (SystemInfo cpuUsagePayload, SystemInfo memoryUsagePayload) = ClientTelemetryHelper.RecordSystemUsage(systemUsageHistory); if (cpuUsagePayload != null) { this.clientTelemetryInfo.SystemInfo.Add(cpuUsagePayload); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs index 644caa2f20..958426b185 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs @@ -88,36 +88,37 @@ static ValueTask CreateRequestMessage() /// /// Record System Usage and return recorded metrics /// - /// + /// /// ReportPayload - internal static (SystemInfo cpuInfo, SystemInfo memoryInfo) RecordSystemUsage(SystemUsageHistory systemUsageRecorder) + internal static (SystemInfo cpuInfo, SystemInfo memoryInfo) RecordSystemUsage(SystemUsageHistory systemUsageHistory) { - LongConcurrentHistogram cpuHistogram = new LongConcurrentHistogram(1, + LongConcurrentHistogram cpuHistogram = new LongConcurrentHistogram(ClientTelemetryOptions.CpuMin, ClientTelemetryOptions.CpuMax, ClientTelemetryOptions.CpuPrecision); - LongConcurrentHistogram memoryHistogram = new LongConcurrentHistogram(1, + LongConcurrentHistogram memoryHistogram = new LongConcurrentHistogram(ClientTelemetryOptions.MemoryMin, ClientTelemetryOptions.MemoryMax, ClientTelemetryOptions.MemoryPrecision); - if (systemUsageRecorder.Values == null) + if (systemUsageHistory.Values == null) { return (null, null); } - foreach (SystemUsageLoad systemUsage in systemUsageRecorder.Values) + DefaultTrace.TraceInformation("System Usage recorded by telemetry is : " + systemUsageHistory); + + foreach (SystemUsageLoad systemUsage in systemUsageHistory.Values) { float? cpuValue = systemUsage.CpuUsage; if (cpuValue.HasValue && !float.IsNaN(cpuValue.Value)) { - cpuHistogram.RecordValue((long)cpuValue); + cpuHistogram.RecordValue((long)(cpuValue * ClientTelemetryOptions.HistogramPrecisionFactor)); } long? memoryLoad = systemUsage.MemoryUsage; if (memoryLoad.HasValue) { - long memoryLoadInMb = memoryLoad.Value / ClientTelemetryOptions.BytesToMb; - memoryHistogram.RecordValue(memoryLoadInMb); + memoryHistogram.RecordValue(memoryLoad.Value); } } @@ -125,14 +126,14 @@ internal static (SystemInfo cpuInfo, SystemInfo memoryInfo) RecordSystemUsage(Sy if (memoryHistogram.TotalCount > 0) { memoryInfoPayload = new SystemInfo(ClientTelemetryOptions.MemoryName, ClientTelemetryOptions.MemoryUnit); - memoryInfoPayload.SetAggregators(memoryHistogram); + memoryInfoPayload.SetAggregators(memoryHistogram, ClientTelemetryOptions.KbToMbFactor); } SystemInfo cpuInfoPayload = null; if (cpuHistogram.TotalCount > 0) { cpuInfoPayload = new SystemInfo(ClientTelemetryOptions.CpuName, ClientTelemetryOptions.CpuUnit); - cpuInfoPayload.SetAggregators(cpuHistogram); + cpuInfoPayload.SetAggregators(cpuHistogram, ClientTelemetryOptions.HistogramPrecisionFactor); } return (cpuInfoPayload, memoryInfoPayload); @@ -152,7 +153,7 @@ internal static List ToListWithMetricsInfo(IDictionary ProcessResponseAsync(HttpResponseMes return JObject.Parse(jsonVmInfo).ToObject(); } - internal static string GetHostInformation(Compute vmInformation) + internal static string GetHostInformation(Compute vmInformation) { return String.Concat(vmInformation?.OSType, "|", vmInformation?.SKU, "|", vmInformation?.VMSize, "|", vmInformation?.AzEnvironment); - } + } internal static Uri GetClientTelemetryEndpoint() { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProperties.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProperties.cs index 21dec4e36f..9879951c7d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProperties.cs @@ -66,11 +66,14 @@ internal ClientTelemetryProperties(string clientId, this.ProcessId = processId; this.UserAgent = userAgent; this.ConnectionModeEnum = connectionMode; - this.ConnectionMode = connectionMode.ToString(); + this.ConnectionMode = ClientTelemetryProperties.GetConnectionModeString(connectionMode); this.SystemInfo = new List(); this.PreferredRegions = preferredRegions; } + /// + /// Needed by Serializer to deserialize the json + /// public ClientTelemetryProperties(string dateTimeUtc, string clientId, string processId, @@ -99,5 +102,15 @@ public ClientTelemetryProperties(string dateTimeUtc, this.OperationInfo = operationInfo; this.PreferredRegions = preferredRegions; } + + private static string GetConnectionModeString(ConnectionMode connectionMode) + { + return connectionMode switch + { + Cosmos.ConnectionMode.Direct => "DIRECT", + Cosmos.ConnectionMode.Gateway => "GATEWAY", + _ => connectionMode.ToString().ToUpper(), + }; + } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/MetricInfo.cs b/Microsoft.Azure.Cosmos/src/Telemetry/MetricInfo.cs index cd7ee6da34..59e0f7d24b 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/MetricInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/MetricInfo.cs @@ -48,13 +48,13 @@ public MetricInfo(string metricsName, internal long Count { get; set; } [JsonProperty(PropertyName = "min")] - internal long Min { get; set; } + internal double Min { get; set; } [JsonProperty(PropertyName = "max")] - internal long Max { get; set; } + internal double Max { get; set; } [JsonProperty(PropertyName = "percentiles")] - internal IReadOnlyDictionary Percentiles { get; set; } + internal IReadOnlyDictionary Percentiles { get; set; } /// /// It will set the current object with the aggregated values from the given histogram @@ -62,15 +62,15 @@ public MetricInfo(string metricsName, /// /// /// MetricInfo - internal MetricInfo SetAggregators(LongConcurrentHistogram histogram, long adjustment = 1) + internal MetricInfo SetAggregators(LongConcurrentHistogram histogram, double adjustment = 1) { if (histogram != null) { this.Count = histogram.TotalCount; this.Max = histogram.GetMaxValue() / adjustment; this.Min = histogram.GetMinValue() / adjustment; - this.Mean = histogram.GetMean() / Convert.ToDouble(adjustment); - IReadOnlyDictionary percentile = new Dictionary + this.Mean = histogram.GetMean() / adjustment; + IReadOnlyDictionary percentile = new Dictionary { { ClientTelemetryOptions.Percentile50, histogram.GetValueAtPercentile(ClientTelemetryOptions.Percentile50) / adjustment }, { ClientTelemetryOptions.Percentile90, histogram.GetValueAtPercentile(ClientTelemetryOptions.Percentile90) / adjustment }, diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OperationInfo.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OperationInfo.cs index e066a2b005..8e8a1ae04e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OperationInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OperationInfo.cs @@ -62,7 +62,7 @@ internal OperationInfo(string regionsContacted, { this.GreaterThan1Kb = responseSizeInBytes > ClientTelemetryOptions.OneKbToBytes; } - this.Consistency = consistency?.ToString(); + this.Consistency = OperationInfo.GetConsistencyString(consistency); this.DatabaseName = databaseName; this.ContainerName = containerName; this.Operation = operation?.ToOperationTypeString(); @@ -93,6 +93,24 @@ public OperationInfo(string regionsContacted, this.MetricInfo = metricInfo; } + private static string GetConsistencyString(Cosmos.ConsistencyLevel? consistency) + { + if (consistency == null) + { + return null; + } + + return consistency switch + { + Cosmos.ConsistencyLevel.Strong => "STRONG", + Cosmos.ConsistencyLevel.Session => "SESSION", + Cosmos.ConsistencyLevel.Eventual => "EVENTUAL", + Cosmos.ConsistencyLevel.ConsistentPrefix => "CONSISTENTPREFIX", + Cosmos.ConsistencyLevel.BoundedStaleness => "BOUNDEDSTALENESS", + _ => consistency.ToString().ToUpper(), + }; + } + public OperationInfo Copy() { return new OperationInfo(this.RegionsContacted, @@ -136,7 +154,7 @@ public override bool Equals(object obj) return isequal; } - internal void SetAggregators(LongConcurrentHistogram histogram, long adjustment = 1) + internal void SetAggregators(LongConcurrentHistogram histogram, double adjustment = 1) { this.MetricInfo.SetAggregators(histogram, adjustment); } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/SystemInfo.cs b/Microsoft.Azure.Cosmos/src/Telemetry/SystemInfo.cs index b8b10311a8..60c8291a30 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/SystemInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/SystemInfo.cs @@ -24,7 +24,7 @@ public SystemInfo(MetricInfo metricInfo) this.MetricInfo = metricInfo; } - internal void SetAggregators(LongConcurrentHistogram histogram, long adjustment = 1) + internal void SetAggregators(LongConcurrentHistogram histogram, double adjustment = 1) { this.MetricInfo.SetAggregators(histogram, adjustment); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index a7f3e6dc65..5d01dc04ba 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -16,17 +16,19 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Newtonsoft.Json; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Telemetry; + using System.IO; [TestClass] public class ClientTelemetryTests : BaseCosmosClientHelper { private const string telemetryEndpointUrl = "http://dummy.telemetry.endpoint/"; private const int scheduledInSeconds = 1; - private Container container; + private CosmosClientBuilder cosmosClientBuilder; private List actualInfo; + [TestInitialize] - public async Task TestInitialize() + public void TestInitialize() { this.actualInfo = new List(); @@ -67,15 +69,10 @@ public async Task TestInitialize() "region2" }; - CosmosClientBuilder cosmosClientBuilder = TestCommon.GetDefaultConfiguration(); - - this.cosmosClient = cosmosClientBuilder + this.cosmosClientBuilder = TestCommon.GetDefaultConfiguration() .WithApplicationPreferredRegions(preferredRegionList) .WithTelemetryEnabled() - .WithHttpClientFactory(() => new HttpClient(httpHandler)).Build(); - - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); - this.container = await this.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); + .WithHttpClientFactory(() => new HttpClient(httpHandler)); } [TestCleanup] @@ -88,46 +85,53 @@ public async Task Cleanup() } [TestMethod] - public async Task PointSuccessOperationsTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task PointSuccessOperationsTest(ConnectionMode mode) { + Container container = await this.GetContainer(mode); + // Create an item ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); - ItemResponse createResponse = await this.container.CreateItemAsync(testItem); + ItemResponse createResponse =await container.CreateItemAsync(testItem); ToDoActivity testItemCreated = createResponse.Resource; // Read an Item - await this.container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); // Upsert an Item - await this.container.UpsertItemAsync(testItem); + await container.UpsertItemAsync(testItem); // Replace an Item - await this.container.ReplaceItemAsync(testItemCreated, testItemCreated.id.ToString()); + await container.ReplaceItemAsync(testItemCreated, testItemCreated.id.ToString()); // Patch an Item List patch = new List() { PatchOperation.Add("/new", "patched") }; - await ((ContainerInternal)this.container).PatchItemAsync( + await ((ContainerInternal)container).PatchItemAsync( testItem.id, new Cosmos.PartitionKey(testItem.id), patch); // Delete an Item - await this.container.DeleteItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + await container.DeleteItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - this.WaitAndAssert(12); + await this.WaitAndAssert(12); } [TestMethod] - public async Task PointReadFailureOperationsTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task PointReadFailureOperationsTest(ConnectionMode mode) { // Fail Read try { - await this.container.ReadItemAsync( - new Guid().ToString(), + Container container = await this.GetContainer(mode); + await container.ReadItemAsync( + new Guid().ToString(), new Cosmos.PartitionKey(new Guid().ToString())); } catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.NotFound) @@ -135,16 +139,21 @@ await this.container.ReadItemAsync( string message = ce.ToString(); Assert.IsNotNull(message); } - this.WaitAndAssert(2); + + await this.WaitAndAssert(2); } [TestMethod] - public async Task StreamReadFailureOperationsTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task StreamReadFailureOperationsTest(ConnectionMode mode) { + Container container = await this.GetContainer(mode); + // Fail Read try { - await this.container.ReadItemStreamAsync( + await container.ReadItemStreamAsync( new Guid().ToString(), new Cosmos.PartitionKey(new Guid().ToString())); } @@ -154,50 +163,56 @@ await this.container.ReadItemStreamAsync( Assert.IsNotNull(message); } - this.WaitAndAssert(2); + await this.WaitAndAssert(2); } [TestMethod] - public async Task StreamOperationsTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task StreamOperationsTest(ConnectionMode mode) { + Container container = await this.GetContainer(mode); // Create an item var testItem = new { id = "MyTestItemId", partitionKeyPath = "MyTestPkValue", details = "it's working", status = "done" }; - await this.container + await container .CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), new Cosmos.PartitionKey(testItem.id)); //Upsert an Item - await this.container.UpsertItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), new Cosmos.PartitionKey(testItem.id)); + await container.UpsertItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), new Cosmos.PartitionKey(testItem.id)); //Read an Item - await this.container.ReadItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + await container.ReadItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); //Replace an Item - await this.container.ReplaceItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), testItem.id, new Cosmos.PartitionKey(testItem.id)); + await container.ReplaceItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), testItem.id, new Cosmos.PartitionKey(testItem.id)); // Patch an Item List patch = new List() { PatchOperation.Add("/new", "patched") }; - await ((ContainerInternal)this.container).PatchItemStreamAsync( + await ((ContainerInternal)container).PatchItemStreamAsync( partitionKey: new Cosmos.PartitionKey(testItem.id), id: testItem.id, patchOperations: patch); //Delete an Item - await this.container.DeleteItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + await container.DeleteItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - this.WaitAndAssert(12); + await this.WaitAndAssert(12); } [TestMethod] - public async Task BatchOperationsTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task BatchOperationsTest(ConnectionMode mode) { + Container container = await this.GetContainer(mode); using (BatchAsyncContainerExecutor executor = new BatchAsyncContainerExecutor( - (ContainerInlineCore)this.container, - ((ContainerInlineCore)this.container).ClientContext, + (ContainerInlineCore)container, + ((ContainerInlineCore)container).ClientContext, 20, Documents.Constants.MaxDirectModeBatchRequestBodySizeInBytes) ) @@ -210,21 +225,26 @@ public async Task BatchOperationsTest() await Task.WhenAll(tasks); } - this.WaitAndAssert(2); + + await this.WaitAndAssert(2); } [TestMethod] - public async Task QueryOperationTest() + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public async Task QueryOperationTest(ConnectionMode mode) { + Container container = await this.GetContainer(mode); + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue", "MyTestItemId"); - ItemResponse createResponse = await this.container.CreateItemAsync(testItem); + ItemResponse createResponse = await container.CreateItemAsync(testItem); if (createResponse.StatusCode == HttpStatusCode.Created) { string sqlQueryText = "SELECT * FROM c"; QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); - FeedIterator queryResultSetIterator = this.container.GetItemQueryIterator(queryDefinition); + FeedIterator queryResultSetIterator = container.GetItemQueryIterator(queryDefinition); List families = new List(); while (queryResultSetIterator.HasMoreResults) @@ -236,13 +256,13 @@ public async Task QueryOperationTest() } } } - this.WaitAndAssert(4); + await this.WaitAndAssert(4); } - - private void WaitAndAssert(int expectedOperationCount, int milliseconds = 2000) + private async Task WaitAndAssert(int expectedOperationCount, int millisecondsToWait = 2000) { - Task.Delay(milliseconds).Wait(); + // As this feature is thread based execution so waiting to get results and to avoid test flakyness + await this.Wait(millisecondsToWait); Assert.IsNotNull(this.actualInfo, "Telemetry Information not available"); Assert.IsTrue(this.actualInfo.Count > 0, "Telemetry Information not available"); @@ -300,11 +320,48 @@ private void WaitAndAssert(int expectedOperationCount, int milliseconds = 2000) } } + private async Task Wait(int millisecondsToWait, int timeout = 30000) + { + int totalTimeTaken = 0; + bool isOperationInfoThere = false; + do + { + totalTimeTaken += millisecondsToWait; + await Task.Delay(millisecondsToWait); + foreach (ClientTelemetryProperties telemetryData in this.actualInfo) + { + isOperationInfoThere = telemetryData.OperationInfo.Count > 0; + } + + if(!isOperationInfoThere && totalTimeTaken >= timeout) + { + throw new TimeoutException("Timeout happens, as operation info is not there, even after " + totalTimeTaken + "Ms"); + } + + } while (!isOperationInfoThere); + } + private static ItemBatchOperation CreateItem(string itemId) { var testItem = new { id = itemId, Status = itemId }; return new ItemBatchOperation(Documents.OperationType.Create, 0, new Cosmos.PartitionKey(itemId), itemId, TestCommon.SerializerCore.ToStream(testItem)); } + private async Task GetContainer(ConnectionMode mode) + { + if (mode == ConnectionMode.Direct) + { + this.cosmosClient = this.cosmosClientBuilder.WithConnectionModeDirect().Build(); + } + + if (mode == ConnectionMode.Gateway) + { + this.cosmosClient = this.cosmosClientBuilder.WithConnectionModeGateway().Build(); + } + + this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); + return await this.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); + } + } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs index d65adb6c18..bef18208cc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs @@ -103,7 +103,7 @@ public void CheckMetricsAggregationLogicWithAdjustment() public void CheckJsonSerializerContract() { string json = JsonConvert.SerializeObject(new ClientTelemetryProperties("clientId", "", null, ConnectionMode.Direct, null), ClientTelemetryOptions.JsonSerializerSettings); - Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"Direct\",\"systemInfo\":[]}",json); + Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"systemInfo\":[]}",json); } [TestMethod] @@ -114,7 +114,7 @@ public void CheckJsonSerializerContractWithPreferredRegions() "region1" }; string json = JsonConvert.SerializeObject(new ClientTelemetryProperties("clientId", "", null, ConnectionMode.Direct, preferredRegion), ClientTelemetryOptions.JsonSerializerSettings); - Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"Direct\",\"systemInfo\":[],\"preferredRegions\":[\"region1\"]}", json); + Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"systemInfo\":[],\"preferredRegions\":[\"region1\"]}", json); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs index 231fdf3693..2a5ef4cb81 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs @@ -63,8 +63,8 @@ public void HandlerOrderIfTelemetryIsEnabled() { typeof(RequestInvokerHandler), typeof(DiagnosticsHandler), - typeof(RetryHandler), typeof(TelemetryHandler), + typeof(RetryHandler), typeof(RouterHandler) };