Skip to content

Commit

Permalink
feat: Provide scraper for Azure Monitor Autoscale (#1624)
Browse files Browse the repository at this point in the history
* Serialization

Signed-off-by: Tom Kerkhove <kerkhove.tom@gmail.com>

* Provide scraping

Signed-off-by: Tom Kerkhove <kerkhove.tom@gmail.com>

* Docs

Signed-off-by: Tom Kerkhove <kerkhove.tom@gmail.com>
  • Loading branch information
tomkerkhove committed May 6, 2021
1 parent c8ddeed commit fd9807c
Show file tree
Hide file tree
Showing 22 changed files with 423 additions and 3 deletions.
2 changes: 2 additions & 0 deletions changelog/content/experimental/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ version:

#### Scraper

- {{% tag added %}} Provide scraper for Azure Monitor Autoscale ([docs](https://promitor.io/configuration/v2.x/metrics/monitor-autoscale)
| [#1593](https://github.com/tomkerkhove/promitor/issues/1593))
- {{% 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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ resourceDiscoveryGroups:
type: IoTHub
- name: key-vaults
type: KeyVault
- name: autoscaling-rules
type: MonitorAutoscale
- name: network-interfaces
type: NetworkInterface
- name: postgres-databases
Expand Down
25 changes: 25 additions & 0 deletions config/promitor/scraper/metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,31 @@ 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: promitor_demo_appplan_percentage_cpu
description: "Average percentage of memory usage on an Azure App Plan"
resourceType: AppPlan
Expand Down
1 change: 1 addition & 0 deletions docs/configuration/v2.x/metrics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ We also provide a simplified way to scrape the following Azure resources:
- [Azure Key Vault](key-vault)
- [Azure Kubernetes Service](kubernetes)
- [Azure Logic Apps](logic-apps)
- [Azure Monitor Autoscale](monitor-autoscale)
- [Azure Network Gateway](network-gateway)
- [Azure Network Interface](network-interface)
- [Azure Service Bus Namespace](service-bus-namespace)
Expand Down
40 changes: 40 additions & 0 deletions docs/configuration/v2.x/metrics/monitor-autoscale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: default
title: Azure Monitor Autoscale Declaration
---

## Azure Monitor Autoscale

![Availability Badge](https://img.shields.io/badge/Available%20Starting-v2.3-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 Monitor Autoscale via the `MonitorAutoscale`
resource type.

When using declared resources, the following fields need to be provided:

- `autoscaleSettingsName` - The name of the Azure Monitor Autoscale settings

All supported metrics are documented in the official [Azure Monitor documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/metrics-supported#microsoftinsightsautoscalesettings).

Example:

```yaml
- 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: ObservedCapacity
aggregation:
type: Average
resources: # Optional, required when no resource discovery is configured
- autoscaleSettingsName: app-service-autoscaling-rules
resourceDiscoveryGroups: # Optional, requires Promitor Resource Discovery agent (https://promitor.io/concepts/how-it-works#using-resource-discovery)
- name: autoscaling-rules
```
<!-- markdownlint-disable MD033 -->
[&larr; back to metrics declarations](/configuration/v2.x/metrics)<br />
[&larr; back to introduction](/)
<!-- markdownlint-enable -->
1 change: 1 addition & 0 deletions docs/configuration/v2.x/resource-discovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Dynamic resource discovery is supported for the following scrapers:
- [Azure Key Vault](metrics/key-vault)
- [Azure Kubernetes Service](metrics/kubernetes)
- [Azure Logic Apps](metrics/logic-apps)
- [Azure Monitor Autoscale](metrics/monitor-autoscale)
- [Azure Network Gateway](metrics/network-gateway)
- [Azure Network Interface](metrics/network-interface)
- [Azure Service Bus Namespace](metrics/service-bus-namespace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public static ResourceDiscoveryQuery UseResourceDiscoveryFor(ResourceType resour
return new KubernetesServiceDiscoveryQuery();
case ResourceType.LogicApp:
return new LogicAppDiscoveryQuery();
case ResourceType.MonitorAutoscale:
return new MonitorAutoscaleDiscoveryQuery();
case ResourceType.NetworkGateway:
return new NetworkGatewayDiscoveryQuery();
case ResourceType.NetworkInterface:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using GuardNet;
using Newtonsoft.Json.Linq;
using Promitor.Core.Contracts;
using Promitor.Core.Contracts.ResourceTypes;

namespace Promitor.Agents.ResourceDiscovery.Graph.ResourceTypes
{
public class MonitorAutoscaleDiscoveryQuery : ResourceDiscoveryQuery
{
public override string[] ResourceTypes => new[] { "microsoft.insights/autoscalesettings" };
public override string[] ProjectedFieldNames => new[] { "subscriptionId", "resourceGroup", "type", "name" };

public override AzureResourceDefinition ParseResults(JToken resultRowEntry)
{
Guard.NotNull(resultRowEntry, nameof(resultRowEntry));

var autoscaleSettingsName = resultRowEntry[3]?.ToString();

var resource = new MonitorAutoscaleResourceDefinition(resultRowEntry[0]?.ToString(), resultRowEntry[1]?.ToString(), autoscaleSettingsName);
return resource;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType)
return new KubernetesServiceMetricValidator();
case ResourceType.LogicApp:
return new LogicAppMetricValidator();
case ResourceType.MonitorAutoscale:
return new MonitorAutoscaleMetricValidator();
case ResourceType.NetworkGateway:
return new NetworkGatewayMetricValidator();
case ResourceType.NetworkInterface:
Expand Down
Original file line number Diff line number Diff line change
@@ -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 MonitorAutoscaleMetricValidator : IMetricValidator
{
public IEnumerable<string> Validate(MetricDefinition metricDefinition)
{
Guard.NotNull(metricDefinition, nameof(metricDefinition));

foreach (var resourceDefinition in metricDefinition.Resources.Cast<MonitorAutoscaleResourceDefinition>())
{
if (string.IsNullOrWhiteSpace(resourceDefinition.AutoscaleSettingsName))
{
yield return "No Azure Monitor Autoscale settings name is configured";
}
}
}
}
}
3 changes: 2 additions & 1 deletion src/Promitor.Core.Contracts/ResourceType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public enum ResourceType
SqlElasticPool = 33,
SynapseApacheSparkPool = 34,
SynapseSqlPool = 35,
SynapseWorkspace = 36
SynapseWorkspace = 36,
MonitorAutoscale = 37
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Promitor.Core.Contracts.ResourceTypes
{
public class MonitorAutoscaleResourceDefinition : AzureResourceDefinition
{
public MonitorAutoscaleResourceDefinition(string subscriptionId, string resourceGroupName, string autoscaleSettingsName)
: base(ResourceType.MonitorAutoscale, subscriptionId, resourceGroupName, autoscaleSettingsName)
{
AutoscaleSettingsName = autoscaleSettingsName;
}

public string AutoscaleSettingsName { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public IDeserializer<AzureResourceDefinitionV1> GetDeserializerFor(ResourceType
case ResourceType.LogicApp:
var logicAppLogger = _loggerFactory.CreateLogger<LogicAppDeserializer>();
return new LogicAppDeserializer(logicAppLogger);
case ResourceType.MonitorAutoscale:
var monitorAutoscaleLogger = _loggerFactory.CreateLogger<MonitorAutoscaleDeserializer>();
return new MonitorAutoscaleDeserializer(monitorAutoscaleLogger);
case ResourceType.NetworkGateway:
var networkGatewayLogger = _loggerFactory.CreateLogger<NetworkGatewayDeserializer>();
return new NetworkGatewayDeserializer(networkGatewayLogger);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public V1MappingProfile()
CreateMap<KeyVaultResourceV1, KeyVaultResourceDefinition>();
CreateMap<KubernetesServiceResourceV1, KubernetesServiceResourceDefinition>();
CreateMap<LogicAppResourceV1, LogicAppResourceDefinition>();
CreateMap<MonitorAutoscaleResourceV1, MonitorAutoscaleResourceDefinition>();
CreateMap<NetworkGatewayResourceV1, NetworkGatewayResourceDefinition>();
CreateMap<NetworkInterfaceResourceV1, NetworkInterfaceResourceDefinition>();
CreateMap<PostgreSqlResourceV1, PostgreSqlResourceDefinition>();
Expand Down Expand Up @@ -85,6 +86,7 @@ public V1MappingProfile()
.Include<KeyVaultResourceV1, KeyVaultResourceDefinition>()
.Include<KubernetesServiceResourceV1, KubernetesServiceResourceDefinition>()
.Include<LogicAppResourceV1, LogicAppResourceDefinition>()
.Include<MonitorAutoscaleResourceV1, MonitorAutoscaleResourceDefinition>()
.Include<NetworkGatewayResourceV1, NetworkGatewayResourceDefinition>()
.Include<NetworkInterfaceResourceV1, NetworkInterfaceResourceDefinition>()
.Include<PostgreSqlResourceV1, PostgreSqlResourceDefinition>()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes
{
/// <summary>
/// Contains the configuration required to scrape an Azure Monitor Autoscale settings.
/// </summary>
public class MonitorAutoscaleResourceV1 : AzureResourceDefinitionV1
{
/// <summary>
/// The name of the Azure Monitor Autoscale settings to get metrics for.
/// </summary>
public string AutoscaleSettingsName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;

namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers
{
public class MonitorAutoscaleDeserializer : ResourceDeserializer<MonitorAutoscaleResourceV1>
{
public MonitorAutoscaleDeserializer(ILogger<MonitorAutoscaleDeserializer> logger) : base(logger)
{
Map(resource => resource.AutoscaleSettingsName)
.IsRequired();
}
}
}
6 changes: 4 additions & 2 deletions src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ public IScraper<IAzureResourceDefinition> CreateScraper(ResourceType metricDefin
return new KeyVaultScraper(scraperConfiguration);
case ResourceType.KubernetesService:
return new KubernetesServiceScraper(scraperConfiguration);
case ResourceType.LogicApp:
return new LogicAppScraper(scraperConfiguration);
case ResourceType.MonitorAutoscale:
return new MonitorAutoscaleScraper(scraperConfiguration);
case ResourceType.NetworkGateway:
return new NetworkGatewayScraper(scraperConfiguration);
case ResourceType.NetworkInterface:
return new NetworkInterfaceScraper(scraperConfiguration);
case ResourceType.LogicApp:
return new LogicAppScraper(scraperConfiguration);
case ResourceType.PostgreSql:
return new PostgreSqlScraper(scraperConfiguration);
case ResourceType.RedisCache:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Promitor.Core.Contracts;
using Promitor.Core.Contracts.ResourceTypes;
using Promitor.Core.Scraping.Configuration.Model.Metrics;

namespace Promitor.Core.Scraping.ResourceTypes
{
internal class MonitorAutoscaleScraper : AzureMonitorScraper<MonitorAutoscaleResourceDefinition>
{
private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/autoscalesettings/{2}";

public MonitorAutoscaleScraper(ScraperConfiguration scraperConfiguration)
: base(scraperConfiguration)
{
}

protected override string BuildResourceUri(string subscriptionId, ScrapeDefinition<IAzureResourceDefinition> scrapeDefinition, MonitorAutoscaleResourceDefinition resource)
{
return string.Format(ResourceUriTemplate, subscriptionId, scrapeDefinition.ResourceGroupName, resource.AutoscaleSettingsName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,24 @@ public MetricsDeclarationBuilder WithLogicAppMetric(string metricName = "promito
return this;
}

public MetricsDeclarationBuilder WithMonitorAutoscaleMetric(string metricName = "promitor-autoscale",
string metricDescription = "Description for a metric",
string autoscaleSettingsName = "promitor-autoscale-rules",
string azureMetricName = "ObservedCapacity",
string resourceDiscoveryGroupName = "",
int? azureMetricLimit = null,
bool omitResource = false)
{
var resource = new MonitorAutoscaleResourceV1
{
AutoscaleSettingsName = autoscaleSettingsName
};

CreateAndAddMetricDefinition(ResourceType.MonitorAutoscale, metricName, metricDescription, resourceDiscoveryGroupName, omitResource, azureMetricName, azureMetricLimit, resource);

return this;
}

public MetricsDeclarationBuilder WithCosmosDbMetric(string metricName = "promitor-cosmosdb",
string metricDescription = "Description for a metric",
string dbName = "promitor-cosmosdb",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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 MonitorAutoscaleDeserializerTests : ResourceDeserializerTest<MonitorAutoscaleDeserializer>
{
private readonly MonitorAutoscaleDeserializer _deserializer;

public MonitorAutoscaleDeserializerTests()
{
_deserializer = new MonitorAutoscaleDeserializer(Logger);
}

[Fact]
public void Deserialize_AutoscaleSettingsNameSupplied_SetsName()
{
YamlAssert.PropertySet<MonitorAutoscaleResourceV1, AzureResourceDefinitionV1, string>(
_deserializer,
"autoscaleSettingsName: promitor-application-gateway",
"promitor-application-gateway",
r => r.AutoscaleSettingsName);
}

[Fact]
public void Deserialize_AutoscaleSettingsNameNotSupplied_Null()
{
YamlAssert.PropertyNull<MonitorAutoscaleResourceV1, AzureResourceDefinitionV1>(
_deserializer,
"resourceGroupName: promitor-group",
r => r.AutoscaleSettingsName);
}

[Fact]
public void Deserialize_AutoscaleSettingsNameNotSupplied_ReportsError()
{
// Arrange
var node = YamlUtils.CreateYamlNode("resourceGroupName: promitor-group");

// Act / Assert
YamlAssert.ReportsErrorForProperty(
_deserializer,
node,
"autoscaleSettingsName");
}

protected override IDeserializer<AzureResourceDefinitionV1> CreateDeserializer()
{
return new MonitorAutoscaleDeserializer(Logger);
}
}
}
Loading

0 comments on commit fd9807c

Please sign in to comment.