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

Metric deserialization refactor #439

Merged
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# General owners
* @tomkerkhove

# Hackaton Codeowners
docs/* @brusmx
deploy/* @brusmx @jsturtevant
charts/* @brusmx @jsturtevant
src/* @brandonh-msft @jsturtevant
9 changes: 5 additions & 4 deletions adding-a-new-scraper.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ This guide walks you through the process of adding a new scraper type.
-------------------------

## Configuration
1. Add your new scraping type to `ResourceType`
2. Describe what your configuration by creating `<New-Type>MetricDefinition`and inherit from `MetricDefinition`
3. Update the deserialization to support your new type in `MetricsDeserializer`
4. Provide a unit test that tests the deserialization based on our sample
1. Add your new scraping type to the `Promitor.Core.Scraping.Configuration.Model.ResourceType`
2. Describe the resource for which you're creating scraping metrics by creating `<New-Type>MetricDefinition`and inherit from `Promitor.Core.Scraping.Configuration.Model.Metrics.MetricDefinition` - this class should go in `.\src\Promitor.Core.Scraping\Configuration\Model\Metrics\ResourceTypes`
3. Create a new Deserializer in `.\src\Promitor.Core.Scraping\Configuration\Serialization\Deserializers`. This must inherit from `AzureMetricDeserializer`.
3. Update `Promitor.Core.Scraping.Factories.MetricDeserializerFactory` to handle your new resource type by returning a new instance of the Deserializer you created in the previous step.
4. Provide a unit test in `.\src\Promitor.Scraper.Tests.Unit\Serialization\MetricsDeclaration\` that tests the deserialization based on our sample

Going forward in this guide, `TMetricDefinition` will refer to your newly created configuration type.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Promitor.Core.Scraping.Configuration.Model.Metrics
{
public class MetricDefinition
public abstract class MetricDefinition
{
/// <summary>
/// Configuration about the Azure Monitor metric to scrape
Expand All @@ -20,6 +20,6 @@ public class MetricDefinition
/// <summary>
/// Type of resource that is configured
/// </summary>
public virtual ResourceType ResourceType { get; set; }
public abstract ResourceType ResourceType { get; }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
namespace Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes
{
public class GenericMetricDefinition : MetricDefinition
public class GenericAzureMetricDefinition : MetricDefinition
{
public string Filter { get; set; }
public override ResourceType ResourceType { get; set; } = ResourceType.Generic;
public override ResourceType ResourceType { get; } = ResourceType.Generic;
public string ResourceUri { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ public class ServiceBusQueueMetricDefinition : MetricDefinition
{
public string Namespace { get; set; }
public string QueueName { get; set; }
public override ResourceType ResourceType { get; set; } = ResourceType.ServiceBusQueue;
public override ResourceType ResourceType { get; } = ResourceType.ServiceBusQueue;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
namespace Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes
{
public class StorageQueueMetricDefinition: MetricDefinition
public class StorageQueueMetricDefinition : MetricDefinition
{
public string AccountName { get; set; }
public string QueueName { get; set; }
public string SasToken { get; set; }
public override ResourceType ResourceType { get; set; } = ResourceType.StorageQueue;
public override ResourceType ResourceType { get; } = ResourceType.StorageQueue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Model;
using Promitor.Core.Scraping.Configuration.Providers.Interfaces;
using Promitor.Core.Scraping.Configuration.Serialization;
using Promitor.Core.Scraping.Configuration.Serialization.Core;

namespace Promitor.Core.Scraping.Configuration.Providers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Promitor.Core.Scraping.Configuration.Model;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class AggregationDeserializer : Deserializer<Aggregation>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Promitor.Core.Scraping.Configuration.Model;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class AzureMetadataDeserializer : Deserializer<AzureMetadata>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Promitor.Core.Scraping.Configuration.Model;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class AzureMetricConfigurationDeserializer : Deserializer<AzureMetricConfiguration>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using Promitor.Core.Serialization.Yaml;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
public class ConfigurationSerializer
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Microsoft.Extensions.Logging;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal abstract class Deserializer<TObject>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Promitor.Core.Scraping.Configuration.Model;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class MetricAggregationDeserializer : Deserializer<MetricAggregation>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Promitor.Core.Scraping.Configuration.Model;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization
namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class MetricDefaultsDeserializer : Deserializer<MetricDefaults>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using GuardNet;
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Model.Metrics;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal abstract class MetricDeserializer
{
protected ILogger Logger { get; private set; }

internal MetricDeserializer WithLogger(ILogger logger)
{
Guard.NotNull(logger, nameof(logger));

Logger = logger;
return this;
}

internal abstract MetricDefinition Deserialize(YamlMappingNode metricNode);

protected virtual TMetricDefinition DeserializeMetricDefinition<TMetricDefinition>(YamlMappingNode metricNode)
where TMetricDefinition : MetricDefinition, new()
{
Guard.NotNull(metricNode, nameof(metricNode));

var name = metricNode.Children[new YamlScalarNode("name")];
var description = metricNode.Children[new YamlScalarNode("description")];
var azureMetricConfigurationNode = (YamlMappingNode)metricNode.Children[new YamlScalarNode("azureMetricConfiguration")];

var azureMetricConfigurationDeserializer = new AzureMetricConfigurationDeserializer(Logger);
var azureMetricConfiguration = azureMetricConfigurationDeserializer.Deserialize(azureMetricConfigurationNode);

var metricDefinition = new TMetricDefinition
{
Name = name?.ToString(),
Description = description?.ToString(),
AzureMetricConfiguration = azureMetricConfiguration
};

return metricDefinition;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using Microsoft.Extensions.Logging;
using Promitor.Core.Scraping.Configuration.Model;
using Promitor.Core.Scraping.Configuration.Model.Metrics;
using Promitor.Core.Scraping.Factories;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.Core
{
internal class MetricsDeserializer : Deserializer<MetricDefinition>
{
internal MetricsDeserializer(ILogger logger) : base(logger)
{
}

internal override MetricDefinition Deserialize(YamlMappingNode node)
{
var rawResourceType = node.Children[new YamlScalarNode("resourceType")];

if (!Enum.TryParse<ResourceType>(rawResourceType.ToString(), out var resourceType))
{
throw new ArgumentException($@"Unknown 'resourceType' value in metric configuration: {rawResourceType}");
}

return MetricDeserializerFactory
.GetDeserializerFor(resourceType)
.WithLogger(Logger)
.Deserialize(node);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Promitor.Core.Scraping.Configuration.Model.Metrics;
using Promitor.Core.Scraping.Configuration.Model.Metrics.ResourceTypes;
using Promitor.Core.Scraping.Configuration.Serialization.Core;
using YamlDotNet.RepresentationModel;

namespace Promitor.Core.Scraping.Configuration.Serialization.Deserializers
{
internal class GenericAzureMetricDeserializer : MetricDeserializer
{
/// <summary>Deserializes the specified Generic Azure metric node from the YAML configuration file.</summary>
/// <param name="metricNode">The metric node containing 'filter' and 'resourceUri' parameters pointing to an arbitrary Azure resource</param>
/// <returns>A new <see cref="MetricDefinition"/> object (strongly typed as a <see cref="GenericAzureMetricDefinition"/>) </returns>
internal override MetricDefinition Deserialize(YamlMappingNode metricNode)
{
tomkerkhove marked this conversation as resolved.
Show resolved Hide resolved
var metricDefinition = base.DeserializeMetricDefinition<GenericAzureMetricDefinition>(metricNode);

if (metricNode.Children.TryGetValue(new YamlScalarNode("filter"), out var filterNode))
{
metricDefinition.Filter = filterNode?.ToString();
}

var resourceUri = metricNode.Children[new YamlScalarNode("resourceUri")];

metricDefinition.ResourceUri = resourceUri?.ToString();

return metricDefinition;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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 ServiceBusQueueMetricDeserializer : GenericAzureMetricDeserializer
{
/// <summary>Deserializes the specified Service Bus Queue metric node from the YAML configuration file.</summary>
/// <param name="metricNode">The metric node containing 'queueName' and 'namespace' parameters pointing to an instance of a Service Bus queue</param>
/// <returns>A new <see cref="MetricDefinition"/> object (strongly typed as a <see cref="ServiceBusQueueMetricDefinition"/>) </returns>
internal override MetricDefinition Deserialize(YamlMappingNode metricNode)
{
var metricDefinition = base.DeserializeMetricDefinition<ServiceBusQueueMetricDefinition>(metricNode);

var queueName = metricNode.Children[new YamlScalarNode("queueName")];
var namespaceName = metricNode.Children[new YamlScalarNode("namespace")];

metricDefinition.QueueName = queueName?.ToString();
metricDefinition.Namespace = namespaceName?.ToString();

return metricDefinition;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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 StorageQueueMetricDeserializer : GenericAzureMetricDeserializer
{
/// <summary>Deserializes the specified Storage Queue metric node from the YAML configuration file.</summary>
/// <param name="metricNode">The metric node containing 'accountName', 'queueName', and 'sasToken' parameters pointing to an instance of a Storage queue</param>
/// <returns>A new <see cref="MetricDefinition"/> object (strongly typed as a <see cref="StorageQueueMetricDefinition"/>) </returns>
internal override MetricDefinition Deserialize(YamlMappingNode metricNode)
{
var metricDefinition = base.DeserializeMetricDefinition<StorageQueueMetricDefinition>(metricNode);
var accountName = metricNode.Children[new YamlScalarNode("accountName")];
var queueName = metricNode.Children[new YamlScalarNode("queueName")];
var sasToken = metricNode.Children[new YamlScalarNode("sasToken")];

metricDefinition.AccountName = accountName?.ToString();
metricDefinition.QueueName = queueName?.ToString();
metricDefinition.SasToken = sasToken?.ToString();

return metricDefinition;
}
}
}
Loading