Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide Azure Virtual Machine Scale Set (VMSS) Scraper #816

Merged
merged 3 commits into from
Jan 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions changelog/content/experimental/unreleased.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: "(2018-09-15)"
date: 2018-09-02T20:46:47+02:00
weight: 1
version:
---

- {{% tag added %}} Azure Virtual Machine Scale Set Scraper ([docs](https://promitor.io/configuration/v1.x/metrics/virtual-machine-scale-set) | [#310](https://github.com/tomkerkhove/promitor/issues/310))
1 change: 1 addition & 0 deletions docs/configuration/v1.x/metrics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ We also provide a simplified way to scrape the following Azure resources:
- [Azure SQL Managed Instance](sql-managed-instance)
- [Azure Storage Queue](storage-queue)
- [Azure Virtual Machine](virtual-machine)
- [Azure Virtual Machine Scale Set (VMSS)](virtual-machine-scale-set)

Want to help out? Create an issue and [contribute a new scraper](https://github.com/tomkerkhove/promitor/blob/master/adding-a-new-scraper.md).

Expand Down
36 changes: 36 additions & 0 deletions docs/configuration/v1.x/metrics/virtual-machine-scale-set.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
layout: default
title: Azure Virtual Machine Scale Set (VMSS) Declaration
---

## Azure Virtual Machine Scale Set (VMSS) - ![Availability Badge](https://img.shields.io/badge/Available%20Starting-v1.2-green.svg)

You can declare to scrape an Azure Virtual Machine Scale Set via the `VirtualMachineScaleSet` resource
type.

The following fields need to be provided:

- `scaleSetName` - The name of the Virtual Machine Scale Set

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

Example:

```yaml
name: azure_virtual_machine_scale_set_percentage_cpu
description: "Average percentage cpu usage on an Azure virtual machine scale set"
resourceType: VirtualMachineScaleSet
azureMetricConfiguration:
metricName: Percentage CPU
dimension:
name: VMName
aggregation:
type: Average
resources:
- scaleSetName: promitor-virtual-machine-scale-set-1
```

<!-- markdownlint-disable MD033 -->
[&larr; back to metrics declarations](/configuration/v1.x/metrics)<br />
[&larr; back to introduction](/)
<!-- markdownlint-enable -->
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
/// <summary>
/// Represents an Azure SQL Managed Instance resource.
/// </summary>
public class SqlManagedInstanceDefinition : AzureResourceDefinition
public class SqlManagedInstanceResourceDefinition : AzureResourceDefinition
{
/// <summary>
/// Initializes a new instance of the <see cref="SqlManagedInstanceDefinition" /> class.
/// Initializes a new instance of the <see cref="SqlManagedInstanceResourceDefinition" /> class.
/// </summary>
/// <param name="resourceGroupName">The name of the resource group the server is in.</param>
/// <param name="instanceName">The name of the Azure SQL Managed Instance resource.</param>
public SqlManagedInstanceDefinition(string resourceGroupName, string instanceName)
public SqlManagedInstanceResourceDefinition(string resourceGroupName, string instanceName)
: base(ResourceType.SqlManagedInstance, resourceGroupName)
{
InstanceName = instanceName;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes
{
public class VirtualMachineScaleSetResourceDefinition : AzureResourceDefinition
{
public VirtualMachineScaleSetResourceDefinition(string resourceGroupName, string scaleSetName)
: base(ResourceType.VirtualMachineScaleSet, resourceGroupName)
{
ScaleSetName = scaleSetName;
}

public string ScaleSetName { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum ResourceType
RedisCache = 9,
PostgreSql = 10,
SqlDatabase = 11,
SqlManagedInstance = 12
SqlManagedInstance = 12,
VirtualMachineScaleSet = 13
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public IDeserializer<AzureResourceDefinitionV1> GetDeserializerFor(ResourceType
case ResourceType.SqlManagedInstance:
var sqlManagedInstanceLogger = _loggerFactory.CreateLogger<SqlManagedInstanceDeserializer>();
return new SqlManagedInstanceDeserializer(sqlManagedInstanceLogger);
case ResourceType.VirtualMachineScaleSet:
var virtualMachineScaleSetLogger = _loggerFactory.CreateLogger<VirtualMachineScaleSetDeserializer>();
return new VirtualMachineScaleSetDeserializer(virtualMachineScaleSetLogger);
default:
throw new ArgumentOutOfRangeException($"Resource Type {resourceType} not supported.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public V1MappingProfile()
CreateMap<StorageQueueResourceV1, StorageQueueResourceDefinition>();
CreateMap<VirtualMachineResourceV1, VirtualMachineResourceDefinition>();
CreateMap<SqlDatabaseResourceV1, SqlDatabaseResourceDefinition>();
CreateMap<SqlManagedInstanceResourceV1, SqlManagedInstanceDefinition>();
CreateMap<SqlManagedInstanceResourceV1, SqlManagedInstanceResourceDefinition>();
CreateMap<VirtualMachineScaleSetResourceV1, VirtualMachineScaleSetResourceDefinition>();

CreateMap<MetricDefinitionV1, PrometheusMetricDefinition>();

Expand All @@ -52,7 +53,8 @@ public V1MappingProfile()
.Include<StorageQueueResourceV1, StorageQueueResourceDefinition>()
.Include<VirtualMachineResourceV1, VirtualMachineResourceDefinition>()
.Include<SqlDatabaseResourceV1, SqlDatabaseResourceDefinition>()
.Include<SqlManagedInstanceResourceV1, SqlManagedInstanceDefinition>();
.Include<SqlManagedInstanceResourceV1, SqlManagedInstanceResourceDefinition>()
.Include<VirtualMachineScaleSetResourceV1, VirtualMachineScaleSetResourceDefinition>();
}
}
}
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 a virtual machine scale set.
/// </summary>
public class VirtualMachineScaleSetResourceV1 : AzureResourceDefinitionV1
{
/// <summary>
/// The name of the scale set machine to get metrics for.
/// </summary>
public string ScaleSetName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model;
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model.ResourceTypes;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Providers
{
public class VirtualMachineScaleSetDeserializer : ResourceDeserializer
{
private const string ScaleSetNameTag = "scaleSetName";

public VirtualMachineScaleSetDeserializer(ILogger<VirtualMachineScaleSetDeserializer> logger) : base(logger)
{
}

protected override AzureResourceDefinitionV1 DeserializeResource(YamlMappingNode node)
{
var scaleSetName = node.GetString(ScaleSetNameTag);

return new VirtualMachineScaleSetResourceV1
{
ScaleSetName = scaleSetName
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public IScraper<AzureResourceDefinition> CreateScraper(ResourceType metricDefini
return new SqlDatabaseScraper(scraperConfiguration);
case ResourceType.SqlManagedInstance:
return new SqlManagedInstanceScraper(scraperConfiguration);
case ResourceType.VirtualMachineScaleSet:
return new VirtualMachineScaleSetScraper(scraperConfiguration);
default:
throw new ArgumentOutOfRangeException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Promitor.Core.Scraping.ResourceTypes
{
public class SqlManagedInstanceScraper : Scraper<SqlManagedInstanceDefinition>
public class SqlManagedInstanceScraper : Scraper<SqlManagedInstanceResourceDefinition>
{
private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Sql/managedInstances/{2}";

Expand All @@ -18,13 +18,13 @@ public SqlManagedInstanceScraper(ScraperConfiguration scraperConfiguration) : ba
{
}

protected override async Task<ScrapeResult> ScrapeResourceAsync(string subscriptionId, ScrapeDefinition<AzureResourceDefinition> scrapeDefinition, SqlManagedInstanceDefinition resourceDefinition, AggregationType aggregationType, TimeSpan aggregationInterval)
protected override async Task<ScrapeResult> ScrapeResourceAsync(string subscriptionId, ScrapeDefinition<AzureResourceDefinition> scrapeDefinition, SqlManagedInstanceResourceDefinition resourceResourceDefinition, AggregationType aggregationType, TimeSpan aggregationInterval)
{
var resourceUri = string.Format(
ResourceUriTemplate,
AzureMetadata.SubscriptionId,
scrapeDefinition.ResourceGroupName,
resourceDefinition.InstanceName);
resourceResourceDefinition.InstanceName);

var metricName = scrapeDefinition.AzureMetricConfiguration.MetricName;
var dimensionName = scrapeDefinition.AzureMetricConfiguration.Dimension?.Name;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Management.Monitor.Fluent.Models;
using Promitor.Core.Scraping.Configuration.Model.Metrics;
using Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;

namespace Promitor.Core.Scraping.ResourceTypes
{
internal class VirtualMachineScaleSetScraper : Scraper<VirtualMachineScaleSetResourceDefinition>
{
private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualMachineScaleSets/{2}";

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

protected override async Task<ScrapeResult> ScrapeResourceAsync(string subscriptionId, ScrapeDefinition<AzureResourceDefinition> scrapeDefinition, VirtualMachineScaleSetResourceDefinition resource, AggregationType aggregationType, TimeSpan aggregationInterval)
{
var resourceUri = string.Format(ResourceUriTemplate, AzureMetadata.SubscriptionId, scrapeDefinition.ResourceGroupName, resource.ScaleSetName);

var metricName = scrapeDefinition.AzureMetricConfiguration.MetricName;
var dimensionName = scrapeDefinition.AzureMetricConfiguration.Dimension?.Name;
var foundMetricValue = await AzureMonitorClient.QueryMetricAsync(metricName,dimensionName, aggregationType, aggregationInterval, resourceUri);

return new ScrapeResult(subscriptionId, scrapeDefinition.ResourceGroupName, resource.ScaleSetName, resourceUri, foundMetricValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType)
return new SqlDatabaseMetricValidator();
case ResourceType.SqlManagedInstance:
return new SqlManagedInstanceMetricValidator();
case ResourceType.VirtualMachineScaleSet:
return new VirtualMachineScaleSetMetricValidator();
}

throw new ArgumentOutOfRangeException(nameof(resourceType), $"No validation rules are defined for metric type '{resourceType}'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public IEnumerable<string> Validate(MetricDefinition metricDefinition)
{
Guard.NotNull(metricDefinition, nameof(metricDefinition));

foreach (var definition in metricDefinition.Resources.Cast<SqlManagedInstanceDefinition>())
foreach (var definition in metricDefinition.Resources.Cast<SqlManagedInstanceResourceDefinition>())
{
if (string.IsNullOrWhiteSpace(definition.InstanceName))
{
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.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;
using Promitor.Scraper.Host.Validation.MetricDefinitions.Interfaces;

namespace Promitor.Scraper.Host.Validation.MetricDefinitions.ResourceTypes
{
internal class VirtualMachineScaleSetMetricValidator : IMetricValidator
{
public IEnumerable<string> Validate(MetricDefinition metricDefinition)
{
Guard.NotNull(metricDefinition, nameof(metricDefinition));

foreach (var resourceDefinition in metricDefinition.Resources.Cast<VirtualMachineScaleSetResourceDefinition>())
{
if (string.IsNullOrWhiteSpace(resourceDefinition.ScaleSetName))
{
yield return "No virtual machine scale set name is configured";
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,28 @@ public string Build(IMapper mapper)
return this;
}

public MetricsDeclarationBuilder WithVirtualMachineScaleSetMetric(string metricName = "promitor-virtual-machine-scale-set", string metricDescription = "Description for a metric", string scaleSetName = "promitor-scale-set-name", string azureMetricName = "Total")
{
var azureMetricConfiguration = CreateAzureMetricConfiguration(azureMetricName);
var resource = new VirtualMachineScaleSetResourceV1()
{
ScaleSetName = scaleSetName
};

var metric = new MetricDefinitionV1
{
Name = metricName,
Description = metricDescription,
AzureMetricConfiguration = azureMetricConfiguration,
Resources = new List<AzureResourceDefinitionV1> { resource },
ResourceType = ResourceType.VirtualMachineScaleSet
};

_metrics.Add(metric);

return this;
}

public MetricsDeclarationBuilder WithNetworkInterfaceMetric(string metricName = "promitor-network-interface", string metricDescription = "Description for a metric", string networkInterfaceName = "promitor-network-interface-name", string azureMetricName = "Total")
{
var azureMetricConfiguration = CreateAzureMetricConfiguration(azureMetricName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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.Scraper.Tests.Unit.Serialization.v1.Providers
{
[Category("Unit")]
public class VirtualMachineScaleSetDeserializerTests : ResourceDeserializerTest<VirtualMachineScaleSetDeserializer>
{
private readonly VirtualMachineScaleSetDeserializer _deserializer;

public VirtualMachineScaleSetDeserializerTests()
{
_deserializer = new VirtualMachineScaleSetDeserializer(Logger);
}

[Fact]
public void Deserialize_ScaleSetNameSupplied_SetsName()
{
YamlAssert.PropertySet<VirtualMachineScaleSetResourceV1, AzureResourceDefinitionV1, string>(
_deserializer,
"scaleSetName: promitor-vmss",
"promitor-vmss",
r => r.ScaleSetName);
}

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

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