private async Task MeasureArmRateLimitingAsync(HttpResponseMessage response) { // Source: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-request-limits if (response.Headers.Contains("x-ms-ratelimit-remaining-subscription-reads")) { var remainingApiCalls = response.Headers.GetValues("x-ms-ratelimit-remaining-subscription-reads").FirstOrDefault(); var subscriptionReadLimit = Convert.ToInt16(remainingApiCalls); await _metricSinkWriter.ReportMetricAsync(RuntimeMetricNames.RateLimitingForArm, "Indication how many calls are still available before Azure Resource Manager is going to throttle us.", subscriptionReadLimit, _metricLabels); _metricsCollector.SetGaugeMeasurement(RuntimeMetricNames.RateLimitingForArm, "Indication how many calls are still available before Azure Resource Manager is going to throttle us.", subscriptionReadLimit, _metricLabels); } }
public async Task ReportMetricAsync_WriteToNoSinks_Succeeds() { // Arrange var metricName = BogusGenerator.Name.FirstName(); var metricDescription = BogusGenerator.Lorem.Sentence(); var metricValue = BogusGenerator.Random.Double(); var scrapeResult = ScrapeResultGenerator.Generate(metricValue); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink>(), NullLogger <MetricSinkWriter> .Instance); // Act & Assert await metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult); }
public async Task ReportMetricAsync_WriteToOneSinkWithoutMetricDescription_Succeeds(string metricDescription) { // Arrange var metricName = BogusGenerator.Name.FirstName(); var metricValue = BogusGenerator.Random.Double(); var scrapeResult = ScrapeResultGenerator.Generate(metricValue); var metricSink = new Mock <IMetricSink>(); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { metricSink.Object }, NullLogger <MetricSinkWriter> .Instance); // Act & Assert await metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult); }
protected override async Task AvailableRateLimitingCallsAsync(HttpResponseMessage response) { // Source: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-request-limits if (response.Headers.Contains(ThrottlingHeaderName)) { var remainingApiCalls = response.Headers.GetValues(ThrottlingHeaderName).FirstOrDefault(); var subscriptionReadLimit = Convert.ToInt16(remainingApiCalls); // Report metric await _metricSinkWriter.ReportMetricAsync(RuntimeMetricNames.RateLimitingForArm, AvailableCallsMetricDescription, subscriptionReadLimit, _metricLabels); _azureScrapingPrometheusMetricsCollector.WriteGaugeMeasurement(RuntimeMetricNames.RateLimitingForArm, AvailableCallsMetricDescription, subscriptionReadLimit, _metricLabels); } }
public async Task ScrapeAsync(ScrapeDefinition <IAzureResourceDefinition> scrapeDefinition) { if (scrapeDefinition == null) { throw new ArgumentNullException(nameof(scrapeDefinition)); } var aggregationInterval = scrapeDefinition.AzureMetricConfiguration?.Aggregation?.Interval; if (aggregationInterval == null) { throw new ArgumentNullException(nameof(scrapeDefinition)); } try { var castedMetricDefinition = scrapeDefinition.Resource as TResourceDefinition; if (castedMetricDefinition == null) { throw new ArgumentException($"Could not cast metric definition of type {scrapeDefinition.Resource.ResourceType} to {typeof(TResourceDefinition)}. Payload: {JsonConvert.SerializeObject(scrapeDefinition)}"); } var aggregationType = scrapeDefinition.AzureMetricConfiguration.Aggregation.Type; var scrapedMetricResult = await ScrapeResourceAsync( scrapeDefinition.SubscriptionId, scrapeDefinition, castedMetricDefinition, aggregationType, aggregationInterval.Value); LogMeasuredMetrics(scrapeDefinition, scrapedMetricResult, aggregationInterval); await _metricSinkWriter.ReportMetricAsync(scrapeDefinition.PrometheusMetricDefinition.Name, scrapeDefinition.PrometheusMetricDefinition.Description, scrapedMetricResult); ReportScrapingOutcome(scrapeDefinition, isSuccessful: true); } catch (ErrorResponseException errorResponseException) { HandleErrorResponseException(errorResponseException, scrapeDefinition.PrometheusMetricDefinition.Name); ReportScrapingOutcome(scrapeDefinition, isSuccessful: false); } catch (Exception exception) { Logger.LogCritical(exception, "Failed to scrape resource for metric '{MetricName}'", scrapeDefinition.PrometheusMetricDefinition.Name); ReportScrapingOutcome(scrapeDefinition, isSuccessful: false); } }
public async Task ReportMetricAsync_WriteToOneSinkWithoutScrapeResult_ThrowsException() { // Arrange var metricName = BogusGenerator.Name.FirstName(); var metricDescription = BogusGenerator.Lorem.Sentence(); ScrapeResult scrapeResult = null; var metricSink = new Mock <IMetricSink>(); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { metricSink.Object }, NullLogger <MetricSinkWriter> .Instance); // Act & Assert // ReSharper disable once ExpressionIsAlwaysNull await Assert.ThrowsAsync <ArgumentNullException>(() => metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult)); }
public async Task ReportMetricAsync_WriteToOneSinkWithoutMetricName_ThrowsException(string metricName) { // Arrange var metricDescription = _bogus.Lorem.Sentence(); var metricValue = _bogus.Random.Double(); var scrapeResult = ScrapeResultGenerator.Generate(metricValue); var metricSink = new Mock <IMetricSink>(); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { metricSink.Object }, NullLogger <MetricSinkWriter> .Instance); // Act & Assert // ReSharper disable once ExpressionIsAlwaysNull await Assert.ThrowsAsync <ArgumentException>(() => metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult)); }
public async Task ReportMetricAsync_WriteToOneSink_Succeeds() { // Arrange var metricName = BogusGenerator.Name.FirstName(); var metricDescription = BogusGenerator.Lorem.Sentence(); var metricValue = BogusGenerator.Random.Double(); var scrapeResult = ScrapeResultGenerator.Generate(metricValue); var metricSink = new Mock <IMetricSink>(); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { metricSink.Object }, NullLogger <MetricSinkWriter> .Instance); // Act await metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult); // Assert metricSink.Verify(mock => mock.ReportMetricAsync(metricName, metricDescription, scrapeResult), Times.Once()); }
public async Task ReportMetricAsync_WriteToStatsDSink_Succeeds() { // Arrange var metricName = _bogus.Name.FirstName(); var metricDescription = _bogus.Lorem.Sentence(); var metricValue = _bogus.Random.Double(); var scrapeResult = ScrapeResultGenerator.Generate(metricValue); var statsDPublisherMock = new Mock <IStatsDPublisher>(); var statsdMetricSink = new StatsdMetricSink(statsDPublisherMock.Object, NullLogger <StatsdMetricSink> .Instance); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { statsdMetricSink }, NullLogger <MetricSinkWriter> .Instance); // Act await metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult); // Assert statsDPublisherMock.Verify(mock => mock.Gauge(metricValue, metricName), Times.Once()); }
public async Task ReportMetricAsync_WriteToMultipleSinks_Succeeds() { // Arrange var metricName = _bogus.Name.FirstName(); var metricDescription = _bogus.Lorem.Sentence(); var metricValue = _bogus.Random.Double(); var scrapeResult = GenerateScrapeResult(metricValue); var firstSink = new Mock <IMetricSink>(); var secondSink = new Mock <IMetricSink>(); var metricSinkWriter = new MetricSinkWriter(new List <IMetricSink> { firstSink.Object, secondSink.Object }, NullLogger <MetricSinkWriter> .Instance); // Act await metricSinkWriter.ReportMetricAsync(metricName, metricDescription, scrapeResult); // Assert firstSink.Verify(mock => mock.ReportMetricAsync(metricName, metricDescription, It.IsAny <MeasuredMetric>()), Times.Once()); secondSink.Verify(mock => mock.ReportMetricAsync(metricName, metricDescription, It.IsAny <MeasuredMetric>()), Times.Once()); }