diff --git a/changelog/content/experimental/unreleased.md b/changelog/content/experimental/unreleased.md index 2176ada74..f09c9e20c 100644 --- a/changelog/content/experimental/unreleased.md +++ b/changelog/content/experimental/unreleased.md @@ -7,6 +7,7 @@ version: #### Scraper - {{% tag added %}} Provide capability to transform metric labels in Prometheus ([docs](https://promitor.io/configuration/v2.x/runtime/scraper#prometheus-scraping-endpoint) +- {{% tag added %}} Provide capability to limit the amount of resources to query when using filters/dimensions ([docs](https://promitor.io/configuration/v2.x/metrics) | [#1596](https://github.com/tomkerkhove/promitor/issues/1596)) - {{% tag added %}} Provide capability to define default custom labels ([docs](https://promitor.io/configuration/v2.x/metrics/) | [#1608](https://github.com/tomkerkhove/promitor/issues/1608)) diff --git a/config/promitor/scraper/metrics.yaml b/config/promitor/scraper/metrics.yaml index 103543d8a..f719c9280 100644 --- a/config/promitor/scraper/metrics.yaml +++ b/config/promitor/scraper/metrics.yaml @@ -6,6 +6,7 @@ azureMetadata: metricDefaults: aggregation: interval: 00:05:00 + limit: 10 labels: geo: china environment: dev @@ -136,140 +137,151 @@ metrics: type: Average resources: - namespace: promitor-messaging - # resourceDiscoveryGroups: - # - name: service-bus-landscape -# - name: promitor_demo_app_insights_dependency_duration -# description: "Average dependency duration per dependency type" -# resourceType: Generic -# azureMetricConfiguration: -# metricName: dependencies/duration -# dimension: -# name: dependency/type -# aggregation: -# type: Average -# resources: -# - resourceUri: Microsoft.Insights/Components/docker-hub-metrics -# resourceGroupName: docker-hub-metrics -# - name: promitor_demo_app_insights_dependency_duration_200_OK -# description: "Average dependency duration per dependency type" -# resourceType: Generic -# azureMetricConfiguration: -# metricName: dependencies/duration -# aggregation: -# type: Average -# resources: -# - resourceUri: Microsoft.Insights/Components/docker-hub-metrics -# resourceGroupName: docker-hub-metrics -# filter: dependency/resultCode eq '200' -# - name: promitor_demo_automation_job_count -# description: "Amount of jobs per Azure Automation account" -# resourceType: AutomationAccount -# azureMetricConfiguration: -# metricName: TotalJob -# aggregation: -# type: Total -# resourceDiscoveryGroups: -# - name: automation-accounts -# resources: -# - resourceGroupName: promitor-sources -# accountName: promitor-sandbox -# - name: promitor_demo_automation_update_deployment_runs -# description: "Amount of jobs per Azure Automation account" -# resourceType: AutomationAccount -# azureMetricConfiguration: -# metricName: TotalUpdateDeploymentRuns -# aggregation: -# type: Total -# resourceDiscoveryGroups: -# - name: automation-accounts -# resources: -# - resourceGroupName: promitor-sources -# accountName: promitor-sandbox -# - name: promitor_demo_automation_update_deployment_machine_runs -# description: "Amount of jobs per Azure Automation account" -# resourceType: AutomationAccount -# azureMetricConfiguration: -# metricName: TotalUpdateDeploymentMachineRuns -# aggregation: -# type: Total -# resourceDiscoveryGroups: -# - name: automation-accounts -# resources: -# - resourceGroupName: promitor-sources -# accountName: promitor-sandbox -# - name: promitor_demo_frontdoor_backend_health_per_backend -# description: "Health percentage for a backed in Azure Front Door" -# resourceType: FrontDoor -# labels: -# app: promitor -# azureMetricConfiguration: -# metricName: BackendHealthPercentage -# dimension: -# name: Backend -# aggregation: -# type: Average -# resources: -# - name: promitor-landscape -# resourceGroupName: promitor-landscape -# - name: promitor_demo_frontdoor_backend_health_per_backend_pool -# description: "Health percentage for a backed in Azure Front Door" -# resourceType: FrontDoor -# labels: -# app: promitor -# azureMetricConfiguration: -# metricName: BackendHealthPercentage -# dimension: -# name: BackendPool -# aggregation: -# type: Average -# resourceDiscoveryGroups: -# - name: front-door-landscape -# - name: promitor_demo_sql_elastic_pool_cpu -# description: "CPU percentage used for a Azure SQL Elastic Pool" -# resourceType: SqlElasticPool -# labels: -# app: promitor -# azureMetricConfiguration: -# metricName: cpu_percent -# aggregation: -# type: Average -# resourceDiscoveryGroups: -# - name: sql-elastic-pools -# - name: promitor_demo_sql_elastic_pool_allocated_storage -# description: "Percentage of allocated storage for a Azure SQL Elastic Pool" -# resourceType: SqlElasticPool -# labels: -# app: promitor -# azureMetricConfiguration: -# metricName: allocated_data_storage_percent -# aggregation: -# type: Average -# resourceDiscoveryGroups: -# - name: sql-elastic-pools -# - name: promitor_demo_synapse_apache_spark_apps_ended -# description: "Amount of apps ended running on Apache Spark pool in Azure Synapse" -# resourceType: SynapseApacheSparkPool -# azureMetricConfiguration: -# metricName: BigDataPoolApplicationsEnded -# aggregation: -# type: Total -# resourceDiscoveryGroups: -# - name: synapse-apache-spark-pools -# - name: promitor_demo_synapse_sql_pool_dwu_limit -# description: "Amount of DWUs defined as limit for SQL pool in Azure Synapse" -# resourceType: SynapseSqlPool -# azureMetricConfiguration: -# metricName: DWULimit -# aggregation: -# type: Maximum -# resourceDiscoveryGroups: -# - name: synapse-sql-pools -# - name: promitor_demo_synapse_workspace_builtin_sql_processed_bytes -# description: "Amount of bytes processed in Azure Synapse workspace" -# resourceType: SynapseWorkspace -# azureMetricConfiguration: -# metricName: BuiltinSqlPoolDataProcessedBytes -# aggregation: -# type: Total -# resourceDiscoveryGroups: -# - name: synapse-workspaces +- name: promitor_demo_servicebus_messagecount_limited + description: "Average percentage of memory usage on an Azure App Plan" + resourceType: ServiceBusNamespace + labels: + geo: europe + app: promitor + azureMetricConfiguration: + limit: 5 + metricName: ActiveMessages + aggregation: + type: Average + resources: + - namespace: promitor-messaging +- name: promitor_demo_app_insights_dependency_duration + description: "Average dependency duration per dependency type" + resourceType: Generic + azureMetricConfiguration: + metricName: dependencies/duration + dimension: + name: dependency/type + aggregation: + type: Average + resources: + - resourceUri: Microsoft.Insights/Components/docker-hub-metrics + resourceGroupName: docker-hub-metrics +- name: promitor_demo_app_insights_dependency_duration_200_OK + description: "Average dependency duration per dependency type" + resourceType: Generic + azureMetricConfiguration: + metricName: dependencies/duration + aggregation: + type: Average + resources: + - resourceUri: Microsoft.Insights/Components/docker-hub-metrics + resourceGroupName: docker-hub-metrics + filter: dependency/resultCode eq '200' +- name: promitor_demo_automation_job_count + description: "Amount of jobs per Azure Automation account" + resourceType: AutomationAccount + azureMetricConfiguration: + metricName: TotalJob + aggregation: + type: Total + resourceDiscoveryGroups: + - name: automation-accounts + resources: + - resourceGroupName: promitor-sources + accountName: promitor-sandbox +- name: promitor_demo_automation_update_deployment_runs + description: "Amount of jobs per Azure Automation account" + resourceType: AutomationAccount + azureMetricConfiguration: + metricName: TotalUpdateDeploymentRuns + aggregation: + type: Total + resourceDiscoveryGroups: + - name: automation-accounts + resources: + - resourceGroupName: promitor-sources + accountName: promitor-sandbox +- name: promitor_demo_automation_update_deployment_machine_runs + description: "Amount of jobs per Azure Automation account" + resourceType: AutomationAccount + azureMetricConfiguration: + metricName: TotalUpdateDeploymentMachineRuns + aggregation: + type: Total + resourceDiscoveryGroups: + - name: automation-accounts + resources: + - resourceGroupName: promitor-sources + accountName: promitor-sandbox +- name: promitor_demo_frontdoor_backend_health_per_backend + description: "Health percentage for a backed in Azure Front Door" + resourceType: FrontDoor + labels: + app: promitor + azureMetricConfiguration: + metricName: BackendHealthPercentage + dimension: + name: Backend + aggregation: + type: Average + resources: + - name: promitor-landscape + resourceGroupName: promitor-landscape +- name: promitor_demo_frontdoor_backend_health_per_backend_pool + description: "Health percentage for a backed in Azure Front Door" + resourceType: FrontDoor + labels: + app: promitor + azureMetricConfiguration: + metricName: BackendHealthPercentage + dimension: + name: BackendPool + aggregation: + type: Average + resourceDiscoveryGroups: + - name: front-door-landscape +- name: promitor_demo_sql_elastic_pool_cpu + description: "CPU percentage used for a Azure SQL Elastic Pool" + resourceType: SqlElasticPool + labels: + app: promitor + azureMetricConfiguration: + metricName: cpu_percent + aggregation: + type: Average + resourceDiscoveryGroups: + - name: sql-elastic-pools +- name: promitor_demo_sql_elastic_pool_allocated_storage + description: "Percentage of allocated storage for a Azure SQL Elastic Pool" + resourceType: SqlElasticPool + labels: + app: promitor + azureMetricConfiguration: + metricName: allocated_data_storage_percent + aggregation: + type: Average + resourceDiscoveryGroups: + - name: sql-elastic-pools +- name: promitor_demo_synapse_apache_spark_apps_ended + description: "Amount of apps ended running on Apache Spark pool in Azure Synapse" + resourceType: SynapseApacheSparkPool + azureMetricConfiguration: + metricName: BigDataPoolApplicationsEnded + aggregation: + type: Total + resourceDiscoveryGroups: + - name: synapse-apache-spark-pools +- name: promitor_demo_synapse_sql_pool_dwu_limit + description: "Amount of DWUs defined as limit for SQL pool in Azure Synapse" + resourceType: SynapseSqlPool + azureMetricConfiguration: + metricName: DWULimit + aggregation: + type: Maximum + resourceDiscoveryGroups: + - name: synapse-sql-pools +- name: promitor_demo_synapse_workspace_builtin_sql_processed_bytes + description: "Amount of bytes processed in Azure Synapse workspace" + resourceType: SynapseWorkspace + azureMetricConfiguration: + metricName: BuiltinSqlPoolDataProcessedBytes + aggregation: + type: Total + resourceDiscoveryGroups: + - name: synapse-workspaces diff --git a/config/promitor/scraper/runtime.yaml b/config/promitor/scraper/runtime.yaml index cb4e65390..e02f07d5c 100644 --- a/config/promitor/scraper/runtime.yaml +++ b/config/promitor/scraper/runtime.yaml @@ -12,11 +12,11 @@ metricSinks: host: graphite port: 8125 metricPrefix: promitor. - # atlassianStatuspage: - # pageId: y79z9b78ybgs - # systemMetricMapping: - # - id: nfkgnrwpn545 - # promitorMetricName: promitor_demo_appplan_percentage_cpu + atlassianStatuspage: + pageId: y79z9b78ybgs + systemMetricMapping: + - id: nfkgnrwpn545 + promitorMetricName: promitor_demo_appplan_percentage_cpu metricsConfiguration: absolutePath: /config/metrics-declaration.yaml telemetry: diff --git a/docs/configuration/v2.x/metrics/index.md b/docs/configuration/v2.x/metrics/index.md index 6d205cbbc..a94ef98bd 100644 --- a/docs/configuration/v2.x/metrics/index.md +++ b/docs/configuration/v2.x/metrics/index.md @@ -23,14 +23,16 @@ values are `v1`. *(Required)* ### Metric Defaults -- `metricDefaults.scraping.schedule` - A cron expression that controls - the frequency of which all the configured metrics will be scraped from Azure Monitor. - You can use [crontab-generator.org](https://crontab-generator.org/) to generate - a cron that fits your needs. *(Required)* - `metricDefaults.aggregation.interval` - The default interval which defines over what period measurements of a metric should be aggregated. a cron that fits your needs. +- `metricDefaults.limit` - The default maximum amount of resources to scrape when using dimensions + or filters. - `metricDefaults.labels` - The default labels that will be applied to all metrics. _(starting as of v2.3)_ +- `metricDefaults.scraping.schedule` - A cron expression that controls + the frequency of which all the configured metrics will be scraped from Azure Monitor. + You can use [crontab-generator.org](https://crontab-generator.org/) to generate + a cron that fits your needs. *(Required)* ### Metrics @@ -48,6 +50,8 @@ Every metric that is being declared needs to define the following fields: - `resources` - An array of one or more resources to get metrics for. The fields required vary depending on the `resourceType` being created, and are documented for each resource. +- `azureMetricConfiguration.limit` - The maximum amount of resources to scrape when using dimensions + or filters. - `resourceDiscoveryGroups` An array of one or more resource discovery groups that will be used to automatically discover all resources through Promitor Resource Discovery. For every found resource, it will get the metrics and report them. Learn more on resource discovery, in [our documentation](https://promitor.io/concepts/how-it-works#using-resource-discovery) @@ -84,12 +88,13 @@ azureMetadata: metricDefaults: aggregation: interval: 00:05:00 - scraping: - # Every minute - schedule: "0 * * ? * *" + limit: 10 labels: geo: china environment: dev + scraping: + # Every minute + schedule: "0 * * ? * *" metrics: - name: azure_service_bus_active_messages description: "The number of active messages on a service bus queue." @@ -102,6 +107,7 @@ metrics: schedule: "0 */2 * ? * *" azureMetricConfiguration: metricName: ActiveMessages + limit: 5 dimension: name: <dimension-name> aggregation: @@ -111,7 +117,6 @@ metrics: - namespace: promitor-messaging queueName: orders - namespace: promitor-messaging-dev - queueName: orders resourceGroupName: promitor-dev subscriptionId: ABC resourceDiscoveryGroups: diff --git a/src/Promitor.Agents.Scraper/Validation/Steps/MetricsDeclarationValidationStep.cs b/src/Promitor.Agents.Scraper/Validation/Steps/MetricsDeclarationValidationStep.cs index 2c74f3aa4..7fd43b5b9 100644 --- a/src/Promitor.Agents.Scraper/Validation/Steps/MetricsDeclarationValidationStep.cs +++ b/src/Promitor.Agents.Scraper/Validation/Steps/MetricsDeclarationValidationStep.cs @@ -78,6 +78,16 @@ private static IEnumerable<string> ValidateMetricDefaults(MetricDefaults metricD { yield return @"No default metric scraping schedule is defined."; } + + if (metricDefaults.Limit > Promitor.Core.Defaults.MetricDefaults.Limit) + { + yield return $"Limit cannot be higher than {Promitor.Core.Defaults.MetricDefaults.Limit}"; + } + + if (metricDefaults.Limit <= 0) + { + yield return @"Limit has to be at least 1"; + } } private static IEnumerable<string> DetectDuplicateMetrics(List<MetricDefinition> metrics) diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/MetricDefaultsDeserializer.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/MetricDefaultsDeserializer.cs index 1ff525e8c..8e0ca275d 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/MetricDefaultsDeserializer.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/MetricDefaultsDeserializer.cs @@ -1,5 +1,7 @@ -using Microsoft.Extensions.Logging; +using System.Collections.Generic; +using Microsoft.Extensions.Logging; using Promitor.Core.Scraping.Configuration.Serialization.v1.Model; +using YamlDotNet.RepresentationModel; namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Core { @@ -12,10 +14,22 @@ public MetricDefaultsDeserializer( { Map(defaults => defaults.Aggregation) .MapUsingDeserializer(aggregationDeserializer); + Map(defaults => defaults.Limit) + .MapUsing(DetermineLimit); Map(defaults => defaults.Scraping) .IsRequired() .MapUsingDeserializer(scrapingDeserializer); Map(defaults => defaults.Labels); } + + private object DetermineLimit(string rawLimit, KeyValuePair<YamlNode, YamlNode> nodePair, IErrorReporter errorReporter) + { + if (int.TryParse(rawLimit, out int limit)) + { + return limit; + } + + return null; + } } } diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/MetricDefaultsV1.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/MetricDefaultsV1.cs index 18ce22f83..91d839e9c 100644 --- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/MetricDefaultsV1.cs +++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/MetricDefaultsV1.cs @@ -17,6 +17,11 @@ public class MetricDefaultsV1 /// </summary> public ScrapingV1 Scraping { get; set; } + /// <summary> + /// The default amount of resources to scrape + /// </summary> + public int? Limit { get; set; } + /// <summary> /// The default metric labels. /// </summary> diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/GeneralMetricsDeclarationValidationStepTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/GeneralMetricsDeclarationValidationStepTests.cs index 393e0d5f1..f4b23395a 100644 --- a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/GeneralMetricsDeclarationValidationStepTests.cs +++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/GeneralMetricsDeclarationValidationStepTests.cs @@ -120,5 +120,58 @@ public void MetricsDeclaration_WithoutDefaultScrapingSchedule_Fails() // Assert PromitorAssert.ValidationFailed(validationResult); } + + [Fact] + public void MetricsDeclaration_WithDefaultScrapingSchedule_Succeeds() + { + // Arrange + var metricDefaults = new MetricDefaultsV1 + { + Scraping = new ScrapingV1 + { + Schedule = @"0 * * ? * *" + }, + Limit = 5 + }; + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithDefaults(metricDefaults) + .Build(_mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, _mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger<MetricsDeclarationValidationStep>.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationIsSuccessful(validationResult); + } + + [Theory] + [InlineData(-1)] + [InlineData(0)] + [InlineData(10001)] + public void MetricsDeclaration_WithInvalidDefaultMetricLimit_Fails(int metricLimit) + { + // Arrange + var metricDefaults = new MetricDefaultsV1 + { + Scraping = new ScrapingV1 + { + Schedule = @"0 * * ? * *" + }, + Limit = metricLimit + }; + var rawDeclaration = MetricsDeclarationBuilder.WithMetadata() + .WithDefaults(metricDefaults) + .Build(_mapper); + var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, _mapper); + + // Act + var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger<MetricsDeclarationValidationStep>.Instance); + var validationResult = scrapingScheduleValidationStep.Run(); + + // Assert + PromitorAssert.ValidationFailed(validationResult); + } } } \ No newline at end of file diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/StorageQueueMetricsDeclarationValidationStepTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/StorageQueueMetricsDeclarationValidationStepTests.cs index 9966c7b50..d07c5cbb1 100644 --- a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/StorageQueueMetricsDeclarationValidationStepTests.cs +++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/StorageQueueMetricsDeclarationValidationStepTests.cs @@ -37,7 +37,6 @@ public void StorageQueuesMetricsDeclaration_DeclarationWithNotSupportedMetricNam public void StorageQueuesMetricsDeclaration_DeclarationWithInvalidMetricLimit_Fails(int metricLimit) { // Arrange - var azureMetricName = Guid.NewGuid().ToString(); var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata() .WithStorageQueueMetric(azureMetricLimit: metricLimit) .Build(Mapper);