diff --git a/.gitignore b/.gitignore
index 8d2d5f2ab..dbe6b8a52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -455,3 +455,4 @@ MigrationBackup/
.ionide/
# End of https://www.toptal.com/developers/gitignore/api/dotnetcore,visualstudio,visualstudiocode,rider
+.DS_Store
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Amazon.LambdaPowertools.Metrics.csproj b/libraries/src/Amazon.LambdaPowertools.Metrics/Amazon.LambdaPowertools.Metrics.csproj
index 8642d92f3..13d8744b4 100644
--- a/libraries/src/Amazon.LambdaPowertools.Metrics/Amazon.LambdaPowertools.Metrics.csproj
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/Amazon.LambdaPowertools.Metrics.csproj
@@ -1,7 +1,16 @@
+
+
+
+
netcoreapp3.1
+ Amazon.LambdaPowertools.Metrics
+ 0.0.15
+ AWSLABS
+ Amazon Web Services
+ true
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Class1.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/Class1.cs
deleted file mode 100644
index 8ac84b377..000000000
--- a/libraries/src/Amazon.LambdaPowertools.Metrics/Class1.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System;
-
-namespace Amazon.LambdaPowertools.Metrics
-{
- public class Class1
- {
- }
-}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Metrics.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/Metrics.cs
new file mode 100644
index 000000000..1a1326df4
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/Metrics.cs
@@ -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 dimensions = null,
+ Dictionary> metrics = null,
+ Dictionary metadata = null)
+ : base(metricsNamespace,
+ serviceName,
+ dimensions,
+ metrics,
+ metadata)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/MetricsManager.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/MetricsManager.cs
new file mode 100644
index 000000000..89d7a05e3
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/MetricsManager.cs
@@ -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 _dimensions;
+ public Dictionary Dimensions
+ {
+ get { return _dimensions; }
+ }
+
+ [MaxLength(100)]
+ private Dictionary> _metrics;
+ public Dictionary> Metrics
+ {
+ get { return _metrics; }
+ }
+
+ private Dictionary _metadata;
+
+ public Dictionary Metadata
+ {
+ get { return _metadata; }
+ }
+
+ private bool disposedValue;
+ private static int _metricCount = 0;
+
+ public MetricsManager(
+ string metricsNamespace = null,
+ string serviceName = null,
+ Dictionary dimensions = null,
+ Dictionary> metrics = null,
+ Dictionary metadata = null)
+ {
+ PowertoolsSettings.SetNamespace(metricsNamespace);
+ PowertoolsSettings.SetService(serviceName);
+
+ _dimensions = dimensions != null ? dimensions : new Dictionary();
+ _metrics = metrics != null ? metrics : new Dictionary>();
+ _metadata = metadata != null ? metadata : new Dictionary();
+
+ 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});
+ _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{
+ new CloudWatchMetrics{
+ Namespace = PowertoolsSettings.Namespace,
+ Dimensions = new List>{
+ 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 ExtractDimensions(Dictionary dimensions)
+ {
+ List result = new List();
+
+ result.AddRange(dimensions.Keys);
+
+ return result;
+ }
+
+ private List ExtractMetricDefinitionSet(Dictionary> metrics)
+ {
+ List metricDefinitionSet = new List();
+
+ 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 dimensions, Dictionary metadata, Dictionary> 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);
+ }
+ }
+}
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Model/Metric.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/Metric.cs
new file mode 100644
index 000000000..eeb8b2a3c
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/Metric.cs
@@ -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; }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricUnit.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricUnit.cs
new file mode 100644
index 000000000..68125f118
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricUnit.cs
@@ -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";
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricsWrapper.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricsWrapper.cs
new file mode 100644
index 000000000..fe73348cb
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/Model/MetricsWrapper.cs
@@ -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 { get; set; }
+ }
+
+ public class CloudWatchMetrics
+ {
+ public string Namespace { get; set; }
+ public List> Dimensions { get; set; }
+ public List Metrics { get; set; }
+ }
+
+ public class MetricsDefinitionSet
+ {
+ public string Name { get; set; }
+ public string Unit { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools.Metrics/SingleMetric.cs b/libraries/src/Amazon.LambdaPowertools.Metrics/SingleMetric.cs
new file mode 100644
index 000000000..1593c7b76
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools.Metrics/SingleMetric.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using Amazon.LambdaPowertools.Metrics.Model;
+
+namespace Amazon.LambdaPowertools.Metrics
+{
+ public class SingleMetric : MetricsManager
+ {
+ public SingleMetric(
+ string metricsNamespace = null,
+ string serviceName = null,
+ Metric metric = null)
+ : base(metricsNamespace: metricsNamespace,
+ serviceName: serviceName)
+ {
+ AddMetric(metric);
+ }
+
+ public override void AddMetric(Metric metric)
+ {
+ Metrics.Clear();
+ Metrics.Add(metric.Name, new List{metric});
+ }
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools/Amazon.LambdaPowertools.csproj b/libraries/src/Amazon.LambdaPowertools/Amazon.LambdaPowertools.csproj
index 8642d92f3..92ccb265e 100644
--- a/libraries/src/Amazon.LambdaPowertools/Amazon.LambdaPowertools.csproj
+++ b/libraries/src/Amazon.LambdaPowertools/Amazon.LambdaPowertools.csproj
@@ -2,6 +2,11 @@
netcoreapp3.1
+ Amazon.LambdaPowertools
+ 1.0.0
+ AWSLABS
+ Amazon Web Services
+ true
diff --git a/libraries/src/Amazon.LambdaPowertools/Class1.cs b/libraries/src/Amazon.LambdaPowertools/Class1.cs
deleted file mode 100644
index 5c9a9d0cc..000000000
--- a/libraries/src/Amazon.LambdaPowertools/Class1.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System;
-
-namespace Amazon.LambdaPowertools
-{
- public class Class1
- {
- }
-}
\ No newline at end of file
diff --git a/libraries/src/Amazon.LambdaPowertools/PowertoolsSettings.cs b/libraries/src/Amazon.LambdaPowertools/PowertoolsSettings.cs
new file mode 100644
index 000000000..199018c21
--- /dev/null
+++ b/libraries/src/Amazon.LambdaPowertools/PowertoolsSettings.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Amazon.LambdaPowertools
+{
+ public static class PowertoolsSettings
+ {
+ private static string _namespace;
+ public static string Namespace
+ {
+ get
+ {
+ if (!String.IsNullOrEmpty(_namespace))
+ {
+ return _namespace;
+ }
+ else
+ {
+ return Environment.GetEnvironmentVariable("POWERTOOLS_METRICS_NAMESPACE");
+ }
+ }
+ }
+
+ private static string _service;
+ public static string Service
+ {
+ get
+ {
+ if (!String.IsNullOrEmpty(_service))
+ {
+ return _service;
+ }
+ else
+ {
+ return Environment.GetEnvironmentVariable("POWERTOOLS_SERVICE_NAME");
+ }
+ }
+ }
+
+ public static void SetNamespace(string powertoolsNamespace)
+ {
+ if (powertoolsNamespace != null)
+ {
+ _namespace = powertoolsNamespace;
+ }
+ }
+
+ public static void SetService(string powertoolsService)
+ {
+ if (powertoolsService != null)
+ {
+ _service = powertoolsService;
+ }
+ }
+ }
+}
\ No newline at end of file