The List Metric values operation response.
상속: Microsoft.Azure.AzureOperationResponse
        public GetAzureRmMetricTests(Xunit.Abstractions.ITestOutputHelper output)
        {
            ServiceManagemenet.Common.Models.XunitTracingInterceptor.AddToContext(new ServiceManagemenet.Common.Models.XunitTracingInterceptor(output));
            insightsMetricOperationsMock = new Mock<IMetricOperations>();
            insightsClientMock = new Mock<InsightsClient>();
            commandRuntimeMock = new Mock<ICommandRuntime>();
            cmdlet = new GetAzureRmMetricCommand()
            {
                CommandRuntime = commandRuntimeMock.Object,
                //InsightsClient = insightsClientMock.Object
            };

            response = Utilities.InitializeMetricResponse();

            insightsMetricOperationsMock.Setup(f => f.GetMetricsAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
                .Returns(Task.FromResult<MetricListResponse>(response))
                .Callback((string f, string s, CancellationToken t) =>
                {
                    resourceId = f;
                    filter = s;
                });

            insightsClientMock.SetupGet(f => f.MetricOperations).Returns(this.insightsMetricOperationsMock.Object);
        }
        public async Task<MetricListResponse> GetMetricsAsync(string resourceId, string filterString, IEnumerable<MetricDefinition> definitions, string invocationId)
        {
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);

            var ongoingTasksPerBlob = new Dictionary<string, Task<Dictionary<string, List<MetricValueBlob>>>>();
            var metricsPerBlob = new Dictionary<string, Dictionary<string, List<MetricValueBlob>>>(StringComparer.OrdinalIgnoreCase);
            
            // We download all the relevant blobs first and then use the data later, to avoid download the same blob more than once.
            foreach (MetricDefinition metricDefinition in definitions)
            {
                if (!IsMetricDefinitionIncluded(filter, metricDefinition))
                {
                    continue;
                }

                foreach (MetricAvailability availability in metricDefinition.MetricAvailabilities)
                {
                    if (filter != null && filter.TimeGrain != default(TimeSpan) && filter.TimeGrain != availability.TimeGrain)
                    {
                        continue;
                    }

                    if (availability.BlobLocation == null)
                    {
                        continue;
                    }

                    foreach (BlobInfo blobInfo in availability.BlobLocation.BlobInfo)
                    {
                        string blobId = GetBlobEndpoint(blobInfo);
                        if (!metricsPerBlob.ContainsKey(blobId) && !ongoingTasksPerBlob.ContainsKey(blobId))
                        {
                            ongoingTasksPerBlob.Add(blobId, FetchMetricValuesFromBlob(blobInfo, filter));
                        }

                        if (ongoingTasksPerBlob.Count == Util.NumberOfParallelCallsForMetricBlobs)
                        {
                            foreach (var blobMetricPair in ongoingTasksPerBlob)
                            {
                                metricsPerBlob[blobMetricPair.Key] = await blobMetricPair.Value;
                            }

                            ongoingTasksPerBlob.Clear();
                        }
                    }
                }
            }

            foreach (var blobMetricPair in ongoingTasksPerBlob)
            {
                metricsPerBlob[blobMetricPair.Key] = await blobMetricPair.Value;
            }

            var result = new MetricListResponse
            {
                MetricCollection = new MetricCollection
                {
                    Value = new List<Metric>()
                }
            };

            // Populate the metrics result using the data from the blobs.
            foreach (MetricDefinition metricDefinition in definitions)
            {
                if (!IsMetricDefinitionIncluded(filter, metricDefinition))
                {
                    continue;
                }

                foreach (MetricAvailability availability in metricDefinition.MetricAvailabilities)
                {
                    if (filter != null && filter.TimeGrain != default(TimeSpan) && filter.TimeGrain != availability.TimeGrain)
                    {
                        continue;
                    }

                    if (availability.BlobLocation == null)
                    {
                        continue;
                    }

                    var metricValues = new List<MetricValueBlob>();
                    foreach (BlobInfo blobInfo in availability.BlobLocation.BlobInfo)
                    {
                        string blobId = GetBlobEndpoint(blobInfo);

                        List<MetricValueBlob> metricsInBlob;
                        if (metricsPerBlob[blobId].TryGetValue(metricDefinition.Name.Value, out metricsInBlob))
                        {
                            metricsInBlob.Sort(CompareMetrics);
                            metricValues.AddRange(metricsInBlob);
                        }
                    }

                    var metric = new Metric
                    {
                        Name = new LocalizableString
                        {
                            Value = metricDefinition.Name.Value,
                            LocalizedValue = metricDefinition.Name.LocalizedValue,
                        },
                        StartTime = filter.StartTime,
                        EndTime = filter.EndTime,
                        MetricValues = GetAggregatedByTimestamp(metricValues),
                        TimeGrain = availability.TimeGrain,
                    };

                    result.MetricCollection.Value.Add(metric);
                }
            }

            return result;
        }
        // Alternate method for getting metrics by passing in the definitions
        public async Task<MetricListResponse> GetMetricsAsync(
            string resourceUri, string filterString, IEnumerable<MetricDefinition> definitions, CancellationToken cancellationToken)
        {
            if (definitions == null)
            {
                throw new ArgumentNullException("definitions");
            }

            if (resourceUri == null)
            {
                throw new ArgumentNullException("resourceUri");
            }

            // Remove any '/' characters from the start since these are handled by the hydra (thin) client
            // Don't encode Uri segments here since this will mess up the SAS retrievers (they use the resourceUri directly)
            resourceUri = resourceUri.TrimStart('/');

            MetricListResponse result;
            string invocationId = TracingAdapter.NextInvocationId.ToString(CultureInfo.InvariantCulture);

            // If no definitions provided, return empty collection
            if (!definitions.Any())
            {
                this.LogStartGetMetrics(invocationId, resourceUri, filterString, definitions);
                result = new MetricListResponse()
                {
                    RequestId = Guid.NewGuid().ToString("D"),
                    StatusCode = HttpStatusCode.OK,
                    MetricCollection = new MetricCollection()
                    {
                        Value = new Metric[0]
                    }
                };

                this.LogEndGetMetrics(invocationId, result);

                return result;
            }

            // Parse MetricFilter
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);

            // Names in filter must match the names in the definitions
            if (filter.DimensionFilters != null && filter.DimensionFilters.Any())
            {
                IEnumerable<string> filterNames = filter.DimensionFilters.Select(df => df.Name);
                IEnumerable<string> definitionNames = definitions.Select(d => d.Name.Value);
                IEnumerable<string> filterOnly = filterNames.Where(fn => !definitionNames.Contains(fn, StringComparer.InvariantCultureIgnoreCase));
                IEnumerable<string> definitionOnly = definitionNames.Where(df => !filterNames.Contains(df, StringComparer.InvariantCultureIgnoreCase));

                if (filterOnly.Any() || definitionOnly.Any())
                {
                    throw new ArgumentException("Set of names specified in filter string must match set of names in provided definitions", "filterString");
                }

                // "Filter out" metrics with unsupported dimensions
                definitions = definitions.Where(d => SupportsRequestedDimensions(d, filter));
            }
            else
            {
                filter = new MetricFilter()
                {
                    TimeGrain = filter.TimeGrain,
                    StartTime = filter.StartTime,
                    EndTime = filter.EndTime,
                    DimensionFilters = definitions.Select(d => new MetricDimension()
                    {
                        Name = d.Name.Value
                    })
                };
            }

            // Parse out provider name and determine if provider is storage
            string providerName = this.GetProviderFromResourceId(resourceUri);
            bool isStorageProvider =
                string.Equals(providerName, "Microsoft.Storage", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(providerName, "Microsoft.ClassicStorage", StringComparison.OrdinalIgnoreCase);

            // Create supported MetricRetrievers
            IMetricRetriever proxyRetriever = new ProxyMetricRetriever(this);
            IMetricRetriever shoeboxRetriever = new ShoeboxMetricRetriever();
            IMetricRetriever storageRetriever = new StorageMetricRetriever();
            IMetricRetriever blobShoeboxMetricRetriever = new BlobShoeboxMetricRetriever();
            IMetricRetriever emptyRetriever = EmptyMetricRetriever.Instance;

            // Create the selector function here so it has access to the retrievers, filter, and providerName
            Func<MetricDefinition, IMetricRetriever> retrieverSelector = (d) =>
            {
                if (!d.MetricAvailabilities.Any())
                {
                    return emptyRetriever;
                }

                if (isStorageProvider)
                {
                    return storageRetriever;
                }

                if (IsBlobSasMetric(d, filter.TimeGrain))
                {
                    return blobShoeboxMetricRetriever;
                }

                if (IsTableSasMetric(d, filter.TimeGrain))
                {
                    return shoeboxRetriever;
                }

                return proxyRetriever;
            };

            // Group definitions by retriever so we can make one request to each retriever
            IEnumerable<IGrouping<IMetricRetriever, MetricDefinition>> groups = definitions.GroupBy(retrieverSelector);

            // Get Metrics from each retriever (group)
            IEnumerable<Task<MetricListResponse>> locationTasks = groups.Select(g =>
                g.Key.GetMetricsAsync(resourceUri, GetFilterStringForDefinitions(filter, g), g, invocationId));

            // Aggregate metrics from all groups
            this.LogStartGetMetrics(invocationId, resourceUri, filterString, definitions);
            MetricListResponse[] results = (await Task.Factory.ContinueWhenAll(locationTasks.ToArray(), tasks => tasks.Select(t => t.Result))).ToArray();
            IEnumerable<Metric> metrics = results.Aggregate<MetricListResponse, IEnumerable<Metric>>(
                new List<Metric>(), (list, response) => list.Union(response.MetricCollection.Value));

            this.LogMetricCountFromResponses(invocationId, metrics.Count());

            // Fill in values (resourceUri, displayName, unit) from definitions
            CompleteShoeboxMetrics(metrics, definitions, resourceUri);

            // Add empty objects for metrics that had no values come back, ensuring a metric is returned for each definition
            IEnumerable<Metric> emptyMetrics = (await emptyRetriever.GetMetricsAsync(
                resourceUri,
                filterString,
                definitions.Where(d => !metrics.Any(m => string.Equals(m.Name.Value, d.Name.Value, StringComparison.OrdinalIgnoreCase))),
                invocationId)).MetricCollection.Value;

            // Create response (merge and wrap metrics)
            result = new MetricListResponse()
            {
                RequestId = Guid.NewGuid().ToString("D"),
                StatusCode = HttpStatusCode.OK,
                MetricCollection = new MetricCollection()
                {
                    Value = metrics.Union(emptyMetrics).ToList()
                }
            };

            this.LogEndGetMetrics(invocationId, result);

            return result;
        }
 private void LogEndGetMetrics(string invocationId, MetricListResponse result)
 {
     if (TracingAdapter.IsEnabled)
     {
         TracingAdapter.Exit(invocationId, result);
     }
 }