コード例 #1
0
        public async Task <MetricListResponse> GetMetricsAsync(string resourceId, string filterString, IEnumerable <MetricDefinition> definitions, string invocationId)
        {
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);

            // Grab all metric definitiions that contain the specific timegrain from the filter.
            // See the extension class for implementation
            var timegraindefinitions = from d in definitions
                                       where d.MetricAvailabilities.Count > 0 &&
                                       d.MetricAvailabilities.Contains(filter)
                                       select d;

            // Group definitions by location so we can make one request to each location
            Dictionary <MetricAvailability, MetricFilter> groups =
                timegraindefinitions.GroupBy(d => d.MetricAvailabilities.FirstOrDefault()).ToDictionary(g => g.Key, g => new MetricFilter()
            {
                TimeGrain        = filter.TimeGrain,
                StartTime        = filter.StartTime,
                EndTime          = filter.EndTime,
                DimensionFilters = g.Select(d =>
                                            filter.DimensionFilters.FirstOrDefault(df => string.Equals(df.Name, d.Name.Value, StringComparison.OrdinalIgnoreCase))
                                            ?? new MetricDimension()
                {
                    Name = d.Name.Value
                })
            }, new AvailabilityComparer());



            // Verify all groups represent shoebox metrics
            if (groups.Any(g => g.Key.Location == null))
            {
                throw new ArgumentException("All definitions provided to ShoeboxMetricRetriever must include location information.", "definitions");
            }

            // Get Metrics from each location (group)
            IEnumerable <Task <MetricListResponse> > locationTasks = groups.Select(g => this.GetMetricsInternalAsync(g.Value, g.Key.Location, invocationId));

            // Aggregate metrics from all groups
            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));

            // Return aggregated results (the MetricOperations class will fill in additional info from the MetricDefinitions)
            return(new MetricListResponse()
            {
                RequestId = invocationId,
                StatusCode = HttpStatusCode.OK,
                MetricCollection = new MetricCollection()
                {
                    Value = metrics.ToList()
                }
            });
        }
コード例 #2
0
        public async Task <MetricListResponse> GetMetricsAsync(string resourceUri, string filterString, CancellationToken cancellationToken)
        {
            if (resourceUri == null)
            {
                throw new System.ArgumentNullException("resourceUri");
            }

            // Generate filter strings
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);
            string       filterStringNamesOnly = filter.DimensionFilters == null ? null
                : ShoeboxHelper.GenerateMetricDefinitionFilterString(filter.DimensionFilters.Select(df => df.Name));

            // Get definitions for requested metrics
            IList <MetricDefinition> definitions =
                (await this.Client.MetricDefinitionOperations.GetMetricDefinitionsAsync(
                     resourceUri,
                     filterStringNamesOnly,
                     cancellationToken).ConfigureAwait(false)).MetricDefinitionCollection.Value;

            // Get Metrics with definitions
            return(await this.GetMetricsAsync(resourceUri, filterString, definitions, cancellationToken));
        }
コード例 #3
0
        public Task <MetricListResponse> GetMetricsAsync(string resourceId, string filterString, IEnumerable <MetricDefinition> definitions, string invocationId)
        {
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);

            return(Task.Factory.StartNew(() => new MetricListResponse()
            {
                RequestId = invocationId,
                StatusCode = HttpStatusCode.OK,
                MetricCollection = new MetricCollection()
                {
                    Value = definitions == null ? new List <Metric>() : definitions.Select(d => new Metric()
                    {
                        Name = d.Name,
                        Unit = d.Unit,
                        ResourceId = resourceId,
                        StartTime = filter.StartTime,
                        EndTime = filter.EndTime,
                        TimeGrain = filter.TimeGrain,
                        MetricValues = new List <MetricValue>(),
                        Properties = new Dictionary <string, string>()
                    }).ToList()
                }
            }));
        }
コード例 #4
0
        public async Task <MetricListResponse> GetMetricsAsync(string resourceId, string filterString, IEnumerable <MetricDefinition> definitions, string invocationId)
        {
            MetricFilter filter = MetricFilterExpressionParser.Parse(filterString);

            var metricsPerBlob = new Dictionary <string, Task <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 (availability.BlobLocation == null)
                    {
                        continue;
                    }

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

            foreach (var task in metricsPerBlob.Values)
            {
                await task;
            }

            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 (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].Result.TryGetValue(metricDefinition.Name.Value, out metricsInBlob))
                        {
                            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);
        }
コード例 #5
0
        // 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);
        }