-
-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow multiple resources to be specified per metric (#683)
* Add a v2 serializer - Renaming the v1 serializer to `V1Serializer` to avoid having multiple classes all called `ConfigurationSerializer`. - Added the initial framework for the `V2Serializer`. * Implement v2 AzureMetadataDeserializer * Deserialize v2 metricDefaults * Make v2 deserializers inherit from Deserializer - Updated all the v2 deserializers. - Moved IDeserializer next to Deserializer, and adjusted the access levels from internal to public to allow unit testing. - Updated the V2Serializer to inherit from Deserializer. * Implemented AggregationDeserializer * Implement v2 Scraping deserializer * Implement v2 MetricDefinition deserialization * Pull utility methods to Deserializer object I've pulled a few utility methods up to the Deserializer object, and updated the v2 subclasses to use them. * Refactor common deserialization assertions Most of the tests were checking that a property had been set, or that it was null. As a result I've pulled those two assertions out to a helper class, and refactored the tests to use that helper. * Implement v2 container instance deserializer - Added the deserializer. - Added some extra assertions to `DeserializerTestHelpers` to help with the situation where a deserializer returns a base type, but we want to assert against another type. * Implement v2 container registry deserializer - Implemented the container registry deserializer. - Created a base class for azure resource deserializers to make sure ResourceGroupName is always deserialized. - Created a base class for the resource deserializer tests. * Implement v2 cosmos db deserializer * Implement v2 generic resource deserializer * Implement v2 network interface deserializer * Implement v2 postgre deserializer * Implement v2 redis cache deserializer * Implemented v2 service bus queue deserializer * Implement v2 virtual machine deserializer * Implement v2 secret deserializer * Implement v2 storage queue deserializer * Implement v2 azure metric config deserializer * Implement v2 metric aggregation deserializer I also added a `GetTimespan()` method to `Deserializer`, and updated the `AggregationDeserializer` to use that. * Remove duplicate enum deserialization method Removed `GetNullableEnum()` and altered `GetEnum()` to return a nullable enum. The rationale for this is that the configuration model should have null properties where nothing was supplied in the yaml. * Add v2 serialization integration test - Added a test that creates a v2 model, serializes it, deserializes it using the V2 deserializer, and then verifies it was deserialized correctly. - Implemented the AzureResourceDeserializerFactory. - Fixed a small typo where I had put "metrics" instead of "resources" as a yaml tag name in the MetricDefinitionDeserializer. - Defaulted the version in MetricsDeclarationV2 so you don't need to explicitly specify it when creating a v2 model. * Remove unnecessary type argument on null helpers The `AssertPropertyNull()` methods didn't actually need the property type argument because we can assert null against an object. * Rename v1 and v2 serializers They both handle deserialization, so I've renamed them to `{Version}Deserializer`. I've also rename the `InterpretYamlStream()` method in the v1 deserializer to `Deserialize()` since that's what it does. * Connect v2 format to application I've hooked the v2 format into the application so that it can actually be used. * Remove v1 config objects * Rename v2 objects back to v1 * Update example config for new format I've converted the example config so that it uses the new multi-resource format. * Updates as a result of PR feedback - Pulled Deserializer methods to extension methods. - Fixed some places where I'd left names as `v2`. - Removed the duplicated code for creating the deserializer in test classes to fix code factor tests. - Added missing doc-comments to resources. - Renamed DeserializerTestHelpers to YamlAssert. - Replaced mock loggers with NullLogger.Instance. - Various other fixes. * Fixing build issues - Removed TODO. - Removed unnecessary using directives.
- Loading branch information
1 parent
9f32372
commit e457df4
Showing
118 changed files
with
3,311 additions
and
1,856 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/Promitor.Core.Scraping/Configuration/Serialization/IDeserializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.Collections.Generic; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization | ||
{ | ||
/// <summary> | ||
/// An object that can deserialize a yaml node into an object. | ||
/// </summary> | ||
/// <typeparam name="TObject">The type of object that can be deserialized.</typeparam> | ||
public interface IDeserializer<TObject> | ||
{ | ||
/// <summary> | ||
/// Deserializes the specified node. | ||
/// </summary> | ||
/// <param name="node">The node to deserialize.</param> | ||
/// <returns>The deserialized object.</returns> | ||
TObject Deserialize(YamlMappingNode node); | ||
|
||
/// <summary> | ||
/// Deserializes an array of elements. | ||
/// </summary> | ||
/// <param name="node">The node to deserialize.</param> | ||
/// <returns>The deserialized objects.</returns> | ||
List<TObject> Deserialize(YamlSequenceNode node); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
src/Promitor.Core.Scraping/Configuration/Serialization/YamlMappingNodeExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization | ||
{ | ||
public static class YamlMappingNodeExtensions | ||
{ | ||
/// <summary> | ||
/// Gets the string value of the specified yaml property. | ||
/// </summary> | ||
/// <param name="node">The node containing the property.</param> | ||
/// <param name="propertyName">The name of the property.</param> | ||
/// <returns>The string value of the property.</returns> | ||
public static string GetString(this YamlMappingNode node, string propertyName) | ||
{ | ||
if (node.Children.TryGetValue(propertyName, out var propertyNode)) | ||
{ | ||
return propertyNode.ToString(); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the value of the specified yaml property converted to an enum. | ||
/// </summary> | ||
/// <typeparam name="TEnum">The type of enum to return.</typeparam> | ||
/// <param name="node">The node containing the property.</param> | ||
/// <param name="propertyName">The property name.</param> | ||
/// <returns>The enum value, or null if the property doesn't exist.</returns> | ||
public static TEnum? GetEnum<TEnum>(this YamlMappingNode node, string propertyName) | ||
where TEnum: struct | ||
{ | ||
if (node.Children.TryGetValue(propertyName, out var propertyNode)) | ||
{ | ||
return System.Enum.Parse<TEnum>(propertyNode.ToString()); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the contents of the specified property as a dictionary. | ||
/// </summary> | ||
/// <param name="node">The node containing the property.</param> | ||
/// <param name="propertyName">The name of the property.</param> | ||
/// <returns>The child items of the property as a dictionary.</returns> | ||
public static Dictionary<string, string> GetDictionary(this YamlMappingNode node, string propertyName) | ||
{ | ||
if (node.Children.TryGetValue(propertyName, out var propertyNode)) | ||
{ | ||
var result = new Dictionary<string, string>(); | ||
|
||
foreach (var (key, value) in ((YamlMappingNode) propertyNode).Children) | ||
{ | ||
result[key.ToString()] = value.ToString(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the value of the specified yaml property converted to a <see cref="TimeSpan"/>. | ||
/// </summary> | ||
/// <param name="node">The node containing the property.</param> | ||
/// <param name="propertyName">The name of the property.</param> | ||
/// <returns>The value converted to a timespan, or null if the property doesn't exist.</returns> | ||
public static TimeSpan? GetTimeSpan(this YamlMappingNode node, string propertyName) | ||
{ | ||
if (node.Children.TryGetValue(propertyName, out var propertyNode)) | ||
{ | ||
return TimeSpan.Parse(propertyNode.ToString()); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/// <summary> | ||
/// Deserializes a child object using the specified deserializer. | ||
/// </summary> | ||
/// <typeparam name="TObject">The type of object to deserialize.</typeparam> | ||
/// <param name="node">The yaml node.</param> | ||
/// <param name="propertyName">The name of the property to deserialize.</param> | ||
/// <param name="deserializer">The deserializer to use.</param> | ||
/// <returns>The deserialized property, or null if the property does not exist.</returns> | ||
public static TObject DeserializeChild<TObject>( | ||
this YamlMappingNode node, string propertyName, IDeserializer<TObject> deserializer) | ||
where TObject: class | ||
{ | ||
if (node.Children.TryGetValue(propertyName, out var propertyNode)) | ||
{ | ||
return deserializer.Deserialize((YamlMappingNode)propertyNode); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 15 additions & 19 deletions
34
src/Promitor.Core.Scraping/Configuration/Serialization/v1/Core/AzureMetadataDeserializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,28 @@ | ||
using GuardNet; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging; | ||
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Core | ||
{ | ||
internal class AzureMetadataDeserializer : Deserializer<AzureMetadataV1> | ||
public class AzureMetadataDeserializer : Deserializer<AzureMetadataV1> | ||
{ | ||
internal AzureMetadataDeserializer(ILogger logger) : base(logger) | ||
private const string TenantIdTag = "tenantId"; | ||
private const string SubscriptionIdTag = "subscriptionId"; | ||
private const string ResourceGroupNameTag = "resourceGroupName"; | ||
|
||
public AzureMetadataDeserializer(ILogger logger) : base(logger) | ||
{ | ||
} | ||
|
||
internal override AzureMetadataV1 Deserialize(YamlMappingNode node) | ||
public override AzureMetadataV1 Deserialize(YamlMappingNode node) | ||
{ | ||
Guard.NotNull(node, nameof(node)); | ||
|
||
var tenantId = node.Children[new YamlScalarNode("tenantId")]; | ||
var subscriptionId = node.Children[new YamlScalarNode("subscriptionId")]; | ||
var resourceGroupName = node.Children[new YamlScalarNode("resourceGroupName")]; | ||
|
||
var azureMetadata = new AzureMetadataV1 | ||
{ | ||
TenantId = tenantId?.ToString(), | ||
SubscriptionId = subscriptionId?.ToString(), | ||
ResourceGroupName = resourceGroupName?.ToString() | ||
}; | ||
var metadata = new AzureMetadataV1(); | ||
|
||
return azureMetadata; | ||
metadata.TenantId = node.GetString(TenantIdTag); | ||
metadata.SubscriptionId = node.GetString(SubscriptionIdTag); | ||
metadata.ResourceGroupName = node.GetString(ResourceGroupNameTag); | ||
|
||
return metadata; | ||
} | ||
} | ||
} | ||
} |
45 changes: 21 additions & 24 deletions
45
...Core.Scraping/Configuration/Serialization/v1/Core/AzureMetricConfigurationDeserializer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,38 @@ | ||
using GuardNet; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging; | ||
using Promitor.Core.Scraping.Configuration.Serialization.v1.Model; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Core | ||
{ | ||
internal class AzureMetricConfigurationDeserializer : Deserializer<AzureMetricConfigurationV1> | ||
public class AzureMetricConfigurationDeserializer : Deserializer<AzureMetricConfigurationV1> | ||
{ | ||
private readonly MetricAggregationDeserializer _metricAggregationDeserializer; | ||
private readonly YamlScalarNode _metricNode = new YamlScalarNode("metricName"); | ||
private readonly YamlScalarNode _aggregationNode = new YamlScalarNode("aggregation"); | ||
private const string MetricNameTag = "metricName"; | ||
private const string AggregationTag = "aggregation"; | ||
private readonly IDeserializer<MetricAggregationV1> _aggregationDeserializer; | ||
|
||
internal AzureMetricConfigurationDeserializer(ILogger logger) : base(logger) | ||
public AzureMetricConfigurationDeserializer(IDeserializer<MetricAggregationV1> aggregationDeserializer, ILogger logger) | ||
: base(logger) | ||
{ | ||
_metricAggregationDeserializer = new MetricAggregationDeserializer(logger); | ||
_aggregationDeserializer = aggregationDeserializer; | ||
} | ||
|
||
internal override AzureMetricConfigurationV1 Deserialize(YamlMappingNode node) | ||
public override AzureMetricConfigurationV1 Deserialize(YamlMappingNode node) | ||
{ | ||
Guard.NotNull(node, nameof(node)); | ||
|
||
var metricName = node.Children[_metricNode]; | ||
|
||
MetricAggregationV1 metricAggregation = null; | ||
if (node.Children.ContainsKey(_aggregationNode)) | ||
return new AzureMetricConfigurationV1 | ||
{ | ||
var aggregationNode = (YamlMappingNode) node.Children[_aggregationNode]; | ||
metricAggregation = _metricAggregationDeserializer.Deserialize(aggregationNode); | ||
} | ||
MetricName = node.GetString(MetricNameTag), | ||
Aggregation = DeserializeAggregation(node) | ||
}; | ||
} | ||
|
||
var azureMetricConfiguration = new AzureMetricConfigurationV1 | ||
private MetricAggregationV1 DeserializeAggregation(YamlMappingNode node) | ||
{ | ||
if (node.Children.TryGetValue(AggregationTag, out var aggregationNode)) | ||
{ | ||
MetricName = metricName?.ToString(), | ||
Aggregation = metricAggregation | ||
}; | ||
return _aggregationDeserializer.Deserialize((YamlMappingNode) aggregationNode); | ||
} | ||
|
||
return azureMetricConfiguration; | ||
return null; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.