Exemple #1
0
        public async Task TimeSeriesInsightsTypeWithCategoricalVariable_ExpectsError()
        {
            // Arrange
            TimeSeriesInsightsClient client      = GetClient();
            TimeSeriesInsightsTypes  typesClient = client.GetTypesClient();
            var    timeSeriesTypes     = new List <TimeSeriesType>();
            var    tsiTypeNamePrefix   = "type";
            var    timeSeriesTypesName = Recording.GenerateAlphaNumericId(tsiTypeNamePrefix);
            string timeSeriesTypeId    = Recording.GenerateId();

            // Build Numeric variable
            // Below is an invalid expression
            var categoricalValue    = new TimeSeriesExpression("$event");
            var category            = new TimeSeriesDefaultCategory("label");
            var categoricalVariable = new CategoricalVariable(categoricalValue, category);
            var variables           = new Dictionary <string, TimeSeriesVariable>();
            var variableNamePrefix  = "categoricalVariableName";

            variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), categoricalVariable);

            var type = new TimeSeriesType(timeSeriesTypesName, variables)
            {
                Id = timeSeriesTypeId
            };

            timeSeriesTypes.Add(type);

            // Act and Assert
            await TestTimeSeriesTypeWhereErrorIsExpected(typesClient, timeSeriesTypes, timeSeriesTypesName).ConfigureAwait(false);
        }
Exemple #2
0
        private static async Task TestTimeSeriesTypeWhereErrorIsExpected(TimeSeriesInsightsTypes typesClient, List <TimeSeriesType> timeSeriesTypes, string timeSeriesTypesName)
        {
            // create numeric type and expect failure due to invalid input expression
            Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient
                                                                           .CreateOrReplaceAsync(timeSeriesTypes)
                                                                           .ConfigureAwait(false);

            // Assert that the result error array does not contain an error
            createTypesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error != null);

            // Get the type by name and expect error
            Response <TimeSeriesTypeOperationResult[]> getTypesByNamesResult = await typesClient
                                                                               .GetByNameAsync(new string[] { timeSeriesTypesName })
                                                                               .ConfigureAwait(false);

            getTypesByNamesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error != null);

            // Delete the type by name and expect error
            Response <TimeSeriesOperationError[]> deleteTypesResponse = await typesClient
                                                                        .DeleteByNameAsync(new string[] { timeSeriesTypesName })
                                                                        .ConfigureAwait(false);

            // Response is null even when type does not exist.
            deleteTypesResponse.Value.Should().OnlyContain((errorResult) => errorResult == null);
        }
Exemple #3
0
        private async Task <string> createTimeSeriesTypeAsync(TimeSeriesInsightsClient client)
        {
            TimeSeriesInsightsTypes typesClient = client.GetTypesClient();
            var    timeSeriesTypes     = new List <TimeSeriesType>();
            var    tsiTypeNamePrefix   = "type";
            var    timeSeriesTypesName = Recording.GenerateAlphaNumericId(tsiTypeNamePrefix);
            string timeSeriesTypeId    = Recording.GenerateId();

            // Build aggregate variable
            var countExpression    = new TimeSeriesExpression("count()");
            var aggregateVariable  = new AggregateVariable(countExpression);
            var variables          = new Dictionary <string, TimeSeriesVariable>();
            var variableNamePrefix = "aggregateVariable";

            variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), aggregateVariable);

            var type = new TimeSeriesType(timeSeriesTypesName, variables)
            {
                Id = timeSeriesTypeId
            };

            timeSeriesTypes.Add(type);

            Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient
                                                                           .CreateOrReplaceAsync(timeSeriesTypes)
                                                                           .ConfigureAwait(false);

            createTypesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error == null);

            return(timeSeriesTypeId);
        }
Exemple #4
0
        public async Task TimeSeriesInsightsClient_ModelSettingsTest()
        {
            TimeSeriesInsightsClient        client = GetClient();
            TimeSeriesInsightsModelSettings modelSettingsClient = client.GetModelSettingsClient();
            TimeSeriesInsightsTypes         typesClient         = client.GetTypesClient();

            // GET model settings
            Response <TimeSeriesModelSettings> currentSettings = await modelSettingsClient.GetAsync().ConfigureAwait(false);

            currentSettings.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK);
            string testName = "testModel";
            // UPDATE model settings
            string typeId = await createTimeSeriesTypeAsync(client).ConfigureAwait(false);

            string defaultTypeId = await getDefaultTypeIdAsync(modelSettingsClient).ConfigureAwait(false);

            try
            {
                Response <TimeSeriesModelSettings> updatedSettingsName = await modelSettingsClient.UpdateNameAsync(testName).ConfigureAwait(false);

                updatedSettingsName.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK);
                updatedSettingsName.Value.Name.Should().Be(testName);

                await TestRetryHelper.RetryAsync <Response <TimeSeriesModelSettings> >(async() =>
                {
                    Response <TimeSeriesModelSettings> updatedSettingsId = await modelSettingsClient.UpdateDefaultTypeIdAsync(typeId).ConfigureAwait(false);
                    updatedSettingsId.Value.DefaultTypeId.Should().Be(typeId);

                    // update it back to the default Type Id
                    updatedSettingsId = await modelSettingsClient.UpdateDefaultTypeIdAsync(defaultTypeId).ConfigureAwait(false);
                    updatedSettingsId.Value.DefaultTypeId.Should().Be(defaultTypeId);

                    return(null);
                }, MaxNumberOfRetries, s_retryDelay);
            }
            finally
            {
                // clean up
                try
                {
                    Response <TimeSeriesOperationError[]> deleteTypesResponse = await typesClient
                                                                                .DeleteByIdAsync(new string[] { typeId })
                                                                                .ConfigureAwait(false);

                    // Assert that the response array does not have any error object set
                    deleteTypesResponse.Value.Should().OnlyContain((errorResult) => errorResult == null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Test clean up failed: {ex.Message}");
                    throw;
                }
            }
        }
        /// <summary>
        /// This sample demonstrates getting Time Series model settings, updating model settings and changing the default type Id for a model.
        /// </summary>
        public async Task RunSamplesAsync(TimeSeriesInsightsClient client)
        {
            PrintHeader("TIME SERIES INSIGHTS MODEL SETTINGS SAMPLE");

            #region Snippet:TimeSeriesInsightsSampleGetModelSettings
            TimeSeriesInsightsModelSettings    modelSettingsClient      = client.GetModelSettingsClient();
            TimeSeriesInsightsTypes            typesClient              = client.GetTypesClient();
            Response <TimeSeriesModelSettings> getModelSettingsResponse = await modelSettingsClient.GetAsync();

            Console.WriteLine($"Retrieved Time Series Insights model settings \nname : '{getModelSettingsResponse.Value.Name}', " +
                              $"default type Id: {getModelSettingsResponse.Value.DefaultTypeId}'");
            IReadOnlyList <TimeSeriesIdProperty> timeSeriesIdProperties = getModelSettingsResponse.Value.TimeSeriesIdProperties;
            foreach (TimeSeriesIdProperty property in timeSeriesIdProperties)
            {
                Console.WriteLine($"Time Series Id property name : '{property.Name}', type : '{property.PropertyType}'.");
            }
            #endregion Snippet:TimeSeriesInsightsSampleGetModelSettings

            // Store the default type Id so it can be used during clean up
            string defaultTypeId = getModelSettingsResponse.Value.DefaultTypeId;

            #region Snippet:TimeSeriesInsightsSampleUpdateModelSettingsName
            Response <TimeSeriesModelSettings> updateModelSettingsNameResponse = await modelSettingsClient.UpdateNameAsync("NewModelSettingsName");

            Console.WriteLine($"Updated Time Series Insights model settings name: " +
                              $"{updateModelSettingsNameResponse.Value.Name}");
            #endregion Snippet:TimeSeriesInsightsSampleUpdateModelSettingsName

            // For every Time Series Insights environment, there is a default type that any newly created Time Series instance will be associated with.
            // You can change the default type for a TSI environment by creating a new type and calling the API to update the default type Id.

            // Create a Time Series type.
            var aggregateVariable = new AggregateVariable(new TimeSeriesExpression("count()"));
            var variables         = new Dictionary <string, TimeSeriesVariable>
            {
                { "aggregateVariableName", aggregateVariable },
            };
            var type            = new TimeSeriesType("tsiTypeName", variables);
            var timeSeriesTypes = new List <TimeSeriesType> {
                type
            };
            string tsiTypeId = null;
            Response <TimeSeriesTypeOperationResult[]> createTsiTypeResponse = await typesClient
                                                                               .CreateOrReplaceAsync(timeSeriesTypes);

            // Ensure no error was reported as part of the response
            if (createTsiTypeResponse.Value[0].Error == null)
            {
                // Store the Time Series type id to use it for updating default type in model settings
                tsiTypeId = createTsiTypeResponse.Value[0].TimeSeriesType.Id;

                #region Snippet:TimeSeriesInsightsSampleUpdateModelSettingsDefaultType
                Response <TimeSeriesModelSettings> updateDefaultTypeIdResponse = await modelSettingsClient
                                                                                 .UpdateDefaultTypeIdAsync(tsiTypeId);

                Console.WriteLine($"Updated Time Series Insights model settings default type Id: " +
                                  $"{updateDefaultTypeIdResponse.Value.Name}");
                #endregion Snippet:TimeSeriesInsightsSampleUpdateModelSettingsDefaultType
            }
            // Clean up
            try
            {
                // Revert back to the original default type Id
                await modelSettingsClient
                .UpdateDefaultTypeIdAsync(defaultTypeId);

                // Delete the type created
                if (tsiTypeId != null)
                {
                    await typesClient
                    .DeleteByIdAsync(new List <string> {
                        tsiTypeId
                    });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed at one of the clean up steps: {ex.Message}");
            }
        }
Exemple #6
0
        private async Task RunQuerySeriesSampleWithPreDefinedVariables(TimeSeriesInsightsClient client, TimeSeriesId tsId)
        {
            // Setup
            TimeSeriesInsightsInstances instancesClient = client.GetInstancesClient();
            TimeSeriesInsightsTypes     typesClient     = client.GetTypesClient();
            TimeSeriesInsightsQueries   queriesClient   = client.GetQueriesClient();

            // First create the Time Series type along with the numeric variables
            var timeSeriesTypes = new List <TimeSeriesType>();

            var celsiusVariable = new NumericVariable(
                new TimeSeriesExpression("$event.Temperature"),
                new TimeSeriesExpression("avg($value)"));
            var fahrenheitVariable = new NumericVariable(
                new TimeSeriesExpression("$event.Temperature * 1.8 + 32"),
                new TimeSeriesExpression("avg($value)"));

            var celsiusVariableName    = "TemperatureInCelsius";
            var fahrenheitVariableName = "TemperatureInFahrenheit";
            var variables = new Dictionary <string, TimeSeriesVariable>
            {
                { celsiusVariableName, celsiusVariable },
                { fahrenheitVariableName, fahrenheitVariable }
            };

            timeSeriesTypes.Add(new TimeSeriesType("TemperatureSensor", variables)
            {
                Id = "TemperatureSensorTypeId"
            });

            Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient
                                                                           .CreateOrReplaceAsync(timeSeriesTypes)
                                                                           .ConfigureAwait(false);

            if (createTypesResult.Value.First().Error != null)
            {
                Console.WriteLine($"\n\nFailed to create a Time Series Insights type. " +
                                  $"Error Message: '{createTypesResult.Value.First().Error.Message}.' " +
                                  $"Code: '{createTypesResult.Value.First().Error.Code}'.");
            }

            // Get the Time Series instance and replace its type with the one we just created
            Response <InstancesOperationResult[]> getInstanceResult = await instancesClient
                                                                      .GetAsync(new List <TimeSeriesId> {
                tsId
            });

            if (getInstanceResult.Value.First().Error != null)
            {
                Console.WriteLine($"\n\nFailed to retrieve Time Series instance with Id '{tsId}'. " +
                                  $"Error Message: '{getInstanceResult.Value.First().Error.Message}.' " +
                                  $"Code: '{getInstanceResult.Value.First().Error.Code}'.");
            }

            TimeSeriesInstance instanceToReplace = getInstanceResult.Value.First().Instance;

            instanceToReplace.TypeId = createTypesResult.Value.First().TimeSeriesType.Id;
            Response <InstancesOperationResult[]> replaceInstanceResult = await instancesClient
                                                                          .ReplaceAsync(new List <TimeSeriesInstance> {
                instanceToReplace
            });

            if (replaceInstanceResult.Value.First().Error != null)
            {
                Console.WriteLine($"\n\nFailed to retrieve Time Series instance with Id '{tsId}'. " +
                                  $"Error Message: '{replaceInstanceResult.Value.First().Error.Message}.' " +
                                  $"Code: '{replaceInstanceResult.Value.First().Error.Code}'.");
            }

            // Now that we set up the instance with the property type, query for the data
            #region Snippet:TimeSeriesInsightsSampleQuerySeries
            Console.WriteLine($"\n\nQuery for temperature series in Celsius and Fahrenheit over the past 10 minutes. " +
                              $"The Time Series instance belongs to a type that has predefined numeric variable that represents the temperature " +
                              $"in Celsuis, and a predefined numeric variable that represents the temperature in Fahrenheit.\n");

            DateTimeOffset endTime     = DateTime.UtcNow;
            DateTimeOffset startTime   = endTime.AddMinutes(-10);
            QueryAnalyzer  seriesQuery = queriesClient.CreateSeriesQuery(
                tsId,
                startTime,
                endTime);

            await foreach (TimeSeriesPoint point in seriesQuery.GetResultsAsync())
            {
                double?tempInCelsius    = point.GetNullableDouble(celsiusVariableName);
                double?tempInFahrenheit = point.GetNullableDouble(fahrenheitVariableName);

                Console.WriteLine($"{point.Timestamp} - Average temperature in Celsius: {tempInCelsius}. " +
                                  $"Average temperature in Fahrenheit: {tempInFahrenheit}.");
            }
            #endregion Snippet:TimeSeriesInsightsSampleQuerySeries
        }
        /// <summary>
        /// This sample demonstrates usage of Time Series Insights types APIs.
        /// </summary>
        public async Task RunSamplesAsync(TimeSeriesInsightsClient client)
        {
            // For the purpose of keeping code snippets readable to the user, hardcoded string literals are used in place of assigned variables, eg Ids.
            // Despite not being a good code practice, this prevents code snippets from being out of context for the user when making API calls that accept Ids as parameters.

            PrintHeader("TIME SERIES INSIGHTS TYPES SAMPLE");

            #region Snippet:TimeSeriesInsightsSampleCreateType
            TimeSeriesInsightsTypes typesClient = client.GetTypesClient();

            // Create a type with an aggregate variable
            var timeSeriesTypes = new List <TimeSeriesType>();

            var countExpression   = new TimeSeriesExpression("count()");
            var aggregateVariable = new AggregateVariable(countExpression);
            var variables         = new Dictionary <string, TimeSeriesVariable>();
            variables.Add("aggregateVariable", aggregateVariable);

            timeSeriesTypes.Add(new TimeSeriesType("Type1", variables)
            {
                Id = "Type1Id"
            });
            timeSeriesTypes.Add(new TimeSeriesType("Type2", variables)
            {
                Id = "Type2Id"
            });

            Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient
                                                                           .CreateOrReplaceAsync(timeSeriesTypes);

            // The response of calling the API contains a list of error objects corresponding by position to the input parameter array in the request.
            // If the error object is set to null, this means the operation was a success.
            for (int i = 0; i < createTypesResult.Value.Length; i++)
            {
                if (createTypesResult.Value[i].Error == null)
                {
                    Console.WriteLine($"Created Time Series type successfully.");
                }
                else
                {
                    Console.WriteLine($"Failed to create a Time Series Insights type: {createTypesResult.Value[i].Error.Message}.");
                }
            }
            #endregion Snippet:TimeSeriesInsightsSampleCreateType

            #region Snippet:TimeSeriesInsightsSampleGetTypeById
            // Code snippet below shows getting a default Type using Id
            // The default type Id can be obtained programmatically by using the ModelSettings client.

            TimeSeriesInsightsModelSettings modelSettingsClient = client.GetModelSettingsClient();
            TimeSeriesModelSettings         modelSettings       = await modelSettingsClient.GetAsync();

            Response <TimeSeriesTypeOperationResult[]> getTypeByIdResults = await typesClient
                                                                            .GetByIdAsync(new string[] { modelSettings.DefaultTypeId });

            // The response of calling the API contains a list of type or error objects corresponding by position to the input parameter array in the request.
            // If the error object is set to null, this means the operation was a success.
            for (int i = 0; i < getTypeByIdResults.Value.Length; i++)
            {
                if (getTypeByIdResults.Value[i].Error == null)
                {
                    Console.WriteLine($"Retrieved Time Series type with Id: '{getTypeByIdResults.Value[i].TimeSeriesType.Id}'.");
                }
                else
                {
                    Console.WriteLine($"Failed to retrieve a Time Series type due to '{getTypeByIdResults.Value[i].Error.Message}'.");
                }
            }
            #endregion Snippet:TimeSeriesInsightsSampleGetTypeById

            #region Snippet:TimeSeriesInsightsSampleReplaceType
            // Update variables with adding a new variable
            foreach (TimeSeriesType type in timeSeriesTypes)
            {
                type.Description = "Description";
            }

            Response <TimeSeriesTypeOperationResult[]> updateTypesResult = await typesClient
                                                                           .CreateOrReplaceAsync(timeSeriesTypes);

            // The response of calling the API contains a list of error objects corresponding by position to the input parameter array in the request.
            // If the error object is set to null, this means the operation was a success.
            for (int i = 0; i < updateTypesResult.Value.Length; i++)
            {
                if (updateTypesResult.Value[i].Error == null)
                {
                    Console.WriteLine($"Updated Time Series type successfully.");
                }
                else
                {
                    Console.WriteLine($"Failed to update a Time Series Insights type due to: {updateTypesResult.Value[i].Error.Message}.");
                }
            }
            #endregion Snippet:TimeSeriesInsightsSampleReplaceType

            #region Snippet:TimeSeriesInsightsSampleGetAllTypes
            // Get all Time Series types in the environment
            AsyncPageable <TimeSeriesType> getAllTypesResponse = typesClient.GetTypesAsync();

            await foreach (TimeSeriesType tsiType in getAllTypesResponse)
            {
                Console.WriteLine($"Retrieved Time Series Insights type with Id: '{tsiType?.Id}' and Name: '{tsiType?.Name}'");
            }
            #endregion Snippet:TimeSeriesInsightsSampleGetAllTypes

            // Clean up
            try
            {
                #region Snippet:TimeSeriesInsightsSampleDeleteTypeById

                // Delete Time Series types with Ids

                var typesIdsToDelete = new List <string> {
                    "Type1Id", " Type2Id"
                };
                Response <TimeSeriesOperationError[]> deleteTypesResponse = await typesClient
                                                                            .DeleteByIdAsync(typesIdsToDelete);

                // The response of calling the API contains a list of error objects corresponding by position to the input parameter
                // array in the request. If the error object is set to null, this means the operation was a success.
                foreach (var result in deleteTypesResponse.Value)
                {
                    if (result != null)
                    {
                        Console.WriteLine($"Failed to delete a Time Series Insights type: {result.Message}.");
                    }
                    else
                    {
                        Console.WriteLine($"Deleted a Time Series Insights type successfully.");
                    }
                }
                #endregion Snippet:TimeSeriesInsightsSampleDeleteTypeById
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Failed to delete Time Series Insights type: {ex.Message}");
            }
        }
Exemple #8
0
        public async Task TimeSeriesInsightsTypes_Lifecycle()
        {
            // Arrange
            TimeSeriesInsightsClient client      = GetClient();
            TimeSeriesInsightsTypes  typesClient = client.GetTypesClient();
            var timeSeriesTypes           = new List <TimeSeriesType>();
            var tsiTypeNamePrefix         = "type";
            int numOfTypesCreated         = 0;
            var timeSeriesTypesProperties = new Dictionary <string, string>
            {
                { Recording.GenerateAlphaNumericId(tsiTypeNamePrefix), Recording.GenerateId() },
                { Recording.GenerateAlphaNumericId(tsiTypeNamePrefix), Recording.GenerateId() }
            };

            // Build aggregate variable
            var countExpression    = new TimeSeriesExpression("count()");
            var aggregateVariable  = new AggregateVariable(countExpression);
            var variables          = new Dictionary <string, TimeSeriesVariable>();
            var variableNamePrefix = "aggregateVariable";

            variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), aggregateVariable);

            foreach (KeyValuePair <string, string> property in timeSeriesTypesProperties)
            {
                var type = new TimeSeriesType(property.Key, variables)
                {
                    Id = property.Value
                };
                timeSeriesTypes.Add(type);
                numOfTypesCreated++;
            }

            // Act and assert
            try
            {
                // Get all Time Series types in the environment
                AsyncPageable <TimeSeriesType> getAllTypesResponse = typesClient.GetTypesAsync();

                await foreach (TimeSeriesType tsiType in getAllTypesResponse)
                {
                    tsiType.Should().NotBeNull();
                }

                // Create Time Series types
                Response <TimeSeriesTypeOperationResult[]> createTypesResult = await typesClient
                                                                               .CreateOrReplaceAsync(timeSeriesTypes)
                                                                               .ConfigureAwait(false);

                // Assert that the result error array does not contain any object that is set
                createTypesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error == null);
                Response <TimeSeriesTypeOperationResult[]> getTypesByNamesResult;

                // This retry logic was added as the TSI types are not immediately available after creation
                await TestRetryHelper.RetryAsync <Response <TimeSeriesTypeOperationResult[]> >(async() =>
                {
                    // Get the created types by names
                    getTypesByNamesResult = await typesClient
                                            .GetByNameAsync(timeSeriesTypesProperties.Keys)
                                            .ConfigureAwait(false);

                    getTypesByNamesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error == null);
                    getTypesByNamesResult.Value.Length.Should().Be(timeSeriesTypes.Count);
                    foreach (TimeSeriesTypeOperationResult typesResult in getTypesByNamesResult.Value)
                    {
                        typesResult.Error.Should().BeNull();
                        typesResult.TimeSeriesType.Should().NotBeNull();
                        typesResult.TimeSeriesType.Id.Should().NotBeNullOrEmpty();
                        typesResult.TimeSeriesType.Variables.Count.Should().Be(1);
                        typesResult.TimeSeriesType.Variables.IsSameOrEqualTo(variables);
                    }
                    return(null);
                }, MaxNumberOfRetries, s_retryDelay);

                // Update variables with adding a new variable
                foreach (TimeSeriesType type in timeSeriesTypes)
                {
                    type.Description = "Description";
                }

                Response <TimeSeriesTypeOperationResult[]> updateTypesResult = await typesClient
                                                                               .CreateOrReplaceAsync(timeSeriesTypes)
                                                                               .ConfigureAwait(false);

                updateTypesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error == null);
                updateTypesResult.Value.Length.Should().Be(timeSeriesTypes.Count);

                // This retry logic was added as the TSI types are not immediately available after creation
                await TestRetryHelper.RetryAsync <Response <TimeSeriesTypeOperationResult[]> >(async() =>
                {
                    // Get type by Id
                    Response <TimeSeriesTypeOperationResult[]> getTypeByIdResult = await typesClient
                                                                                   .GetByIdAsync(timeSeriesTypesProperties.Values)
                                                                                   .ConfigureAwait(false);

                    getTypeByIdResult.Value.Length.Should().Be(numOfTypesCreated);
                    foreach (TimeSeriesTypeOperationResult typeOperationResult in getTypeByIdResult.Value)
                    {
                        typeOperationResult.TimeSeriesType.Should().NotBeNull();
                        typeOperationResult.Error.Should().BeNull();
                        typeOperationResult.TimeSeriesType.Name.Should().StartWith(tsiTypeNamePrefix);
                        typeOperationResult.TimeSeriesType.Id.Should().NotBeNull();
                    }

                    return(null);
                }, MaxNumberOfRetries, s_retryDelay);
            }
            finally
            {
                // clean up
                try
                {
                    Response <TimeSeriesOperationError[]> deleteTypesResponse = await typesClient
                                                                                .DeleteByIdAsync(timeSeriesTypesProperties.Values)
                                                                                .ConfigureAwait(false);

                    // Assert that the response array does not have any error object set
                    deleteTypesResponse.Value.Should().OnlyContain((errorResult) => errorResult == null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Test clean up failed: {ex.Message}");
                    throw;
                }
            }
        }