/// <summary> /// Gets the associated Rate and calculates the monthly estimates for the specified Meter details /// </summary> /// <param name="meterCategory">Meter Category of the Meter</param> /// <param name="meterSubCategory">Meter SubCategory of the Meter</param> /// <param name="meterName">Meter Name of the Meter</param> /// <param name="region">Azure Location as per Pricing Specs</param> /// <param name="quantity">Quantity of the resource usage in a month</param> /// <param name="rate">Rate will be set based on the associated meter in CSP Rate Card</param> /// <param name="log">The object that will contain the exception messages</param> /// <param name="nameOfResource">Name of the Azure resource</param> /// <returns> Returns the Monthly Cost for the resource</returns> private static double GetResourceRate(string meterCategory, string meterSubCategory, string meterName, string region, double quantity, out double rate, ref StringBuilder log, string nameOfResource) { double totalCost = 0; rate = 0; try { // If any meter fields are missing throw an exception if (meterCategory == null) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMeterRateFetchFailed("MeterCategory is null", nameOfResource)); } if (meterSubCategory == null) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMeterRateFetchFailed("MeterSubCategory is null", nameOfResource)); } if (meterName == null) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMeterRateFetchFailed("MeterName is null", nameOfResource)); } if (region == null) { throw new Exception(ExceptionLogger.GenerateLoggerTextForMeterRateFetchFailed("Region is null", nameOfResource)); } // Fetch the rate for the resource component by matching the meter fields provided Meter ratesForComponent = meterList.Find(x => meterCategory.Equals(x.MeterCategory, StringComparison.OrdinalIgnoreCase) && meterSubCategory.Equals(x.MeterSubCategory, StringComparison.OrdinalIgnoreCase) && meterName.Equals(x.MeterName, StringComparison.OrdinalIgnoreCase) && region.Equals(x.MeterRegion, StringComparison.OrdinalIgnoreCase)); // If the Meter is missing in CSP Rate Card, check if there is a global rate (Rate without region specified) if (ratesForComponent == null) { ratesForComponent = meterList.Find(x => meterCategory.Equals(x.MeterCategory, StringComparison.OrdinalIgnoreCase) && meterSubCategory.Equals(x.MeterSubCategory, StringComparison.OrdinalIgnoreCase) && meterName.Equals(x.MeterName, StringComparison.OrdinalIgnoreCase) && x.MeterRegion.Equals(string.Empty, StringComparison.OrdinalIgnoreCase)); } // Check if Meter found if (ratesForComponent != null) { // Fetch the Rates from the meter found OrderedDictionary meterRates = ratesForComponent.MeterRates; // If consumed quantity if less that included quantity, set rate and cost to zero if (quantity <= ratesForComponent.IncludedQuantity) { totalCost = 0; rate = 0; } else if (meterRates.Count == 1) { // If linear rating, Calculate Monthly Cost as quantity x rate rate = (double)meterRates[0]; totalCost = (quantity - ratesForComponent.IncludedQuantity) * rate; } else { // If tiered rating, calculate Monthly Cost based on tiered pricing double quantitytobeRated = quantity - ratesForComponent.IncludedQuantity; totalCost = 0; for (int i = 1; i < meterRates.Count; i++) { string currentKeyString = (string)meterRates.Cast <DictionaryEntry>().ElementAt(i).Key; string previousKeyString = (string)meterRates.Cast <DictionaryEntry>().ElementAt(i - 1).Key; double currentKey = double.Parse(currentKeyString); double previousKey = double.Parse(previousKeyString); if (quantitytobeRated <= currentKey) { totalCost = totalCost + ((quantitytobeRated - previousKey) * (double)meterRates[i - 1]); rate = (double)meterRates[i - 1]; break; } else { totalCost = totalCost + ((currentKey - previousKey) * (double)meterRates[i - 1]); if (i == meterRates.Count - 1) { totalCost = totalCost + ((quantitytobeRated - currentKey) * (double)meterRates[i]); rate = (double)meterRates[i]; } } } } } else { // Meter for specified parameters not found, Throw an exception throw new Exception(ExceptionLogger.GenerateLoggerTextForMeterRateFetchFailed(string.Format("Meter not found in Rate Card. MeterCategory:{0},MeterSubCategory:{1},MeterName:{2},Region:{3} ", meterCategory, meterSubCategory, meterName, region), nameOfResource)); } } catch (Exception ex) { totalCost = 0; log.AppendLine(ex.Message); } return(totalCost); }