diff --git a/changelog/content/experimental/unreleased.md b/changelog/content/experimental/unreleased.md
index ab9eee97a..46e17ace0 100644
--- a/changelog/content/experimental/unreleased.md
+++ b/changelog/content/experimental/unreleased.md
@@ -6,6 +6,10 @@ version:
#### Scraper
+- {{% tag added %}} Provide scraper for Azure Data Factory ([docs](https://promitor.io/configuration/v2.x/metrics/data-factory)
+ | [#359](https://github.com/tomkerkhove/promitor/issues/359))
+- {{% tag added %}} Provide scraper for Azure Data Share ([docs](https://promitor.io/configuration/v2.x/metrics/data-share)
+ | [#1678](https://github.com/tomkerkhove/promitor/issues/1678))
- {{% tag added %}} Provide system metrics related to agent performance & resources ([docs](https://promitor.io/operations/#performance)
| [#341](https://github.com/tomkerkhove/promitor/issues/341))
- {{% tag added %}} Provide system metrics indicating ARM throttling status ([docs](https://promitor.io/operations/#azure-resource-manager-api---consumption--throttling)
diff --git a/config/promitor/resource-discovery/resource-discovery-declaration.yaml b/config/promitor/resource-discovery/resource-discovery-declaration.yaml
index 1e43dd8e5..e68ae245b 100644
--- a/config/promitor/resource-discovery/resource-discovery-declaration.yaml
+++ b/config/promitor/resource-discovery/resource-discovery-declaration.yaml
@@ -20,6 +20,10 @@ resourceDiscoveryGroups:
type: ContainerRegistry
- name: cosmos-accounts
type: CosmosDb
+- name: data-factory-landscape
+ type: DataFactory
+- name: data-share-landscape
+ type: DataShare
- name: dps
type: DeviceProvisioningService
- name: event-hubs-landscape
diff --git a/config/promitor/scraper/metrics.yaml b/config/promitor/scraper/metrics.yaml
index 10ab884a1..c0a3763d6 100644
--- a/config/promitor/scraper/metrics.yaml
+++ b/config/promitor/scraper/metrics.yaml
@@ -14,250 +14,298 @@ metricDefaults:
# Every minute
schedule: "0 * * ? * *"
metrics:
-- name: promitor_demo_appplan_autoscale_instances_current_discovered
- description: "Average amount of current instances for an Azure App Plan with Azure Monitor Autoscale"
- resourceType: MonitorAutoscale
- labels:
- app: promitor
- azureMetricConfiguration:
- metricName: ObservedCapacity
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: autoscaling-rules
-- name: promitor_demo_appplan_autoscale_observed_capacity
- description: "Average amount of current instances for an Azure App Plan with Azure Monitor Autoscale"
- resourceType: MonitorAutoscale
- labels:
- app: promitor
- azureMetricConfiguration:
- metricName: MetricThreshold
- dimension:
- name: MetricTriggerRule
- aggregation:
- type: Average
- resources:
- - autoscaleSettingsName: app-service-autoscaling-rules
- resourceGroupName: demo
-- name: azure_container_registry_total_pull_count_discovered
- description: "Amount of images that were pulled from the container registry"
- resourceType: ContainerRegistry
- azureMetricConfiguration:
- metricName: TotalPullCount
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: container-registry-landscape
-- name: promitor_demo_appplan_percentage_cpu_discovered
- description: "Average percentage of memory usage on an Azure App Plan"
- resourceType: AppPlan
- azureMetricConfiguration:
- metricName: MemoryPercentage
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: app-plan-landscape
-- name: promitor_demo_webapp_cpu_discovery
- description: "Amount of CPU time used for an Azure Web App"
- resourceType: WebApp
- azureMetricConfiguration:
- metricName: CpuTime
- aggregation:
- type: Total
- resourceDiscoveryGroups:
- - name: web-app-landscape
-- name: promitor_demo_function_memory_discovery
- description: "Average memory for an Azure Function App"
- resourceType: FunctionApp
- azureMetricConfiguration:
- metricName: MemoryWorkingSet
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: function-app-landscape
-- name: azure_logic_apps_failed_run
- description: "Total amount of failed runs for Azure Logic Apps"
- resourceType: LogicApp
- azureMetricConfiguration:
- metricName: RunsFailed
- aggregation:
- type: Total
- resources:
- - workflowName: promitor-automation-github-ci-scraper
-- name: azure_logic_apps_failed_run_discovery
- description: "Total amount of failed runs for Azure Logic Apps"
- resourceType: LogicApp
- azureMetricConfiguration:
- metricName: RunsFailed
- aggregation:
- type: Total
- resourceDiscoveryGroups:
- - name: logic-apps-unfiltered
-- name: azure_storage_account_capacity_discovery
- description: "The average capacity used in the storage account"
- resourceType: StorageAccount
- azureMetricConfiguration:
- metricName: UsedCapacity
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: storage-accounts
-- name: azure_sql_database_cpu_percent_discovery
- description: "The CPU percentage used by an Azure SQL Database."
- resourceType: SqlDatabase
- azureMetricConfiguration:
- metricName: cpu_percent
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: sql-databases
-- name: promitor_demo_azuresqlmanagedinstance_nodes_discovery
- description: "The amount of nodes for an Azure SQL Managed Instance."
- resourceType: SqlManagedInstance
- azureMetricConfiguration:
- metricName: virtual_core_count
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: sql-managed-instances
-- name: azure_network_interface_bytes_received_rate_discovery
- description: "Number of bytes the Network Interface sent"
- resourceType: NetworkInterface
- azureMetricConfiguration:
- metricName: BytesReceivedRate
- aggregation:
- type: Average
- resourceDiscoveryGroups:
- - name: network-interfaces
-- name: azure_event_hubs_incoming_messages_discovery
- description: "The number of incoming messages on an Azure Event Hub namespace"
- resourceType: EventHubs
- azureMetricConfiguration:
- metricName: IncomingMessages
- aggregation:
- type: Total
- resourceDiscoveryGroups:
- - name: event-hubs-landscape
-- name: promitor_demo_servicebus_messagecount_discovered
- description: "Average percentage of memory usage on an Azure App Plan"
- resourceType: ServiceBusNamespace
- labels:
- geo: europe
- app: promitor
- azureMetricConfiguration:
- metricName: ActiveMessages
- aggregation:
- type: Average
- resources:
- - namespace: promitor-messaging
-- 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_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_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_appplan_autoscale_instances_current_discovered
+ description: "Average amount of current instances for an Azure App Plan with Azure Monitor Autoscale"
+ resourceType: MonitorAutoscale
+ labels:
+ app: promitor
+ azureMetricConfiguration:
+ metricName: ObservedCapacity
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: autoscaling-rules
+ - name: promitor_demo_appplan_autoscale_observed_capacity
+ description: "Average amount of current instances for an Azure App Plan with Azure Monitor Autoscale"
+ resourceType: MonitorAutoscale
+ labels:
+ app: promitor
+ azureMetricConfiguration:
+ metricName: MetricThreshold
+ dimension:
+ name: MetricTriggerRule
+ aggregation:
+ type: Average
+ resources:
+ - autoscaleSettingsName: app-service-autoscaling-rules
+ resourceGroupName: demo
+ - name: azure_container_registry_total_pull_count_discovered
+ description: "Amount of images that were pulled from the container registry"
+ resourceType: ContainerRegistry
+ azureMetricConfiguration:
+ metricName: TotalPullCount
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: container-registry-landscape
+ - name: promitor_demo_appplan_percentage_cpu_discovered
+ description: "Average percentage of memory usage on an Azure App Plan"
+ resourceType: AppPlan
+ azureMetricConfiguration:
+ metricName: MemoryPercentage
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: app-plan-landscape
+ - name: promitor_demo_webapp_cpu_discovery
+ description: "Amount of CPU time used for an Azure Web App"
+ resourceType: WebApp
+ azureMetricConfiguration:
+ metricName: CpuTime
+ aggregation:
+ type: Total
+ resourceDiscoveryGroups:
+ - name: web-app-landscape
+ - name: promitor_demo_function_memory_discovery
+ description: "Average memory for an Azure Function App"
+ resourceType: FunctionApp
+ azureMetricConfiguration:
+ metricName: MemoryWorkingSet
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: function-app-landscape
+ - name: azure_logic_apps_failed_run
+ description: "Total amount of failed runs for Azure Logic Apps"
+ resourceType: LogicApp
+ azureMetricConfiguration:
+ metricName: RunsFailed
+ aggregation:
+ type: Total
+ resources:
+ - workflowName: promitor-automation-github-ci-scraper
+ - name: azure_logic_apps_failed_run_discovery
+ description: "Total amount of failed runs for Azure Logic Apps"
+ resourceType: LogicApp
+ azureMetricConfiguration:
+ metricName: RunsFailed
+ aggregation:
+ type: Total
+ resourceDiscoveryGroups:
+ - name: logic-apps-unfiltered
+ - name: azure_storage_account_capacity_discovery
+ description: "The average capacity used in the storage account"
+ resourceType: StorageAccount
+ azureMetricConfiguration:
+ metricName: UsedCapacity
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: storage-accounts
+ - name: azure_sql_database_cpu_percent_discovery
+ description: "The CPU percentage used by an Azure SQL Database."
+ resourceType: SqlDatabase
+ azureMetricConfiguration:
+ metricName: cpu_percent
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: sql-databases
+ - name: promitor_demo_azuresqlmanagedinstance_nodes_discovery
+ description: "The amount of nodes for an Azure SQL Managed Instance."
+ resourceType: SqlManagedInstance
+ azureMetricConfiguration:
+ metricName: virtual_core_count
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: sql-managed-instances
+ - name: azure_network_interface_bytes_received_rate_discovery
+ description: "Number of bytes the Network Interface sent"
+ resourceType: NetworkInterface
+ azureMetricConfiguration:
+ metricName: BytesReceivedRate
+ aggregation:
+ type: Average
+ resourceDiscoveryGroups:
+ - name: network-interfaces
+ - name: azure_event_hubs_incoming_messages_discovery
+ description: "The number of incoming messages on an Azure Event Hub namespace"
+ resourceType: EventHubs
+ azureMetricConfiguration:
+ metricName: IncomingMessages
+ aggregation:
+ type: Total
+ resourceDiscoveryGroups:
+ - name: event-hubs-landscape
+ - name: promitor_demo_servicebus_messagecount_discovered
+ description: "Average percentage of memory usage on an Azure App Plan"
+ resourceType: ServiceBusNamespace
+ labels:
+ geo: europe
+ app: promitor
+ azureMetricConfiguration:
+ metricName: ActiveMessages
+ aggregation:
+ type: Average
+ resources:
+ - namespace: promitor-messaging
+ - 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_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_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_data_factory_pipeline_run_successful_declared
+ description: "Amount of successful pipeline runs in Azure Data Factory"
+ resourceType: DataFactory
+ azureMetricConfiguration:
+ metricName: PipelineSucceededRuns
+ aggregation:
+ type: Total
+ resources:
+ - resourceGroupName: promitor-sources
+ factoryName: promitor-data-factory
+ pipelineName: metric-generator
+ - name: promitor_demo_data_factory_pipeline_run_successful_discovered
+ description: "Amount of successful runs for 'metric generator' pipline in Azure Data Factory"
+ resourceType: DataFactory
+ azureMetricConfiguration:
+ metricName: PipelineSucceededRuns
+ aggregation:
+ type: Total
+ resourceDiscoveryGroups:
+ - name: data-factory-landscape
+ - name: promitor_demo_data_share_received_declared
+ description: "Amount of shares received from other parties per Azure Data Share account"
+ resourceType: DataShare
+ azureMetricConfiguration:
+ metricName: ShareSubscriptionCount
+ aggregation:
+ type: Maximum
+ resources:
+ - resourceGroupName: promitor-sources
+ accountName: promitor-data-share
+ - name: promitor_demo_data_share_received_discovered
+ description: "Amount of shares received from other parties per Azure Data Share account"
+ resourceType: DataShare
+ azureMetricConfiguration:
+ metricName: ShareSubscriptionCount
+ aggregation:
+ type: Maximum
+ resourceDiscoveryGroups:
+ - name: data-share-landscape
+ - name: promitor_demo_data_share_sent_discovered
+ description: "Amount of shares sent from other parties per Azure Data Share account"
+ resourceType: DataShare
+ azureMetricConfiguration:
+ metricName: ShareCount
+ aggregation:
+ type: Maximum
+ resourceDiscoveryGroups:
+ - name: data-share-landscape
diff --git a/docs/configuration/v2.x/metrics/data-factory.md b/docs/configuration/v2.x/metrics/data-factory.md
new file mode 100644
index 000000000..8413777f5
--- /dev/null
+++ b/docs/configuration/v2.x/metrics/data-factory.md
@@ -0,0 +1,44 @@
+---
+layout: default
+title: Azure Data Factory Declaration
+---
+
+## Azure Data Factory
+
+![Availability Badge](https://img.shields.io/badge/Available%20Starting-v2.5-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg)
+
+You can declare to scrape an Azure Data Factory resource via the `DataFactory` resource
+type.
+
+When using declared resources, the following fields need to be provided:
+
+- `factoryName` - The name of the Azure Data Factory resource
+- `pipelineName` - The name of the data pipeline *(optional)*
+
+All supported metrics are documented in the official [Azure Monitor documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/metrics-supported#microsoftdatafactoryfactories).
+
+The following scraper-specific metric label will be added:
+
+- `pipeline_name` - Name of the data pipeline.
+
+Example:
+
+```yaml
+- name: azure_data_factory_pipeline_run_successful
+ description: "Amount of successful runs for 'data-pipeline-example' pipline in Azure Data Factory"
+ resourceType: DataFactory
+ azureMetricConfiguration:
+ metricName: PipelineSucceededRuns
+ aggregation:
+ type: Total
+ resources: # Optional, required when no resource discovery is configured
+ - factoryName: promitor-data-factory
+ pipelineName: data-pipeline-example
+ resourceDiscoveryGroups: # Optional, requires Promitor Resource Discovery agent (https://promitor.io/concepts/how-it-works#using-resource-discovery)
+ - name: data-factory-landscape
+```
+
+
+[← back to metrics declarations](/configuration/v2.x/metrics)
+[← back to introduction](/)
+
diff --git a/docs/configuration/v2.x/metrics/data-share.md b/docs/configuration/v2.x/metrics/data-share.md
new file mode 100644
index 000000000..15893b283
--- /dev/null
+++ b/docs/configuration/v2.x/metrics/data-share.md
@@ -0,0 +1,44 @@
+---
+layout: default
+title: Azure Data Share Declaration
+---
+
+## Azure Data Share
+
+![Availability Badge](https://img.shields.io/badge/Available%20Starting-v2.5-green.svg)![Resource Discovery Support Badge](https://img.shields.io/badge/Support%20for%20Resource%20Discovery-Yes-green.svg)
+
+You can declare to scrape an Azure Data Share resource via the `DataShare` resource
+type.
+
+When using declared resources, the following fields need to be provided:
+
+- `accountName` - The name of the Azure Data Share account
+- `shareName` - The name of the share *(optional)*
+
+All supported metrics are documented in the official [Azure Monitor documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/metrics-supported#microsoftdatashareaccounts).
+
+The following scraper-specific metric label will be added:
+
+- `share_name` - Name of the share.
+
+Example:
+
+```yaml
+- name: promitor_demo_data_share_received
+ description: "Amount of shares received from other parties per Azure Data Share account"
+ resourceType: DataShare
+ azureMetricConfiguration:
+ metricName: ShareSubscriptionCount
+ aggregation:
+ type: Maximum
+ resources: # Optional, required when no resource discovery is configured
+ - accountName: promitor-data-share
+ shareName: Promitor
+ resourceDiscoveryGroups: # Optional, requires Promitor Resource Discovery agent (https://promitor.io/concepts/how-it-works#using-resource-discovery)
+ - name: data-share-landscape
+```
+
+
+[← back to metrics declarations](/configuration/v2.x/metrics)
+[← back to introduction](/)
+
diff --git a/docs/configuration/v2.x/metrics/index.md b/docs/configuration/v2.x/metrics/index.md
index 750778a7e..0fdcf163d 100644
--- a/docs/configuration/v2.x/metrics/index.md
+++ b/docs/configuration/v2.x/metrics/index.md
@@ -25,6 +25,8 @@ We also provide a simplified way to scrape the following Azure resources:
- [Azure Container Instances](container-instances)
- [Azure Container Registry](container-registry)
- [Azure Cosmos DB](cosmos-db)
+- [Azure Data Factory](data-factory)
+- [Azure Data Share](data-share)
- [Azure Database for PostgreSQL](postgresql)
- [Azure Event Hubs](event-hubs)
- [Azure Express Route Circuit](express-route-circuit)
diff --git a/docs/configuration/v2.x/resource-discovery.md b/docs/configuration/v2.x/resource-discovery.md
index 90dae0a44..589ad6013 100644
--- a/docs/configuration/v2.x/resource-discovery.md
+++ b/docs/configuration/v2.x/resource-discovery.md
@@ -95,6 +95,8 @@ Dynamic resource discovery is supported for the following scrapers:
- [Azure Container Instances](metrics/container-instances)
- [Azure Container Registry](metrics/container-registry)
- [Azure Cosmos DB](metrics/cosmos-db)
+- [Azure Data Factory](metrics/data-factory)
+- [Azure Data Share](metrics/data-share)
- [Azure Database for PostgreSQL](metrics/postgresql)
- [Azure Event Hubs](metrics/event-hubs)
- [Azure Express Route Circuit](metrics/express-route-circuit)
diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs
index 4f6bbc52c..18a2cc8ca 100644
--- a/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs
+++ b/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs
@@ -100,7 +100,6 @@ private async Task QueryAsync(string queryName, string query, Lis
return response;
}
- // TODO: Clean up
private async Task InteractWithAzureResourceGraphAsync(string queryName, string query, Func> interactionFunc, List targetSubscriptions = null)
{
Guard.NotNullOrWhitespace(query, nameof(query));
diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/Repositories/AzureResourceRepository.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/Repositories/AzureResourceRepository.cs
index a0ddd8595..da7f7c004 100644
--- a/src/Promitor.Agents.ResourceDiscovery/Graph/Repositories/AzureResourceRepository.cs
+++ b/src/Promitor.Agents.ResourceDiscovery/Graph/Repositories/AzureResourceRepository.cs
@@ -70,7 +70,6 @@ public virtual async Task> GetResourcesAsync(strin
return foundResources;
}
- // TODO: Unit test
public async Task> DiscoverAzureSubscriptionsAsync()
{
var query = @"ResourceContainers
@@ -90,7 +89,6 @@ public async Task> DiscoverAzureSubscriptions
});
}
- // TODO: Unit test
public async Task> DiscoverAzureResourceGroupsAsync()
{
var query = @"ResourceContainers
diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs
index cca408587..b82dac829 100644
--- a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs
+++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceDiscoveryFactory.cs
@@ -24,6 +24,10 @@ public static ResourceDiscoveryQuery UseResourceDiscoveryFor(ResourceType resour
return new ContainerRegistryDiscoveryQuery();
case ResourceType.CosmosDb:
return new CosmosDbDiscoveryQuery();
+ case ResourceType.DataFactory:
+ return new DataFactoryDiscoveryQuery();
+ case ResourceType.DataShare:
+ return new DataShareDiscoveryQuery();
case ResourceType.DeviceProvisioningService:
return new DeviceProvisioningServiceDiscoveryQuery();
case ResourceType.EventHubs:
diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataFactoryDiscoveryQuery.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataFactoryDiscoveryQuery.cs
new file mode 100644
index 000000000..757811033
--- /dev/null
+++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataFactoryDiscoveryQuery.cs
@@ -0,0 +1,22 @@
+using GuardNet;
+using Newtonsoft.Json.Linq;
+using Promitor.Core.Contracts;
+using Promitor.Core.Contracts.ResourceTypes;
+
+namespace Promitor.Agents.ResourceDiscovery.Graph.ResourceTypes
+{
+ public class DataFactoryDiscoveryQuery : ResourceDiscoveryQuery
+ {
+ public override string[] ResourceTypes => new[] { "microsoft.datafactory/factories" };
+ public override string[] ProjectedFieldNames => new[] { "subscriptionId", "resourceGroup", "type", "name", "id" };
+
+ public override AzureResourceDefinition ParseResults(JToken resultRowEntry)
+ {
+ Guard.NotNull(resultRowEntry, nameof(resultRowEntry));
+
+ var pipelineName = string.Empty; // We don't use pipeline name since we want all info
+ var resource = new DataFactoryResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), resultRowEntry[3]?.ToString(), pipelineName);
+ return resource;
+ }
+ }
+}
diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataShareDiscoveryQuery.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataShareDiscoveryQuery.cs
new file mode 100644
index 000000000..20e10c578
--- /dev/null
+++ b/src/Promitor.Agents.ResourceDiscovery/Graph/ResourceTypes/DataShareDiscoveryQuery.cs
@@ -0,0 +1,22 @@
+using GuardNet;
+using Newtonsoft.Json.Linq;
+using Promitor.Core.Contracts;
+using Promitor.Core.Contracts.ResourceTypes;
+
+namespace Promitor.Agents.ResourceDiscovery.Graph.ResourceTypes
+{
+ public class DataShareDiscoveryQuery : ResourceDiscoveryQuery
+ {
+ public override string[] ResourceTypes => new[] { "microsoft.datashare/accounts" };
+ public override string[] ProjectedFieldNames => new[] { "subscriptionId", "resourceGroup", "type", "name", "id" };
+
+ public override AzureResourceDefinition ParseResults(JToken resultRowEntry)
+ {
+ Guard.NotNull(resultRowEntry, nameof(resultRowEntry));
+
+ var shareName = string.Empty; // We don't use share name since we want all info
+ var resource = new DataShareResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), resultRowEntry[3]?.ToString(), shareName);
+ return resource;
+ }
+ }
+}
diff --git a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs
index 426356198..2b34f146e 100644
--- a/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs
+++ b/src/Promitor.Agents.Scraper/Validation/Factories/MetricValidatorFactory.cs
@@ -27,6 +27,10 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType)
return new ContainerRegistryMetricValidator();
case ResourceType.CosmosDb:
return new CosmosDbMetricValidator();
+ case ResourceType.DataFactory:
+ return new DataFactoryMetricValidator();
+ case ResourceType.DataShare:
+ return new DataShareMetricValidator();
case ResourceType.DeviceProvisioningService:
return new DeviceProvisioningServiceMetricValidator();
case ResourceType.EventHubs:
diff --git a/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataFactoryMetricValidator.cs b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataFactoryMetricValidator.cs
new file mode 100644
index 000000000..0ec1f9487
--- /dev/null
+++ b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataFactoryMetricValidator.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using System.Linq;
+using GuardNet;
+using Promitor.Core.Scraping.Configuration.Model.Metrics;
+using Promitor.Agents.Scraper.Validation.MetricDefinitions.Interfaces;
+using Promitor.Core.Contracts.ResourceTypes;
+
+namespace Promitor.Agents.Scraper.Validation.MetricDefinitions.ResourceTypes
+{
+ internal class DataFactoryMetricValidator : IMetricValidator
+ {
+ public IEnumerable Validate(MetricDefinition metricDefinition)
+ {
+ Guard.NotNull(metricDefinition, nameof(metricDefinition));
+
+ foreach (var resourceDefinition in metricDefinition.Resources.Cast())
+ {
+ if (string.IsNullOrWhiteSpace(resourceDefinition.FactoryName))
+ {
+ yield return "No Azure Data Factory name is configured";
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataShareMetricValidator.cs b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataShareMetricValidator.cs
new file mode 100644
index 000000000..9ebefbd90
--- /dev/null
+++ b/src/Promitor.Agents.Scraper/Validation/MetricDefinitions/ResourceTypes/DataShareMetricValidator.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using System.Linq;
+using GuardNet;
+using Promitor.Core.Scraping.Configuration.Model.Metrics;
+using Promitor.Agents.Scraper.Validation.MetricDefinitions.Interfaces;
+using Promitor.Core.Contracts.ResourceTypes;
+
+namespace Promitor.Agents.Scraper.Validation.MetricDefinitions.ResourceTypes
+{
+ internal class DataShareMetricValidator : IMetricValidator
+ {
+ public IEnumerable Validate(MetricDefinition metricDefinition)
+ {
+ Guard.NotNull(metricDefinition, nameof(metricDefinition));
+
+ foreach (var resourceDefinition in metricDefinition.Resources.Cast())
+ {
+ if (string.IsNullOrWhiteSpace(resourceDefinition.AccountName))
+ {
+ yield return "No Azure Data Share account name is configured";
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Core.Contracts/ResourceType.cs b/src/Promitor.Core.Contracts/ResourceType.cs
index 8c5c866ba..80e339f8d 100644
--- a/src/Promitor.Core.Contracts/ResourceType.cs
+++ b/src/Promitor.Core.Contracts/ResourceType.cs
@@ -39,6 +39,8 @@ public enum ResourceType
SynapseApacheSparkPool = 34,
SynapseSqlPool = 35,
SynapseWorkspace = 36,
- MonitorAutoscale = 37
+ MonitorAutoscale = 37,
+ DataFactory = 38,
+ DataShare = 39
}
}
\ No newline at end of file
diff --git a/src/Promitor.Core.Contracts/ResourceTypes/DataFactoryResourceDefinition.cs b/src/Promitor.Core.Contracts/ResourceTypes/DataFactoryResourceDefinition.cs
new file mode 100644
index 000000000..4f152aaf5
--- /dev/null
+++ b/src/Promitor.Core.Contracts/ResourceTypes/DataFactoryResourceDefinition.cs
@@ -0,0 +1,16 @@
+namespace Promitor.Core.Contracts.ResourceTypes
+{
+ public class DataFactoryResourceDefinition : AzureResourceDefinition
+ {
+ public DataFactoryResourceDefinition(string subscriptionId, string resourceGroupName, string factoryName, string pipelineName)
+ : base(ResourceType.DataFactory, subscriptionId, resourceGroupName, $"{factoryName}-{pipelineName}")
+ {
+ FactoryName = factoryName;
+ PipelineName = pipelineName;
+ }
+
+ public string FactoryName { get; }
+
+ public string PipelineName { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Core.Contracts/ResourceTypes/DataShareResourceDefinition.cs b/src/Promitor.Core.Contracts/ResourceTypes/DataShareResourceDefinition.cs
new file mode 100644
index 000000000..894815f60
--- /dev/null
+++ b/src/Promitor.Core.Contracts/ResourceTypes/DataShareResourceDefinition.cs
@@ -0,0 +1,15 @@
+namespace Promitor.Core.Contracts.ResourceTypes
+{
+ public class DataShareResourceDefinition : AzureResourceDefinition
+ {
+ public DataShareResourceDefinition(string subscriptionId, string resourceGroupName, string accountName, string shareName)
+ : base(ResourceType.DataShare, subscriptionId, resourceGroupName, $"{accountName}-{shareName}")
+ {
+ AccountName = accountName;
+ ShareName = shareName;
+ }
+
+ public string AccountName { get; }
+ public string ShareName { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Core.Scraping/AzureMonitorScraper.cs b/src/Promitor.Core.Scraping/AzureMonitorScraper.cs
index f00001821..a7ff55496 100644
--- a/src/Promitor.Core.Scraping/AzureMonitorScraper.cs
+++ b/src/Promitor.Core.Scraping/AzureMonitorScraper.cs
@@ -39,13 +39,13 @@ protected override async Task ScrapeResourceAsync(string subscript
var resourceUri = BuildResourceUri(subscriptionId, scrapeDefinition, resourceDefinition);
// Determine the metric filter to use, if any
- var metricFilter = DetermineMetricFilter(resourceDefinition);
+ var metricFilter = DetermineMetricFilter(metricName, resourceDefinition);
// Determine the metric limit to use, if any
var metricLimit = DetermineMetricLimit(scrapeDefinition);
// Determine the metric dimension to use, if any
- var dimensionName = DetermineMetricDimension(resourceDefinition, scrapeDefinition.AzureMetricConfiguration?.Dimension);
+ var dimensionName = DetermineMetricDimension(metricName, resourceDefinition, scrapeDefinition.AzureMetricConfiguration?.Dimension);
List measuredMetrics = new List();
try
@@ -95,8 +95,9 @@ protected virtual List EnrichMeasuredMetrics(TResourceDefinition
///
/// Determines the metric filter to use
///
+ /// Name of the metric being queried
/// Contains the resource cast to the specific resource type.
- protected virtual string DetermineMetricFilter(TResourceDefinition resourceDefinition)
+ protected virtual string DetermineMetricFilter(string metricName, TResourceDefinition resourceDefinition)
{
return null;
}
@@ -104,9 +105,10 @@ protected virtual string DetermineMetricFilter(TResourceDefinition resourceDefin
///
/// Determines the dimension for a metric to use
///
+ /// Name of the metric being queried
/// Contains the resource cast to the specific resource type.
/// Provides information concerning the configured metric dimension.
- protected virtual string DetermineMetricDimension(TResourceDefinition resourceDefinition, MetricDimension dimension)
+ protected virtual string DetermineMetricDimension(string metricName, TResourceDefinition resourceDefinition, MetricDimension dimension)
{
return dimension?.Name;
}
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs
index 9984eb206..65ad4fbd3 100644
--- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureResourceDeserializerFactory.cs
@@ -45,6 +45,12 @@ public IDeserializer GetDeserializerFor(ResourceType
case ResourceType.CosmosDb:
var cosmosDbLogger = _loggerFactory.CreateLogger();
return new CosmosDbDeserializer(cosmosDbLogger);
+ case ResourceType.DataFactory:
+ var dataFactoryDeserializer = _loggerFactory.CreateLogger();
+ return new DataFactoryDeserializer(dataFactoryDeserializer);
+ case ResourceType.DataShare:
+ var dataShareLogger = _loggerFactory.CreateLogger();
+ return new DataShareDeserializer(dataShareLogger);
case ResourceType.DeviceProvisioningService:
var deviceProvisioningServiceLogger = _loggerFactory.CreateLogger();
return new DeviceProvisioningServiceDeserializer(deviceProvisioningServiceLogger);
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs
index 79f221772..9ace8d7c5 100644
--- a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Mapping/V1MappingProfile.cs
@@ -30,6 +30,8 @@ public V1MappingProfile()
CreateMap();
CreateMap();
CreateMap();
+ CreateMap();
+ CreateMap();
CreateMap();
CreateMap();
CreateMap();
@@ -75,6 +77,8 @@ public V1MappingProfile()
.Include()
.Include()
.Include()
+ .Include()
+ .Include()
.Include()
.Include()
.Include()
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataFactoryResourceV1.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataFactoryResourceV1.cs
new file mode 100644
index 000000000..cae37699a
--- /dev/null
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataFactoryResourceV1.cs
@@ -0,0 +1,18 @@
+namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes
+{
+ ///
+ /// Contains the configuration required to scrape a Data Factory instance.
+ ///
+ public class DataFactoryResourceV1 : AzureResourceDefinitionV1
+ {
+ ///
+ /// The data factory name.
+ ///
+ public string FactoryName { get; set; }
+
+ ///
+ /// The data pipeline name.
+ ///
+ public string PipelineName { get; set; }
+ }
+}
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataShareResourceV1.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataShareResourceV1.cs
new file mode 100644
index 000000000..8c68266f6
--- /dev/null
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Model/ResourceTypes/DataShareResourceV1.cs
@@ -0,0 +1,18 @@
+namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes
+{
+ ///
+ /// Contains the configuration required to scrape a Data Share instance.
+ ///
+ public class DataShareResourceV1 : AzureResourceDefinitionV1
+ {
+ ///
+ /// The data share account name.
+ ///
+ public string AccountName { get; set; }
+
+ ///
+ /// The data share name.
+ ///
+ public string ShareName { get; set; }
+ }
+}
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataFactoryDeserializer.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataFactoryDeserializer.cs
new file mode 100644
index 000000000..84821cbc4
--- /dev/null
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataFactoryDeserializer.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.Logging;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;
+
+namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers
+{
+ public class DataFactoryDeserializer : ResourceDeserializer
+ {
+ public DataFactoryDeserializer(ILogger logger) : base(logger)
+ {
+ Map(resource => resource.FactoryName)
+ .IsRequired();
+ Map(resource => resource.PipelineName);
+ }
+ }
+}
diff --git a/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataShareDeserializer.cs b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataShareDeserializer.cs
new file mode 100644
index 000000000..cc49a6450
--- /dev/null
+++ b/src/Promitor.Core.Scraping/Configuration/Serialization/v1/Providers/DataShareDeserializer.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.Logging;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;
+
+namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers
+{
+ public class DataShareDeserializer : ResourceDeserializer
+ {
+ public DataShareDeserializer(ILogger logger) : base(logger)
+ {
+ Map(resource => resource.AccountName)
+ .IsRequired();
+ Map(resource => resource.ShareName);
+ }
+ }
+}
diff --git a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs
index 0b7ede68e..6c1999f64 100644
--- a/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs
+++ b/src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs
@@ -50,6 +50,10 @@ public IScraper CreateScraper(ResourceType metricDefin
return new ContainerRegistryScraper(scraperConfiguration);
case ResourceType.CosmosDb:
return new CosmosDbScraper(scraperConfiguration);
+ case ResourceType.DataFactory:
+ return new DataFactoryScraper(scraperConfiguration);
+ case ResourceType.DataShare:
+ return new DataShareScraper(scraperConfiguration);
case ResourceType.DeviceProvisioningService:
return new DeviceProvisioningServiceScraper(scraperConfiguration);
case ResourceType.EventHubs:
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/ApiManagementScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/ApiManagementScraper.cs
index 4d7893b0a..660924d74 100644
--- a/src/Promitor.Core.Scraping/ResourceTypes/ApiManagementScraper.cs
+++ b/src/Promitor.Core.Scraping/ResourceTypes/ApiManagementScraper.cs
@@ -22,11 +22,11 @@ protected override string BuildResourceUri(string subscriptionId, ScrapeDefiniti
return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.InstanceName);
}
- protected override string DetermineMetricFilter(ApiManagementResourceDefinition resourceDefinition)
+ protected override string DetermineMetricFilter(string metricName, ApiManagementResourceDefinition resourceDefinition)
{
if (string.IsNullOrWhiteSpace(resourceDefinition.LocationName))
{
- return base.DetermineMetricFilter(resourceDefinition);
+ return base.DetermineMetricFilter(metricName, resourceDefinition);
}
return $"Location eq '{resourceDefinition.LocationName}'";
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/AutomationAccountScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/AutomationAccountScraper.cs
index 11deb09d3..a1cda843d 100644
--- a/src/Promitor.Core.Scraping/ResourceTypes/AutomationAccountScraper.cs
+++ b/src/Promitor.Core.Scraping/ResourceTypes/AutomationAccountScraper.cs
@@ -22,11 +22,11 @@ protected override string BuildResourceUri(string subscriptionId, ScrapeDefiniti
return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.AccountName);
}
- protected override string DetermineMetricFilter(AutomationAccountResourceDefinition resourceDefinition)
+ protected override string DetermineMetricFilter(string metricName, AutomationAccountResourceDefinition resourceDefinition)
{
if (string.IsNullOrWhiteSpace(resourceDefinition.RunbookName))
{
- return base.DetermineMetricFilter(resourceDefinition);
+ return base.DetermineMetricFilter(metricName, resourceDefinition);
}
return $"Runbook eq '{resourceDefinition.RunbookName}'";
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/AzureMessagingScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/AzureMessagingScraper.cs
index 704d90317..80db3ad01 100644
--- a/src/Promitor.Core.Scraping/ResourceTypes/AzureMessagingScraper.cs
+++ b/src/Promitor.Core.Scraping/ResourceTypes/AzureMessagingScraper.cs
@@ -40,11 +40,11 @@ protected override Dictionary DetermineMetricLabels(TResourceDef
return metricLabels;
}
- protected override string DetermineMetricDimension(TResourceDefinition resourceDefinition, MetricDimension dimension)
+ protected override string DetermineMetricDimension(string metricName, TResourceDefinition resourceDefinition, MetricDimension dimension)
{
if (IsEntityDeclared(resourceDefinition))
{
- return base.DetermineMetricDimension(resourceDefinition, dimension);
+ return base.DetermineMetricDimension(metricName, resourceDefinition, dimension);
}
Logger.LogTrace("Using 'EntityName' dimension since no topic was configured.");
@@ -52,7 +52,7 @@ protected override string DetermineMetricDimension(TResourceDefinition resourceD
return "EntityName";
}
- protected override string DetermineMetricFilter(TResourceDefinition resourceDefinition)
+ protected override string DetermineMetricFilter(string metricName, TResourceDefinition resourceDefinition)
{
var entityName = "*";
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/DataFactoryScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/DataFactoryScraper.cs
new file mode 100644
index 000000000..a684b5058
--- /dev/null
+++ b/src/Promitor.Core.Scraping/ResourceTypes/DataFactoryScraper.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Logging;
+using Promitor.Core.Contracts;
+using Promitor.Core.Contracts.ResourceTypes;
+using Promitor.Core.Scraping.Configuration.Model;
+using Promitor.Core.Scraping.Configuration.Model.Metrics;
+
+namespace Promitor.Core.Scraping.ResourceTypes
+{
+ public class DataFactoryScraper : AzureMonitorScraper
+ {
+ private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DataFactory/factories/{2}";
+
+ public DataFactoryScraper(ScraperConfiguration scraperConfiguration)
+ : base(scraperConfiguration)
+ {
+ }
+
+ protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition scrapeDefinition, DataFactoryResourceDefinition resource)
+ {
+ return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.FactoryName);
+ }
+
+ protected override string DetermineMetricFilter(string metricName, DataFactoryResourceDefinition resourceDefinition)
+ {
+ var fieldName = GetMetricFilterFieldName(metricName);
+
+ var entityName = "*";
+
+ if (IsPipelineNameConfigured(resourceDefinition))
+ {
+ entityName = resourceDefinition.PipelineName;
+ }
+
+ return $"{fieldName} eq '{entityName}'";
+ }
+
+ protected override Dictionary DetermineMetricLabels(DataFactoryResourceDefinition resourceDefinition)
+ {
+ var metricLabels = base.DetermineMetricLabels(resourceDefinition);
+
+ if (IsPipelineNameConfigured(resourceDefinition))
+ {
+ metricLabels.Add("pipeline_name", resourceDefinition.PipelineName);
+ }
+
+ return metricLabels;
+ }
+
+ protected override string DetermineMetricDimension(string metricName, DataFactoryResourceDefinition resourceDefinition, MetricDimension dimension)
+ {
+ if (IsPipelineNameConfigured(resourceDefinition))
+ {
+ return base.DetermineMetricDimension(metricName, resourceDefinition, dimension);
+ }
+
+ var dimensionName = GetMetricFilterFieldName(metricName);
+ Logger.LogTrace($"Using '{dimensionName}' dimension since no pipeline name was configured.");
+
+ return dimensionName;
+ }
+
+ private static bool IsPipelineNameConfigured(DataFactoryResourceDefinition resourceDefinition)
+ {
+ return string.IsNullOrWhiteSpace(resourceDefinition.PipelineName) == false;
+ }
+
+ private static string GetMetricFilterFieldName(string metricName)
+ {
+ var fieldName = "Name";
+
+ // We need to switch field names when querying activities
+ if (metricName.Equals("ActivitySucceededRuns", StringComparison.InvariantCultureIgnoreCase)
+ || metricName.Equals("ActivityFailedRuns", StringComparison.InvariantCultureIgnoreCase)
+ || metricName.Equals("ActivityCancelledRuns", StringComparison.InvariantCultureIgnoreCase))
+ {
+ fieldName = "PipelineName";
+ }
+
+ return fieldName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/DataShareScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/DataShareScraper.cs
new file mode 100644
index 000000000..5ac73c34b
--- /dev/null
+++ b/src/Promitor.Core.Scraping/ResourceTypes/DataShareScraper.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Extensions.Logging;
+using Promitor.Core.Contracts;
+using Promitor.Core.Contracts.ResourceTypes;
+using Promitor.Core.Metrics;
+using Promitor.Core.Scraping.Configuration.Model;
+using Promitor.Core.Scraping.Configuration.Model.Metrics;
+
+namespace Promitor.Core.Scraping.ResourceTypes
+{
+ public class DataShareScraper : AzureMonitorScraper
+ {
+ private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DataShare/accounts/{2}";
+
+ public DataShareScraper(ScraperConfiguration scraperConfiguration)
+ : base(scraperConfiguration)
+ {
+ }
+
+ protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition scrapeDefinition, DataShareResourceDefinition resource)
+ {
+ return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.AccountName);
+ }
+
+ protected override string DetermineMetricFilter(string metricName, DataShareResourceDefinition resourceDefinition)
+ {
+ var fieldName = GetMetricFilterFieldName(metricName);
+
+ var entityName = "*";
+
+ if (IsShareNameConfigured(resourceDefinition))
+ {
+ entityName = resourceDefinition.ShareName;
+ }
+
+ return $"{fieldName} eq '{entityName}'";
+ }
+
+ protected override string DetermineMetricDimension(string metricName, DataShareResourceDefinition resourceDefinition, MetricDimension dimension)
+ {
+ if (IsShareNameConfigured(resourceDefinition))
+ {
+ return base.DetermineMetricDimension(metricName, resourceDefinition, dimension);
+ }
+
+ var dimensionName = GetMetricFilterFieldName(metricName);
+ Logger.LogTrace($"Using '{dimensionName}' dimension since no share name was configured.");
+
+ return dimensionName;
+ }
+
+ protected override List EnrichMeasuredMetrics(DataShareResourceDefinition resourceDefinition, string dimensionName, List metricValues)
+ {
+ // Change Azure Monitor dimension name to more representable value
+ foreach (var measuredMetric in metricValues.Where(metricValue => metricValue.DimensionName == "ShareName"
+ || metricValue.DimensionName == "ShareSubscriptionName"))
+ {
+ measuredMetric.DimensionName = "share_name";
+ }
+
+ return metricValues;
+ }
+
+ private static string GetMetricFilterFieldName(string metricName)
+ {
+ var fieldName = "ShareName";
+
+ // We need to switch field names when querying activities
+ if (metricName.Equals("ShareSubscriptionCount", StringComparison.InvariantCultureIgnoreCase))
+ {
+ fieldName = "ShareSubscriptionName";
+ }
+
+ return fieldName;
+ }
+
+ protected override Dictionary DetermineMetricLabels(DataShareResourceDefinition resourceDefinition)
+ {
+ var metricLabels = base.DetermineMetricLabels(resourceDefinition);
+
+ if (IsShareNameConfigured(resourceDefinition))
+ {
+ metricLabels.Add("share_name", resourceDefinition.ShareName);
+ }
+
+ return metricLabels;
+ }
+
+ private static bool IsShareNameConfigured(DataShareResourceDefinition resourceDefinition)
+ {
+ return string.IsNullOrWhiteSpace(resourceDefinition.ShareName) == false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Core.Scraping/ResourceTypes/GenericScraper.cs b/src/Promitor.Core.Scraping/ResourceTypes/GenericScraper.cs
index ce97b902d..c0c690a35 100644
--- a/src/Promitor.Core.Scraping/ResourceTypes/GenericScraper.cs
+++ b/src/Promitor.Core.Scraping/ResourceTypes/GenericScraper.cs
@@ -18,7 +18,7 @@ protected override string BuildResourceUri(string subscriptionId, ScrapeDefiniti
return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.ResourceUri);
}
- protected override string DetermineMetricFilter(GenericAzureResourceDefinition resourceDefinition)
+ protected override string DetermineMetricFilter(string metricName, GenericAzureResourceDefinition resourceDefinition)
{
return resourceDefinition.Filter;
}
diff --git a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs
index 4f7c9c7f2..13bdf8596 100644
--- a/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs
+++ b/src/Promitor.Tests.Unit/Builders/Metrics/v1/MetricsDeclarationBuilder.cs
@@ -148,6 +148,46 @@ public MetricsDeclarationBuilder WithContainerRegistryMetric(string metricName =
return this;
}
+ public MetricsDeclarationBuilder WithDataShareMetric(string metricName = "promitor-data-share",
+ string metricDescription = "Description for a metric",
+ string accountName = "promitor-data-share-account",
+ string shareName = "promitor-data-share",
+ string azureMetricName = "TotalRequests",
+ string resourceDiscoveryGroupName = "",
+ int? azureMetricLimit = null,
+ bool omitResource = false)
+ {
+ var resource = new DataShareResourceV1
+ {
+ AccountName = accountName,
+ ShareName = shareName
+ };
+
+ CreateAndAddMetricDefinition(ResourceType.DataShare, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, azureMetricLimit, resource);
+
+ return this;
+ }
+
+ public MetricsDeclarationBuilder WithDataFactoryMetric(string metricName = "promitor-data-factory",
+ string metricDescription = "Description for a metric",
+ string factoryName = "promitor-data-factory",
+ string pipelineName = "promitor-data-pipeline",
+ string azureMetricName = "TotalRequests",
+ string resourceDiscoveryGroupName = "",
+ int? azureMetricLimit = null,
+ bool omitResource = false)
+ {
+ var resource = new DataFactoryResourceV1
+ {
+ FactoryName = factoryName,
+ PipelineName = pipelineName
+ };
+
+ CreateAndAddMetricDefinition(ResourceType.DataFactory, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, azureMetricLimit, resource);
+
+ return this;
+ }
+
public MetricsDeclarationBuilder WithEventHubsMetric(string metricName = "promitor-event-hubs",
string metricDescription = "Description for a metric",
string metricDimension = "",
diff --git a/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataFactoryDeserializerTests.cs b/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataFactoryDeserializerTests.cs
new file mode 100644
index 000000000..1260eab35
--- /dev/null
+++ b/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataFactoryDeserializerTests.cs
@@ -0,0 +1,76 @@
+using System.ComponentModel;
+using Promitor.Core.Scraping.Configuration.Serialization;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Providers;
+using Xunit;
+
+namespace Promitor.Tests.Unit.Serialization.v1.Providers
+{
+ [Category("Unit")]
+ public class DataFactoryDeserializerTests : ResourceDeserializerTest
+ {
+ private readonly DataFactoryDeserializer _deserializer;
+
+ public DataFactoryDeserializerTests()
+ {
+ _deserializer = new DataFactoryDeserializer(Logger);
+ }
+
+ protected override IDeserializer CreateDeserializer()
+ {
+ return new DataFactoryDeserializer(Logger);
+ }
+
+ [Fact]
+ public void Deserialize_FactoryNameSupplied_SetsFactoryName()
+ {
+ YamlAssert.PropertySet(
+ _deserializer,
+ "factoryName: promitor-group",
+ "promitor-group",
+ c => c.FactoryName);
+ }
+
+ [Fact]
+ public void Deserialize_PipelineNameSupplied_SetsPipelineName()
+ {
+ YamlAssert.PropertySet(
+ _deserializer,
+ "pipelineName: staging",
+ "staging",
+ r => r.PipelineName);
+ }
+
+ [Fact]
+ public void Deserialize_PipelineNameNotSupplied_Null()
+ {
+ YamlAssert.PropertyNull(
+ _deserializer,
+ "resourceGroupName: promitor-group",
+ r => r.PipelineName);
+ }
+
+ [Fact]
+ public void Deserialize_FactoryNameNotSupplied_Null()
+ {
+ YamlAssert.PropertyNull(
+ _deserializer,
+ "resourceGroupName: promitor-resource-group",
+ c => c.FactoryName);
+ }
+
+ [Fact]
+ public void Deserialize_FactoryNameNotSupplied_ReportsError()
+ {
+ // Arrange
+ var node = YamlUtils.CreateYamlNode("resourceGroupName: promitor-resource-group");
+
+ // Act / Assert
+ YamlAssert.ReportsErrorForProperty(
+ _deserializer,
+ node,
+ "factoryName");
+ }
+ }
+}
diff --git a/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataShareDeserializerTests.cs b/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataShareDeserializerTests.cs
new file mode 100644
index 000000000..207b3fa42
--- /dev/null
+++ b/src/Promitor.Tests.Unit/Serialization/v1/Providers/DataShareDeserializerTests.cs
@@ -0,0 +1,76 @@
+using System.ComponentModel;
+using Promitor.Core.Scraping.Configuration.Serialization;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;
+using Promitor.Core.Scraping.Configuration.Serialization.v1.Providers;
+using Xunit;
+
+namespace Promitor.Tests.Unit.Serialization.v1.Providers
+{
+ [Category("Unit")]
+ public class DataShareDeserializerTests : ResourceDeserializerTest
+ {
+ private readonly DataShareDeserializer _deserializer;
+
+ public DataShareDeserializerTests()
+ {
+ _deserializer = new DataShareDeserializer(Logger);
+ }
+
+ protected override IDeserializer CreateDeserializer()
+ {
+ return new DataShareDeserializer(Logger);
+ }
+
+ [Fact]
+ public void Deserialize_AccountNameSupplied_SetsAccountName()
+ {
+ YamlAssert.PropertySet(
+ _deserializer,
+ "accountName: promitor-group",
+ "promitor-group",
+ c => c.AccountName);
+ }
+
+ [Fact]
+ public void Deserialize_AccountNameNotSupplied_Null()
+ {
+ YamlAssert.PropertyNull(
+ _deserializer,
+ "resourceGroupName: promitor-resource-group",
+ c => c.AccountName);
+ }
+
+ [Fact]
+ public void Deserialize_ShareNameSupplied_SetsShareName()
+ {
+ YamlAssert.PropertySet(
+ _deserializer,
+ "shareName: staging",
+ "staging",
+ r => r.ShareName);
+ }
+
+ [Fact]
+ public void Deserialize_ShareNameNotSupplied_Null()
+ {
+ YamlAssert.PropertyNull(
+ _deserializer,
+ "resourceGroupName: promitor-group",
+ r => r.ShareName);
+ }
+
+ [Fact]
+ public void Deserialize_AccountNameNotSupplied_ReportsError()
+ {
+ // Arrange
+ var node = YamlUtils.CreateYamlNode("resourceGroupName: promitor-resource-group");
+
+ // Act / Assert
+ YamlAssert.ReportsErrorForProperty(
+ _deserializer,
+ node,
+ "accountName");
+ }
+ }
+}
diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataFactoryMetricsDeclarationValidationStepTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataFactoryMetricsDeclarationValidationStepTests.cs
new file mode 100644
index 000000000..7791b7db1
--- /dev/null
+++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataFactoryMetricsDeclarationValidationStepTests.cs
@@ -0,0 +1,169 @@
+using System.ComponentModel;
+using Microsoft.Extensions.Logging.Abstractions;
+using Promitor.Agents.Scraper.Validation.Steps;
+using Promitor.Tests.Unit.Builders.Metrics.v1;
+using Promitor.Tests.Unit.Stubs;
+using Xunit;
+
+namespace Promitor.Tests.Unit.Validation.Scraper.Metrics.ResourceTypes
+{
+ [Category("Unit")]
+ public class DataFactoryMetricsDeclarationValidationStepTests : MetricsDeclarationValidationStepsTests
+ {
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(azureMetricName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(0)]
+ [InlineData(10001)]
+ public void DataFactoryMetricsDeclaration_DeclarationWithInvalidMetricLimit_Fails(int metricLimit)
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(azureMetricLimit: metricLimit)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutMetricDescription_Succeeded()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(metricDescription: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutMetricName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutFactoryName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(factoryName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutPipelineName_Succeeds()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(pipelineName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutResourceAndResourceDiscoveryGroupInfo_Fails()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(omitResource: true)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_DeclarationWithoutResourceButWithResourceDiscoveryGroupInfo_Succeeds()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric(omitResource: true, resourceDiscoveryGroupName:"sample-collection")
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataFactoryMetricsDeclaration_ValidDeclaration_Succeeds()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataFactoryMetric()
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataShareMetricsDeclarationValidationStepTests.cs b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataShareMetricsDeclarationValidationStepTests.cs
new file mode 100644
index 000000000..8aafd4304
--- /dev/null
+++ b/src/Promitor.Tests.Unit/Validation/Scraper/Metrics/ResourceTypes/DataShareMetricsDeclarationValidationStepTests.cs
@@ -0,0 +1,169 @@
+using System.ComponentModel;
+using Microsoft.Extensions.Logging.Abstractions;
+using Promitor.Agents.Scraper.Validation.Steps;
+using Promitor.Tests.Unit.Builders.Metrics.v1;
+using Promitor.Tests.Unit.Stubs;
+using Xunit;
+
+namespace Promitor.Tests.Unit.Validation.Scraper.Metrics.ResourceTypes
+{
+ [Category("Unit")]
+ public class DataShareMetricsDeclarationValidationStepTests : MetricsDeclarationValidationStepsTests
+ {
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutAzureMetricName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(azureMetricName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(0)]
+ [InlineData(10001)]
+ public void DataShareMetricsDeclaration_DeclarationWithInvalidMetricLimit_Fails(int metricLimit)
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(azureMetricLimit: metricLimit)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutMetricDescription_Succeeded()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(metricDescription: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutMetricName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutAccountName_Fails()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(accountName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutShareName_Succeeds()
+ {
+ // Arrange
+ var rawDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(shareName: string.Empty)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutResourceAndResourceDiscoveryGroupInfo_Fails()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(omitResource: true)
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationFailed(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_DeclarationWithoutResourceButWithResourceDiscoveryGroupInfo_Succeeds()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric(omitResource: true, resourceDiscoveryGroupName:"sample-collection")
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+
+ [Fact]
+ public void DataShareMetricsDeclaration_ValidDeclaration_Succeeds()
+ {
+ // Arrange
+ var rawMetricsDeclaration = MetricsDeclarationBuilder.WithMetadata()
+ .WithDataShareMetric()
+ .Build(Mapper);
+ var metricsDeclarationProvider = new MetricsDeclarationProviderStub(rawMetricsDeclaration, Mapper);
+
+ // Act
+ var scrapingScheduleValidationStep = new MetricsDeclarationValidationStep(metricsDeclarationProvider, NullLogger.Instance);
+ var validationResult = scrapingScheduleValidationStep.Run();
+
+ // Assert
+ PromitorAssert.ValidationIsSuccessful(validationResult);
+ }
+ }
+}
\ No newline at end of file