Skip to content

Commit

Permalink
Merge pull request #7 from t1agob/develop
Browse files Browse the repository at this point in the history
feature: metrics
  • Loading branch information
sliedig authored Oct 13, 2020
2 parents 5d0a155 + 1ad3fe5 commit f3aa1d8
Show file tree
Hide file tree
Showing 12 changed files with 436 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,4 @@ MigrationBackup/
.ionide/

# End of https://www.toptal.com/developers/gitignore/api/dotnetcore,visualstudio,visualstudiocode,rider
.DS_Store
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\Amazon.LambdaPowertools\Amazon.LambdaPowertools.csproj" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PackageId>Amazon.LambdaPowertools.Metrics</PackageId>
<Version>0.0.15</Version>
<Authors>AWSLABS</Authors>
<Company>Amazon Web Services</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

</Project>
8 changes: 0 additions & 8 deletions libraries/src/Amazon.LambdaPowertools.Metrics/Class1.cs

This file was deleted.

24 changes: 24 additions & 0 deletions libraries/src/Amazon.LambdaPowertools.Metrics/Metrics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using Amazon.LambdaPowertools.Metrics.Model;

namespace Amazon.LambdaPowertools.Metrics
{
public class Metrics : MetricsManager
{
public Metrics(
string metricsNamespace = null,
string serviceName = null,
Dictionary<string, string> dimensions = null,
Dictionary<string, List<Metric>> metrics = null,
Dictionary<string, dynamic> metadata = null)
: base(metricsNamespace,
serviceName,
dimensions,
metrics,
metadata)
{

}
}
}
224 changes: 224 additions & 0 deletions libraries/src/Amazon.LambdaPowertools.Metrics/MetricsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Amazon.LambdaPowertools.Metrics.Model;

namespace Amazon.LambdaPowertools.Metrics
{

public class MetricsManager : IDisposable
{
[MaxLength(9)]
private Dictionary<string, string> _dimensions;
public Dictionary<string, string> Dimensions
{
get { return _dimensions; }
}

[MaxLength(100)]
private Dictionary<string, List<Metric>> _metrics;
public Dictionary<string, List<Metric>> Metrics
{
get { return _metrics; }
}

private Dictionary<string, dynamic> _metadata;

public Dictionary<string, dynamic> Metadata
{
get { return _metadata; }
}

private bool disposedValue;
private static int _metricCount = 0;

public MetricsManager(
string metricsNamespace = null,
string serviceName = null,
Dictionary<string, string> dimensions = null,
Dictionary<string, List<Metric>> metrics = null,
Dictionary<string, dynamic> metadata = null)
{
PowertoolsSettings.SetNamespace(metricsNamespace);
PowertoolsSettings.SetService(serviceName);

_dimensions = dimensions != null ? dimensions : new Dictionary<string, string>();
_metrics = metrics != null ? metrics : new Dictionary<string, List<Metric>>();
_metadata = metadata != null ? metadata : new Dictionary<string, dynamic>();

if(!string.IsNullOrEmpty(PowertoolsSettings.Service)){
AddDimension("service", PowertoolsSettings.Service);
}
}

public void AddDimension(string key, string value)
{
if (_dimensions.ContainsKey(key))
{
Console.WriteLine($"Dimension '{key}' already exists. Skipping...");
return;
}

if(_dimensions.Count == 9)
{
Console.WriteLine($"Maximum number of dimensions (9) reached. Cannot add '{key}' to dimensions.");
return;
}

_dimensions.Add(key, value);
}

public virtual void AddMetric(Metric metric)
{
if (_metrics.ContainsKey(metric.Name))
{
_metrics[metric.Name].Add(metric);
_metricCount++;
}
else {
_metrics.Add(metric.Name, new List<Metric>{metric});
_metricCount++;
}

if (_metricCount == 100)
{
Flush();
}
}

public void AddMetadata(string key, dynamic value)
{

if (_metadata.ContainsKey(key))
{
Console.WriteLine($"Metadata '{key}' already exists. Skipping...");
return;
}

_metadata.Add(key, value);
}

//TODO: Turn this into a private method once decision has been made on the implementation
public void Flush()
{
var metricObj = new MetricsWrapper
{
Root = new MetricsDefinition
{
Timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
CloudWatchMetrics = new List<CloudWatchMetrics>{
new CloudWatchMetrics{
Namespace = PowertoolsSettings.Namespace,
Dimensions = new List<List<string>>{
ExtractDimensions(Dimensions)
},
Metrics = ExtractMetricDefinitionSet(Metrics)
}
}
}
};

var json = JsonSerializer.Serialize(metricObj, typeof(MetricsWrapper));

string result = AddToJson(json, _dimensions, _metadata, _metrics);

Console.WriteLine(result);

_metrics.Clear();
}

private List<string> ExtractDimensions(Dictionary<string, string> dimensions)
{
List<string> result = new List<string>();

result.AddRange(dimensions.Keys);

return result;
}

private List<MetricsDefinitionSet> ExtractMetricDefinitionSet(Dictionary<string, List<Metric>> metrics)
{
List<MetricsDefinitionSet> metricDefinitionSet = new List<MetricsDefinitionSet>();

foreach (var item in metrics)
{
metricDefinitionSet.Add(new MetricsDefinitionSet
{
Name = item.Value[0].Name,
Unit = item.Value[0].Unit
});
}

return metricDefinitionSet;
}

private string AddToJson(string json, Dictionary<string, string> dimensions, Dictionary<string, dynamic> metadata, Dictionary<string, List<Metric>> metrics)
{
string result = "";
foreach (var item in dimensions)
{
result += $",\"{item.Key}\":\"{item.Value}\"";
}

foreach (var item in metadata)
{
result += $",\"{item.Key}\":\"{item.Value}\"";
}

foreach (var item in metrics.Values)
{
if(item.Count > 1){
string resultArray = $",\"{item[0].Name}\": [";

for (int i = 0; i < item.Count; i++)
{
if(i == item.Count - 1){
resultArray += $"{item[i].Value}]";
}
else {
resultArray += $"{item[i].Value},";
}
}

result += resultArray;
}
else {
result += $",\"{item[0].Name}\": {item[0].Value}";
}

}

return $"{json.Remove(json.Length - 1)}{result}}}";
}

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
Flush();
}

_dimensions = null;
_metrics = null;
_metadata = null;
disposedValue = true;
}
}

~MetricsManager()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
29 changes: 29 additions & 0 deletions libraries/src/Amazon.LambdaPowertools.Metrics/Model/Metric.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Amazon.LambdaPowertools.Metrics.Model;

namespace Amazon.LambdaPowertools.Metrics
{
public class Metric
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}

private string _unit;
public string Unit
{
get { return _unit; }
set { _unit = value; }
}

private double _value;
public double Value
{
get { return _value; }
set { _value = value; }
}

}
}
32 changes: 32 additions & 0 deletions libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricUnit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace Amazon.LambdaPowertools.Metrics.Model
{
public class MetricUnit
{
public static readonly string Seconds = "Seconds";
public static readonly string Microseconds = "Microseconds";
public static readonly string Milliseconds = "Milliseconds";
public static readonly string Bytes = "Bytes";
public static readonly string Kilobytes = "Kilobytes";
public static readonly string Megabytes = "Megabytes";
public static readonly string Gigabytes = "Gigabytes";
public static readonly string Terabytes = "Terabytes";
public static readonly string Bits = "Bits";
public static readonly string Kilobits = "Kilobits";
public static readonly string Megabits = "Megabits";
public static readonly string Gigabits = "Gigabits";
public static readonly string Terabits = "Terabits";
public static readonly string Percent = "Percent";
public static readonly string Count = "Count";
public static readonly string BytesPerSecond = "Bytes/Second";
public static readonly string KilobytesPerSecond = "Kilobytes/Second";
public static readonly string MegabytesPerSecond = "Megabytes/Second";
public static readonly string GigabytesPerSecond = "Gigabytes/Second";
public static readonly string TerabytesPerSecond = "Terabytes/Second";
public static readonly string BitsPerSecond = "Bits/Second";
public static readonly string KilobitsPerSecond = "Kilobits/Second";
public static readonly string MegabitsPerSecond = "Megabits/Second";
public static readonly string GigabitsPerSecond = "Gigabits/Second";
public static readonly string TerabitsPerSecond = "Terabits/Second";
public static readonly string CountPerSecond = "Count/Second";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Amazon.LambdaPowertools.Metrics.Model;

namespace Amazon.LambdaPowertools.Metrics
{

public class MetricsWrapper
{
[JsonPropertyName("_aws")]
public MetricsDefinition Root { get; set; }
}

public class MetricsDefinition
{
public double Timestamp { get; set; }
public List<CloudWatchMetrics> CloudWatchMetrics { get; set; }
}

public class CloudWatchMetrics
{
public string Namespace { get; set; }
public List<List<string>> Dimensions { get; set; }
public List<MetricsDefinitionSet> Metrics { get; set; }
}

public class MetricsDefinitionSet
{
public string Name { get; set; }
public string Unit { get; set; }
}
}
Loading

0 comments on commit f3aa1d8

Please sign in to comment.