/// <summary> /// Reads data from the usage REST API. /// </summary> /// <param name="startDate">Start date - get usage date from this date</param> /// <param name="endDate">End date - get usage data to this date</param> /// <param name="granularity">The granularity - daily or hourly</param> /// <param name="showDetails">Include instance-level details or not</param> /// <returns>the usage data for the given time range with the given granularity</returns> public async Task <UsageData> GetAsync(DateTime startDate, DateTime endDate, AggregationGranularity granularity, bool showDetails) { if (startDate >= endDate) { throw new ArgumentException("Start date must be before the end date!"); } if (endDate >= DateTime.Now.AddHours(-1)) { endDate = DateTime.Now.AddHours(-1).ToUniversalTime(); } var startTime = new DateTime(startDate.Year, startDate.Month, startDate.Day, 0, 0, 0, DateTimeKind.Utc); var endTime = new DateTime(endDate.Year, endDate.Month, endDate.Day, 0, 0, 0, DateTimeKind.Utc); if (granularity == AggregationGranularity.Hourly) { startTime = startTime.AddHours(startDate.Hour); endTime = endTime.AddHours(endDate.Hour); } var st = WebUtility.UrlEncode(startTime.ToString("yyyy-MM-ddTHH:mm:sszzz")); var et = WebUtility.UrlEncode(endTime.ToString("yyyy-MM-ddTHH:mm:sszzz")); var url = $"https://management.azure.com/subscriptions/{Subscription.SubscriptionId}" + $"/providers/Microsoft.Commerce/UsageAggregates" + $"?api-version={APIVERSION}" + $"&reportedStartTime={st}&reportedEndTime={et}" + $"&aggregationGranularity={granularity.ToString()}" + $"&showDetails={showDetails.ToString().ToLower()}"; var data = await GetDataAsync(url); if (String.IsNullOrEmpty(data)) { return(null); } var usageData = JsonConvert.DeserializeObject <UsageData>(data); // read data from the usagedata api as long as the continuationtoken is set. // usage data api returns 1000 values per api call, to receive all values, // we have to call the url stored in nextLink property. while (!String.IsNullOrEmpty(usageData.NextLink)) { var next = await GetDataAsync(usageData.NextLink); var nextUsageData = JsonConvert.DeserializeObject <UsageData>(next); usageData.Values.AddRange(nextUsageData.Values); usageData.NextLink = nextUsageData.NextLink; } return(usageData); }
/// <summary> /// Reads data from the usage REST API. /// </summary> /// <param name="startDate">Start date - get usage date from this date</param> /// <param name="endDate">End date - get usage data to this date</param> /// <param name="granularity">The granularity - daily or hourly</param> /// <param name="showDetails">Include instance-level details or not</param> /// <param name="token">the OAuth token</param> /// <returns>the usage data for the given time range with the given granularity</returns> public Usage.UsageData GetUsageData(DateTime startDate, DateTime endDate, AggregationGranularity granularity, bool showDetails, string token = null) { var uclient = new UsageClient(Tenant, ClientId, ClientSecret, SubscriptionId, RedirectUrl); if (string.IsNullOrEmpty(token)) { return(uclient.Get(startDate, endDate, granularity, showDetails)); } return(uclient.Get(startDate, endDate, granularity, showDetails, token)); }
/// <summary> /// Convert an enum of type AggregationGranularity to a string. /// </summary> /// <param name='value'> /// The value to convert to a string. /// </param> /// <returns> /// The enum value as a string. /// </returns> internal static string AggregationGranularityToString(AggregationGranularity value) { if (value == AggregationGranularity.Daily) { return("Daily"); } if (value == AggregationGranularity.Hourly) { return("Hourly"); } throw new ArgumentOutOfRangeException("value"); }
public static string GetReportingUri(string billingServiceURL, string subscriptionId, DateTime from, DateTime to, AggregationGranularity granularity = AggregationGranularity.Daily, bool showDetails = true) { Func <DateTime, DateTime> cleanStartTime = (_) => { _ = _.ToUniversalTime(); return(new DateTime( year: _.Year, month: _.Month, day: _.Day, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Utc) .ToUniversalTime()); }; Func <DateTime, DateTime> cleanEndTime = (_) => { _ = _.AddDays(1).AddMilliseconds(-1).ToUniversalTime(); return(new DateTime( year: _.Year, month: _.Month, day: _.Day, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Utc) .ToUniversalTime()); }; const string dateTimeFormat = "yyyy-MM-dd HH:mm:ssZ"; string requestURL = new Uri(string.Format("{0}/subscriptions/{1}/providers/Microsoft.Commerce/UsageAggregates", billingServiceURL, subscriptionId)) .AddQuery("api-version", "2015-06-01-preview") .AddQuery("reportedstartTime", cleanStartTime(from).ToString(dateTimeFormat)) .AddQuery("reportedEndTime", cleanEndTime(to).ToString(dateTimeFormat)) .AddQuery("aggregationGranularity", granularity == AggregationGranularity.Daily ? "Daily" : "Hourly") .AddQuery("showDetails", showDetails ? "true" : "false") .AbsoluteUri; return(requestURL); }
/// <summary> /// Query aggregated Azure subscription consumption data for a date /// range. (see /// https://msdn.microsoft.com/library/azure/1ea5b323-54bb-423d-916f-190de96c6a3c /// for more information) /// </summary> /// <param name='reportedStartTime'> /// Required. The start of the time range to retrieve data for. /// </param> /// <param name='reportedEndTime'> /// Required. The end of the time range to retrieve data for. /// </param> /// <param name='aggregationGranularity'> /// Required. Value is either daily (default) or hourly to tell the API /// how to return the results grouped by day or hour. /// </param> /// <param name='showDetails'> /// Required. When set to true (default), the aggregates are broken /// down into the instance metadata which is more granular. /// </param> /// <param name='continuationToken'> /// Optional. Retrieved from previous calls, this is the bookmark used /// for progress when the responses are paged. /// </param> /// <param name='cancellationToken'> /// Cancellation token. /// </param> /// <returns> /// The Get UsageAggregates operation response. /// </returns> public async Task <UsageAggregationGetResponse> GetAsync(DateTime reportedStartTime, DateTime reportedEndTime, AggregationGranularity aggregationGranularity, bool showDetails, string continuationToken, CancellationToken cancellationToken) { // Validate // Tracing bool shouldTrace = TracingAdapter.IsEnabled; string invocationId = null; if (shouldTrace) { invocationId = TracingAdapter.NextInvocationId.ToString(); Dictionary <string, object> tracingParameters = new Dictionary <string, object>(); tracingParameters.Add("reportedStartTime", reportedStartTime); tracingParameters.Add("reportedEndTime", reportedEndTime); tracingParameters.Add("aggregationGranularity", aggregationGranularity); tracingParameters.Add("showDetails", showDetails); tracingParameters.Add("continuationToken", continuationToken); TracingAdapter.Enter(invocationId, this, "GetAsync", tracingParameters); } // Construct URL string url = ""; url = url + "subscriptions/"; if (this.Client.Credentials.SubscriptionId != null) { url = url + Uri.EscapeDataString(this.Client.Credentials.SubscriptionId); } url = url + "/providers/Microsoft.Commerce/UsageAggregates"; List <string> queryParameters = new List <string>(); queryParameters.Add("api-version=2015-06-01-preview"); queryParameters.Add("reportedstartTime=" + Uri.EscapeDataString(reportedStartTime.ToString("O"))); queryParameters.Add("reportedEndTime=" + Uri.EscapeDataString(reportedEndTime.ToString("O"))); queryParameters.Add("showDetails=" + Uri.EscapeDataString(showDetails.ToString().ToLower())); queryParameters.Add("aggregationGranularity=" + Uri.EscapeDataString(UsageAggregationManagementClient.AggregationGranularityToString(aggregationGranularity))); if (continuationToken != null) { queryParameters.Add("continuationToken=" + Uri.EscapeDataString(continuationToken)); } if (queryParameters.Count > 0) { url = url + "?" + string.Join("&", queryParameters); } string baseUrl = this.Client.BaseUri.AbsoluteUri; // Trim '/' character from the end of baseUrl and beginning of url. if (baseUrl[baseUrl.Length - 1] == '/') { baseUrl = baseUrl.Substring(0, baseUrl.Length - 1); } if (url[0] == '/') { url = url.Substring(1); } url = baseUrl + "/" + url; url = url.Replace(" ", "%20"); // Create HTTP transport objects HttpRequestMessage httpRequest = null; try { httpRequest = new HttpRequestMessage(); httpRequest.Method = HttpMethod.Get; httpRequest.RequestUri = new Uri(url); // Set Headers // Set Credentials cancellationToken.ThrowIfCancellationRequested(); await this.Client.Credentials.ProcessHttpRequestAsync(httpRequest, cancellationToken).ConfigureAwait(false); // Send Request HttpResponseMessage httpResponse = null; try { if (shouldTrace) { TracingAdapter.SendRequest(invocationId, httpRequest); } cancellationToken.ThrowIfCancellationRequested(); httpResponse = await this.Client.HttpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false); if (shouldTrace) { TracingAdapter.ReceiveResponse(invocationId, httpResponse); } HttpStatusCode statusCode = httpResponse.StatusCode; if (statusCode != HttpStatusCode.OK) { cancellationToken.ThrowIfCancellationRequested(); CloudException ex = CloudException.Create(httpRequest, null, httpResponse, await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false)); if (shouldTrace) { TracingAdapter.Error(invocationId, ex); } throw ex; } // Create Result UsageAggregationGetResponse result = null; // Deserialize Response if (statusCode == HttpStatusCode.OK) { cancellationToken.ThrowIfCancellationRequested(); string responseContent = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); result = new UsageAggregationGetResponse(); JToken responseDoc = null; if (string.IsNullOrEmpty(responseContent) == false) { responseDoc = JToken.Parse(responseContent); } if (responseDoc != null && responseDoc.Type != JTokenType.Null) { JToken valueArray = responseDoc["value"]; if (valueArray != null && valueArray.Type != JTokenType.Null) { foreach (JToken valueValue in ((JArray)valueArray)) { UsageAggregation usageAggregationInstance = new UsageAggregation(); result.UsageAggregations.Add(usageAggregationInstance); JToken idValue = valueValue["id"]; if (idValue != null && idValue.Type != JTokenType.Null) { string idInstance = ((string)idValue); usageAggregationInstance.Id = idInstance; } JToken nameValue = valueValue["name"]; if (nameValue != null && nameValue.Type != JTokenType.Null) { string nameInstance = ((string)nameValue); usageAggregationInstance.Name = nameInstance; } JToken typeValue = valueValue["type"]; if (typeValue != null && typeValue.Type != JTokenType.Null) { string typeInstance = ((string)typeValue); usageAggregationInstance.Type = typeInstance; } JToken propertiesValue = valueValue["properties"]; if (propertiesValue != null && propertiesValue.Type != JTokenType.Null) { UsageSample propertiesInstance = new UsageSample(); usageAggregationInstance.Properties = propertiesInstance; JToken meterIdValue = propertiesValue["meterId"]; if (meterIdValue != null && meterIdValue.Type != JTokenType.Null) { string meterIdInstance = (string)meterIdValue; propertiesInstance.MeterId = meterIdInstance; } JToken usageStartTimeValue = propertiesValue["usageStartTime"]; if (usageStartTimeValue != null && usageStartTimeValue.Type != JTokenType.Null) { DateTime usageStartTimeInstance = ((DateTime)usageStartTimeValue); propertiesInstance.UsageStartTime = usageStartTimeInstance.ToUniversalTime(); } JToken usageEndTimeValue = propertiesValue["usageEndTime"]; if (usageEndTimeValue != null && usageEndTimeValue.Type != JTokenType.Null) { DateTime usageEndTimeInstance = ((DateTime)usageEndTimeValue); propertiesInstance.UsageEndTime = usageEndTimeInstance.ToUniversalTime(); } JToken quantityValue = propertiesValue["quantity"]; if (quantityValue != null && quantityValue.Type != JTokenType.Null) { decimal quantityInstance = ((decimal)quantityValue); propertiesInstance.Quantity = quantityInstance; } JToken unitValue = propertiesValue["unit"]; if (unitValue != null && unitValue.Type != JTokenType.Null) { string unitInstance = ((string)unitValue); propertiesInstance.Unit = unitInstance; } JToken meterNameValue = propertiesValue["meterName"]; if (meterNameValue != null && meterNameValue.Type != JTokenType.Null) { string meterNameInstance = ((string)meterNameValue); propertiesInstance.MeterName = meterNameInstance; } JToken meterCategoryValue = propertiesValue["meterCategory"]; if (meterCategoryValue != null && meterCategoryValue.Type != JTokenType.Null) { string meterCategoryInstance = ((string)meterCategoryValue); propertiesInstance.MeterCategory = meterCategoryInstance; } JToken meterSubCategoryValue = propertiesValue["meterSubCategory"]; if (meterSubCategoryValue != null && meterSubCategoryValue.Type != JTokenType.Null) { string meterSubCategoryInstance = ((string)meterSubCategoryValue); propertiesInstance.MeterSubCategory = meterSubCategoryInstance; } JToken meterRegionValue = propertiesValue["meterRegion"]; if (meterRegionValue != null && meterRegionValue.Type != JTokenType.Null) { string meterRegionInstance = ((string)meterRegionValue); propertiesInstance.MeterRegion = meterRegionInstance; } JToken infoFieldsValue = propertiesValue["infoFields"]; if (infoFieldsValue != null && infoFieldsValue.Type != JTokenType.Null) { InfoField infoFieldsInstance = new InfoField(); propertiesInstance.InfoFields = infoFieldsInstance; JToken projectValue = infoFieldsValue["project"]; if (projectValue != null && projectValue.Type != JTokenType.Null) { string projectInstance = ((string)projectValue); infoFieldsInstance.Project = projectInstance; } } JToken instanceDataValue = propertiesValue["instanceData"]; if (instanceDataValue != null && instanceDataValue.Type != JTokenType.Null) { string instanceDataInstance = ((string)instanceDataValue); propertiesInstance.InstanceData = instanceDataInstance; } } } } JToken nextLinkValue = responseDoc["nextLink"]; if (nextLinkValue != null && nextLinkValue.Type != JTokenType.Null) { string nextLinkInstance = ((string)nextLinkValue); result.NextLink = nextLinkInstance; if (!string.IsNullOrWhiteSpace(nextLinkInstance)) { string key = "continuationToken="; int startLocation = nextLinkInstance.IndexOf(key, StringComparison.OrdinalIgnoreCase); if (startLocation >= 0) { startLocation = startLocation + key.Length; int length = nextLinkInstance.Length - startLocation; string token = nextLinkInstance.Substring(startLocation, length); result.ContinuationToken = Uri.UnescapeDataString(token); } } } } } result.StatusCode = statusCode; if (shouldTrace) { TracingAdapter.Exit(invocationId, result); } return(result); } finally { if (httpResponse != null) { httpResponse.Dispose(); } } } finally { if (httpRequest != null) { httpRequest.Dispose(); } } }
/// <summary> /// Query aggregated Azure subscription consumption data for a date /// range. (see /// https://msdn.microsoft.com/library/azure/1ea5b323-54bb-423d-916f-190de96c6a3c /// for more information) /// </summary> /// <param name='operations'> /// Reference to the /// Microsoft.Azure.Commerce.UsageAggregates.IUsageAggregationOperations. /// </param> /// <param name='reportedStartTime'> /// Required. The start of the time range to retrieve data for. /// </param> /// <param name='reportedEndTime'> /// Required. The end of the time range to retrieve data for. /// </param> /// <param name='aggregationGranularity'> /// Required. Value is either daily (default) or hourly to tell the API /// how to return the results grouped by day or hour. /// </param> /// <param name='showDetails'> /// Required. When set to true (default), the aggregates are broken /// down into the instance metadata which is more granular. /// </param> /// <param name='continuationToken'> /// Optional. Retrieved from previous calls, this is the bookmark used /// for progress when the responses are paged. /// </param> /// <returns> /// The Get UsageAggregates operation response. /// </returns> public static Task <UsageAggregationGetResponse> GetAsync(this IUsageAggregationOperations operations, DateTime reportedStartTime, DateTime reportedEndTime, AggregationGranularity aggregationGranularity, bool showDetails, string continuationToken) { return(operations.GetAsync(reportedStartTime, reportedEndTime, aggregationGranularity, showDetails, continuationToken, CancellationToken.None)); }
/// <summary> /// Query aggregated Azure subscription consumption data for a date /// range. (see /// https://msdn.microsoft.com/library/azure/1ea5b323-54bb-423d-916f-190de96c6a3c /// for more information) /// </summary> /// <param name='operations'> /// Reference to the /// Microsoft.Azure.Commerce.UsageAggregates.IUsageAggregationOperations. /// </param> /// <param name='reportedStartTime'> /// Required. The start of the time range to retrieve data for. /// </param> /// <param name='reportedEndTime'> /// Required. The end of the time range to retrieve data for. /// </param> /// <param name='aggregationGranularity'> /// Required. Value is either daily (default) or hourly to tell the API /// how to return the results grouped by day or hour. /// </param> /// <param name='showDetails'> /// Required. When set to true (default), the aggregates are broken /// down into the instance metadata which is more granular. /// </param> /// <param name='continuationToken'> /// Optional. Retrieved from previous calls, this is the bookmark used /// for progress when the responses are paged. /// </param> /// <returns> /// The Get UsageAggregates operation response. /// </returns> public static UsageAggregationGetResponse Get(this IUsageAggregationOperations operations, DateTime reportedStartTime, DateTime reportedEndTime, AggregationGranularity aggregationGranularity, bool showDetails, string continuationToken) { return(Task.Factory.StartNew((object s) => { return ((IUsageAggregationOperations)s).GetAsync(reportedStartTime, reportedEndTime, aggregationGranularity, showDetails, continuationToken); } , operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult()); }
/// <summary> /// Gets the <see cref="ResourceCostData"/> instance. /// </summary> /// <param name="offerId">Azure offer Id.</param> /// <param name="currency">Currency value.</param> /// <param name="locale">Locale value.</param> /// <param name="regionInfo">Region information.</param> /// <param name="dateStart">Start date.</param> /// <param name="dateEnd">End date.</param> /// <param name="granularity"><see cref="AggregationGranularity"/> value.</param> /// <param name="showDetails">Value indicating whether to display details or not.</param> /// <param name="authToken">Authentication token.</param> /// <returns>Returns the <see cref="ResourceCostData"/> instance.</returns> public async Task <ResourceCostData> GetResourceCostsAsync(string offerId, string currency, string locale, string regionInfo, DateTime dateStart, DateTime dateEnd, AggregationGranularity granularity, bool showDetails, string authToken = null) { this.EnsureClientIsReady(); var result = await Task.Factory.StartNew(() => this._client.GetResourceCosts(offerId, currency, locale, regionInfo, dateStart, dateEnd, granularity, showDetails, authToken)).ConfigureAwait(false); return(result); }
/// <summary> /// Reads data from the usage REST API. /// </summary> /// <param name="startDate">Start date - get usage date from this date</param> /// <param name="endDate">End date - get usage data to this date</param> /// <param name="granularity">The granularity - daily or hourly</param> /// <param name="showDetails">Include instance-level details or not</param> /// <param name="token">the OAuth token</param> /// <returns>the usage data for the given time range with the given granularity</returns> public Task <UsageData> GetUsageDataAsync(DateTime startDate, DateTime endDate, AggregationGranularity granularity = AggregationGranularity.Hourly, bool showDetails = true) { var uclient = new UsageClient(AzureIdentity, Environment, Subscription); return(uclient.GetAsync(startDate, endDate, granularity, showDetails)); }
/// <summary> /// Returns the data of the billing apis (ratecard and usage) connected and /// calculates the costs. /// </summary> /// <param name="offerDurableId">Offer - e.g. MS-AZR-0003p (see: https://azure.microsoft.com/en-us/support/legal/offer-details/) </param> /// <param name="currency">the currency - e.g. EUR or USD</param> /// <param name="locale">the locale - e.g. de-AT or en-US</param> /// <param name="regionInfo">the region - e.g. DE, AT or US</param> /// <param name="startDate">Start date - get usage date from this date</param> /// <param name="endDate">End date - get usage data to this date</param> /// <param name="granularity">The granularity - daily or hourly</param> /// <param name="showDetails">Include instance-level details or not</param> /// <param name="token">the OAuth token</param> /// <returns>The costs of the resources (combined data of ratecard and usage api)</returns> public ResourceCostData GetResourceCosts(string offerDurableId, string currency, string locale, string regionInfo, DateTime startDate, DateTime endDate, AggregationGranularity granularity, bool showDetails, string token = null) { if (string.IsNullOrEmpty(token)) { token = AzureAuthenticationHelper.GetOAuthTokenFromAAD(Globals.SERVICEURL, Tenant, Globals.RESOURCE, RedirectUrl, ClientId, ClientSecret); } var rateCardData = GetRateCardData(offerDurableId, currency, locale, regionInfo, token); // set startdate to the beginning of the period so that the cost calculation will be correct. DateTime start = GetStartOfBillingCycle(startDate); var usageData = GetUsageData(start, endDate, granularity, showDetails, token); var calculated = Combine(rateCardData, usageData); calculated.Costs = calculated.Costs.Where(x => x.UsageValue.Properties.UsageStartTimeAsDate >= startDate).ToList(); return(calculated); }
public static string GetReportingUri(string billingServiceURL, string subscriptionId, DateTime from, DateTime to, AggregationGranularity granularity = AggregationGranularity.Daily, bool showDetails = true) { Func<DateTime, DateTime> cleanStartTime = (_) => { _ = _.ToUniversalTime(); return new DateTime( year: _.Year, month: _.Month, day: _.Day, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Utc) .ToUniversalTime(); }; Func<DateTime, DateTime> cleanEndTime = (_) => { _ = _.AddDays(1).AddMilliseconds(-1).ToUniversalTime(); return new DateTime( year: _.Year, month: _.Month, day: _.Day, hour: 0, minute: 0, second: 0, kind: DateTimeKind.Utc) .ToUniversalTime(); }; const string dateTimeFormat = "yyyy-MM-dd HH:mm:ssZ"; string requestURL = new Uri(string.Format("{0}/subscriptions/{1}/providers/Microsoft.Commerce/UsageAggregates", billingServiceURL, subscriptionId)) .AddQuery("api-version", "2015-06-01-preview") .AddQuery("reportedstartTime", cleanStartTime(from).ToString(dateTimeFormat)) .AddQuery("reportedEndTime", cleanEndTime(to).ToString(dateTimeFormat)) .AddQuery("aggregationGranularity", granularity == AggregationGranularity.Daily ? "Daily" : "Hourly") .AddQuery("showDetails", showDetails ? "true" : "false") .AbsoluteUri; return requestURL; }
public async Task <ActionResult> Index(string subscriptionId, DateTime?reportedStart = null, DateTime?reportedEnd = null, AggregationGranularity granularity = AggregationGranularity.Daily, bool showDetails = true) { // verify subscription id present if (string.IsNullOrEmpty(subscriptionId)) { return(RedirectToRoute("Default", new { controller = "Subscriptions" })); } // fixup defaults var now = DateTime.UtcNow; if (!reportedStart.HasValue) { reportedStart = new DateTime(now.Year, now.Month, 1, 0, 0, 0); } if (!reportedEnd.HasValue) { reportedEnd = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0); } // get usage info from Azure var azureUsage = await AzureUsageRepository.GetUsage(subscriptionId, reportedStart.Value, reportedEnd.Value, granularity, showDetails); // create viewmodel // > all line items have same report id, name & type var sharedLineItems = azureUsage.LineItems != null ? azureUsage.LineItems[0] : null; AzureUsageViewModel viewModel = new AzureUsageViewModel() { AzureSubscriptionId = subscriptionId, UsageDetailReportId = (sharedLineItems != null) ? sharedLineItems.Id : string.Empty, UsageDetailReportName = (sharedLineItems != null) ? sharedLineItems.Name : string.Empty, UsageDetailReportType = (sharedLineItems != null) ? sharedLineItems.Type : string.Empty, ReportedStart = reportedStart.Value, ReportedEnd = reportedEnd.Value, Granularity = granularity, ShowDetails = showDetails }; // loop through all line items and aggregate... List <UsageDetailProperties> usageDetails = new List <UsageDetailProperties>(); if (azureUsage.LineItems != null) { foreach (var lineItem in azureUsage.LineItems) { usageDetails.Add(lineItem.Properties); } } // sort it up viewModel.UsageDetails.AddRange(from detail in usageDetails orderby detail.MeterCategory, detail.MeterSubCategory, detail.MeterName, detail.UsageStartTime select detail); return(View(viewModel)); }
/// <summary> /// Reads data from the usage REST API. /// </summary> /// <param name="startDate">Start date - get usage date from this date</param> /// <param name="endDate">End date - get usage data to this date</param> /// <param name="granularity">The granularity - daily or hourly</param> /// <param name="showDetails">Include instance-level details or not</param> /// <returns>the usage data for the given time range with the given granularity</returns> public UsageData Get(DateTime startDate, DateTime endDate, AggregationGranularity granularity, bool showDetails) { string token = AzureAuthenticationHelper.GetOAuthTokenFromAAD(Globals.SERVICEURL, Tenant, Globals.RESOURCE, RedirectUrl, ClientId, ClientSecret); return(Get(startDate, endDate, granularity, showDetails, token)); }