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

Allow multiple resources to be specified per metric #683

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
43223e8
Add a v2 serializer
adamconnelly Aug 7, 2019
d0c3952
Implement v2 AzureMetadataDeserializer
adamconnelly Aug 7, 2019
07e23d3
Deserialize v2 metricDefaults
adamconnelly Aug 8, 2019
392326f
Make v2 deserializers inherit from Deserializer
adamconnelly Aug 8, 2019
fd30eeb
Implemented AggregationDeserializer
adamconnelly Aug 8, 2019
ac3abbf
Implement v2 Scraping deserializer
adamconnelly Aug 8, 2019
f733784
Implement v2 MetricDefinition deserialization
adamconnelly Aug 8, 2019
829fe45
Pull utility methods to Deserializer object
adamconnelly Aug 8, 2019
e58e97d
Refactor common deserialization assertions
adamconnelly Aug 8, 2019
913519e
Implement v2 container instance deserializer
adamconnelly Aug 8, 2019
59db9a7
Implement v2 container registry deserializer
adamconnelly Aug 8, 2019
99810c2
Implement v2 cosmos db deserializer
adamconnelly Aug 8, 2019
7b69e4e
Implement v2 generic resource deserializer
adamconnelly Aug 8, 2019
2a86476
Implement v2 network interface deserializer
adamconnelly Aug 8, 2019
f22f4ae
Implement v2 postgre deserializer
adamconnelly Aug 8, 2019
daa6343
Implement v2 redis cache deserializer
adamconnelly Aug 9, 2019
986ebe9
Implemented v2 service bus queue deserializer
adamconnelly Aug 9, 2019
6a0034e
Implement v2 virtual machine deserializer
adamconnelly Aug 9, 2019
97aa006
Implement v2 secret deserializer
adamconnelly Aug 9, 2019
9ba76d1
Implement v2 storage queue deserializer
adamconnelly Aug 9, 2019
8cd561b
Implement v2 azure metric config deserializer
adamconnelly Aug 9, 2019
2b58e34
Implement v2 metric aggregation deserializer
adamconnelly Aug 9, 2019
2551e58
Remove duplicate enum deserialization method
adamconnelly Aug 9, 2019
40eb45d
Add v2 serialization integration test
adamconnelly Aug 9, 2019
b96fbfb
Remove unnecessary type argument on null helpers
adamconnelly Aug 9, 2019
65f31ed
Rename v1 and v2 serializers
adamconnelly Aug 9, 2019
1190a61
Connect v2 format to application
adamconnelly Aug 10, 2019
985a15b
Remove v1 config objects
adamconnelly Aug 21, 2019
202cc9b
Rename v2 objects back to v1
adamconnelly Aug 21, 2019
9c29645
Update example config for new format
adamconnelly Aug 22, 2019
5f84e02
Updates as a result of PR feedback
adamconnelly Aug 24, 2019
b6d868a
Fixing build issues
adamconnelly Aug 27, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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.v1.Model;

namespace Promitor.Core.Scraping.Configuration.Providers
{
Expand All @@ -15,9 +16,9 @@ public class MetricsDeclarationProvider : IMetricsDeclarationProvider
private readonly ConfigurationSerializer _configurationSerializer;
private readonly IConfiguration _configuration;

public MetricsDeclarationProvider(IConfiguration configuration, ILogger logger, IMapper mapper)
public MetricsDeclarationProvider(IConfiguration configuration, ILogger logger, IMapper mapper, IDeserializer<MetricsDeclarationV1> v1Deserializer)
{
_configurationSerializer = new ConfigurationSerializer(logger, mapper);
_configurationSerializer = new ConfigurationSerializer(logger, mapper, v1Deserializer);
_configuration = configuration;
}

Expand All @@ -42,7 +43,7 @@ public virtual MetricsDeclaration Get(bool applyDefaults = false)
}
if (metric.AzureMetricConfiguration?.Aggregation.Interval == null)
tomkerkhove marked this conversation as resolved.
Show resolved Hide resolved
{
metric.AzureMetricConfiguration.Aggregation.Interval = config.MetricDefaults.Aggregation.Interval;
metric.AzureMetricConfiguration.Aggregation.Interval = config.MetricDefaults.Aggregation?.Interval;
}

// Apply the default scraping interval if none is specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ public class ConfigurationSerializer
{
private readonly ILogger _logger;
private readonly IMapper _mapper;
private readonly IDeserializer<MetricsDeclarationV1> _v1Deserializer;

public ConfigurationSerializer(ILogger logger, IMapper mapper)
public ConfigurationSerializer(ILogger logger, IMapper mapper, IDeserializer<MetricsDeclarationV1> v1Deserializer)
{
_logger = logger;
_mapper = mapper;
_v1Deserializer = v1Deserializer;
}

public MetricsDeclaration Deserialize(string rawMetricsDeclaration)
Expand Down Expand Up @@ -55,8 +57,7 @@ private MetricsDeclaration InterpretYamlStream(YamlStream metricsDeclarationYaml
switch (specVersion)
{
case SpecVersion.v1:
var v1Serializer = new v1.Core.ConfigurationSerializer(_logger);
var v1Config = v1Serializer.InterpretYamlStream(rootNode);
var v1Config = _v1Deserializer.Deserialize(rootNode);

return _mapper.Map<MetricsDeclaration>(v1Config);
default:
Expand All @@ -81,21 +82,7 @@ private SpecVersion DetermineDeclarationSpecVersion(YamlMappingNode mappingNode)
return (SpecVersion)specVersion;
}

public string Serialize(MetricsDeclaration metricsDeclaration)
{
Guard.NotNull(metricsDeclaration, nameof(metricsDeclaration));

var serializer = YamlSerialization.CreateSerializer();
var rawMetricsDeclaration = serializer.Serialize(metricsDeclaration);
return rawMetricsDeclaration;
}

/// <summary>
/// Allows a v1 version of the config to be serialized.
/// </summary>
/// <param name="metricsDeclaration">A v1 version of the config.</param>
/// <returns>The serialized yaml.</returns>
public string Serialize(MetricsDeclarationV1 metricsDeclaration)
public string Serialize(object metricsDeclaration)
{
Guard.NotNull(metricsDeclaration, nameof(metricsDeclaration));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@

namespace Promitor.Core.Scraping.Configuration.Serialization
{
internal abstract class Deserializer<TObject>
public abstract class Deserializer<TObject> : IDeserializer<TObject>
{
protected ILogger Logger { get; }

internal Deserializer(ILogger logger)
protected Deserializer(ILogger logger)
{
Guard.NotNull(logger, nameof(logger));

Logger = logger;
}

internal abstract TObject Deserialize(YamlMappingNode node);
public abstract TObject Deserialize(YamlMappingNode node);

internal List<TObject> Deserialize(YamlSequenceNode nodes)
public List<TObject> Deserialize(YamlSequenceNode nodes)
{
Guard.NotNull(nodes, nameof(nodes));

Expand Down
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);
}
}
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@

namespace Promitor.Core.Scraping.Configuration.Serialization.v1.Core
{
internal class AggregationDeserializer : Deserializer<AggregationV1>
public class AggregationDeserializer : Deserializer<AggregationV1>
{
internal AggregationDeserializer(ILogger logger) : base(logger)
private const string IntervalTag = "interval";

private readonly TimeSpan _defaultAggregationInterval = TimeSpan.FromMinutes(5);

public AggregationDeserializer(ILogger logger) : base(logger)
{
}

internal override AggregationV1 Deserialize(YamlMappingNode node)
public override AggregationV1 Deserialize(YamlMappingNode node)
{
var aggregation = new AggregationV1();
var interval = node.GetTimeSpan(IntervalTag);

var interval = TimeSpan.FromMinutes(5);
if (node.Children.ContainsKey("interval"))
{
var rawIntervalNode = node.Children[new YamlScalarNode("interval")];
interval = TimeSpan.Parse(rawIntervalNode.ToString());
}
else
var aggregation = new AggregationV1 {Interval = interval};

if (aggregation.Interval == null)
{
Logger.LogWarning("No default aggregation was configured, falling back to {AggregationInterval}", interval.ToString("g"));
aggregation.Interval = _defaultAggregationInterval;
Logger.LogWarning(
"No default aggregation was configured, falling back to {AggregationInterval}",
aggregation.Interval?.ToString("g"));
}

aggregation.Interval = interval;

return aggregation;
}
}
}
}
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;
}
}
}
}
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)
adamconnelly marked this conversation as resolved.
Show resolved Hide resolved
};
}

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;
}
}
}
}
Loading