Skip to content

Commit

Permalink
Provide Container Registry scraper (#455)
Browse files Browse the repository at this point in the history
Provide Container Registry scraper

Closes #325

### Configuration
```yaml
azureMetadata:
  tenantId: c8819874-9e56-4e3f-b1a8-1c0325138f27
  subscriptionId: 0f9d7fea-99e8-4768-8672-06a28514f77e
  resourceGroupName: promitor-sources
metricDefaults:
  aggregation:
    interval: 01:00:00
metrics:
  - name: demo_generic_total_pull_count
    description: "Amount of images that were pulled from the container registry"
    resourceType: ContainerRegistry
    registryName: promitor
    azureMetricConfiguration:
      metricName: TotalPullCount
      aggregation:
        type: Average
```

### Output
```yaml
# HELP demo_generic_total_pull_count Amount of images that were pulled from the container registry
# TYPE demo_generic_total_pull_count gauge
demo_generic_total_pull_count 1 1553635305491
```
### Portal
![image](https://user-images.githubusercontent.com/4345663/55034449-b5015280-4fd2-11e9-8332-f10033d647dd.png)
  • Loading branch information
tomkerkhove authored Mar 27, 2019
1 parent e347fc2 commit 71244fc
Show file tree
Hide file tree
Showing 17 changed files with 529 additions and 155 deletions.
27 changes: 27 additions & 0 deletions docs/configuration/metrics/container-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
layout: default
title: Azure Container Registry Declaration
---

## Azure Container Registry
You can declare to scrape an Azure Container Registry via the `ContainerRegistry` resource type.

The following fields need to be provided:
- `containerGroup` - The name of the container group

All supported metrics are not documented in the official [Azure Monitor documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported) documentation yet, but it's being added via [this PR](https://github.com/MicrosoftDocs/azure-docs/pull/27991).

Example:
```yaml
name: demo_container_registry_total_pull_count
description: "Amount of images that were pulled from the container registry"
resourceType: ContainerRegistry
registryName: promitor
azureMetricConfiguration:
metricName: TotalPullCount
aggregation:
type: Average
```
[&larr; back to metrics declarations](/configuration/metrics)<br />
[&larr; back to introduction](/)
3 changes: 2 additions & 1 deletion docs/configuration/metrics/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ Every Azure service is supported and can be scraped by using the [Generic Azure
We also provide a simplified way to configure the following Azure resources:

- [Azure Container Instances](container-instances)
- [Azure Container Registry](container-registry)
- [Azure Service Bus Queue](service-bus-queue)
- [Azure Storage Queue](storage-queue)
- [Azure Virtual Machine](virtual-machine)
- [Azure Storage Queue](storage-queue)

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes
{
public class ContainerRegistryMetricDefinition : MetricDefinition
{
public string RegistryName { get; set; }
public override ResourceType ResourceType { get; } = ResourceType.ContainerRegistry;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public enum ResourceType
Generic = 2,
StorageQueue = 3,
ContainerInstance = 4,
VirtualMachine = 5
VirtualMachine = 5,
ContainerRegistry = 6
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Promitor.Core.Scraping.Configuration.Model.Metrics;
using Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.Deserializers
{
internal class ContainerRegistryMetricDeserializer : GenericAzureMetricDeserializer
{
/// <summary>Deserializes the specified Container Registry metric node from the YAML configuration file.</summary>
/// <param name="metricNode">The metric node to deserialize to Container Registry configuration</param>
/// <returns>A new <see cref="MetricDefinition"/> object (strongly typed as a <see cref="ContainerRegistryMetricDefinition"/>) </returns>
internal override MetricDefinition Deserialize(YamlMappingNode metricNode)
{
var metricDefinition = base.DeserializeMetricDefinition<ContainerRegistryMetricDefinition>(metricNode);

var registryName = metricNode.Children[new YamlScalarNode("registryName")];
metricDefinition.RegistryName = registryName?.ToString();

return metricDefinition;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal static GenericAzureMetricDeserializer GetDeserializerFor(Configuration.
return new ContainerInstanceMetricDeserializer();
case Configuration.Model.ResourceType.VirtualMachine:
return new VirtualMachineMetricDeserializer();
case Configuration.Model.ResourceType.ContainerRegistry:
return new ContainerRegistryMetricDeserializer();
}

throw new ArgumentOutOfRangeException($@"Resource Type {resource} not supported.");
Expand Down
2 changes: 2 additions & 0 deletions src/Promitor.Core.Scraping/Factories/MetricScraperFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public static IScraper<MetricDefinition> CreateScraper(ResourceType metricDefini
return new ContainerInstanceScraper(azureMetadata, metricDefaults, azureMonitorClient, logger, exceptionTracker);
case ResourceType.VirtualMachine:
return new VirtualMachineScraper(azureMetadata, metricDefaults, azureMonitorClient, logger, exceptionTracker);
case ResourceType.ContainerRegistry:
return new ContainerRegistryScraper(azureMetadata, metricDefaults, azureMonitorClient, logger, exceptionTracker);
default:
throw new ArgumentOutOfRangeException();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Threading.Tasks;
using Microsoft.Azure.Management.Monitor.Fluent.Models;
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Model;
using Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;
using Promitor.Core.Telemetry.Interfaces;
using Promitor.Integrations.AzureMonitor;

namespace Promitor.Core.Scraping.ResourceTypes
{
public class ContainerRegistryScraper : Scraper<ContainerRegistryMetricDefinition>
{
private const string ResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerRegistry/registries/{2}";

public ContainerRegistryScraper(AzureMetadata azureMetadata, MetricDefaults metricDefaults, AzureMonitorClient azureMonitorClient, ILogger logger, IExceptionTracker exceptionTracker)
: base(azureMetadata, metricDefaults, azureMonitorClient, logger, exceptionTracker)
{
}

protected override async Task<double> ScrapeResourceAsync(string subscriptionId, string resourceGroupName, ContainerRegistryMetricDefinition metricDefinition, AggregationType aggregationType, TimeSpan aggregationInterval)
{
var resourceUri = string.Format(ResourceUriTemplate, subscriptionId, resourceGroupName, metricDefinition.RegistryName);

var metricName = metricDefinition.AzureMetricConfiguration.MetricName;
var foundMetricValue = await AzureMonitorClient.QueryMetricAsync(metricName, aggregationType, aggregationInterval, resourceUri);

return foundMetricValue;
}
}
}
61 changes: 61 additions & 0 deletions src/Promitor.Scraper.Host/Docs/Open-Api.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ internal static IMetricValidator GetValidatorFor(ResourceType resourceType)
return new ContainerInstanceMetricValidator();
case ResourceType.VirtualMachine:
return new VirtualMachineMetricValidator();
case ResourceType.ContainerRegistry:
return new ContainerRegistryMetricValidator();
}

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
@@ -0,0 +1,23 @@
using System.Collections.Generic;
using GuardNet;
using Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;

namespace Promitor.Scraper.Host.Validation.MetricDefinitions.ResourceTypes
{
internal class ContainerRegistryMetricValidator : MetricValidator<ContainerRegistryMetricDefinition>
{
protected override IEnumerable<string> Validate(ContainerRegistryMetricDefinition containerRegistryMetricDefinition)
{
Guard.NotNull(containerRegistryMetricDefinition, nameof(containerRegistryMetricDefinition));

var errorMessages = new List<string>();

if (string.IsNullOrWhiteSpace(containerRegistryMetricDefinition.RegistryName))
{
errorMessages.Add("No registry name is configured");
}

return errorMessages;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,22 @@ public string Build()
return this;
}

public MetricsDeclarationBuilder WithAzureStorageQueueMetric(string metricName = "promitor-storage-queue", string metricDescription = "Description for a metric", string queueName = "promitor-queue", string accountName = "promitor-account", string sasToken="?sig=promitor", string azureMetricName = AzureStorageConstants.Queues.Metrics.MessageCount)
public MetricsDeclarationBuilder WithContainerRegistryMetric(string metricName = "promitor-container-registry", string metricDescription = "Description for a metric", string registryName = "promitor-container-registry", string azureMetricName = "Total")
{
var azureMetricConfiguration = CreateAzureMetricConfiguration(azureMetricName);
var metric = new ContainerRegistryMetricDefinition
{
Name = metricName,
Description = metricDescription,
RegistryName = registryName,
AzureMetricConfiguration = azureMetricConfiguration
};
_metrics.Add(metric);

return this;
}

public MetricsDeclarationBuilder WithAzureStorageQueueMetric(string metricName = "promitor", string metricDescription = "Description for a metric", string queueName = "promitor-queue", string accountName = "promitor-account", string sasToken="?sig=promitor", string azureMetricName = AzureStorageConstants.Queues.Metrics.MessageCount)
{
var azureMetricConfiguration = CreateAzureMetricConfiguration(azureMetricName);
var metric = new StorageQueueMetricDefinition
Expand Down
Loading

0 comments on commit 71244fc

Please sign in to comment.