Created
March 21, 2024 02:05
-
-
Save ssippe/1e3a3455eafdd6f57ce7001fcb4858ee to your computer and use it in GitHub Desktop.
Create a dashboard per asg that beats the 3hr aws CloudWatch Metrics Insights limit
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
using Amazon.AutoScaling.Model; | |
using Amazon.AutoScaling; | |
using Amazon.CloudWatch.Model; | |
using Amazon; | |
using Amazon.CloudWatch; | |
const string Namespace = "CWAgent"; | |
const string MetricName = "TCPv4 Connections Established"; | |
var response = await GetMetrics(); | |
var asgs = GetAsgForMetric(response); | |
var asgEnvTable = await GetAsgEbEnvs(asgs); | |
var asgInstanceDic = GetAsgInstanceDic(response); | |
var widgets = asgEnvTable.OrderByDescending(f=>f.EbEnv).Select((row, idx) => GetDashboardWidgetObj(asgInstanceDic[row.Asg], row.Asg, row.EbEnv, idx)).ToList(); | |
var dashboardObj = GetDashboardObj(widgets); | |
var dashboardJsonString = System.Text.Json.JsonSerializer.Serialize(dashboardObj); | |
await CreateDashboard($"TCP_{DateTime.Now.ToString("yyyy-MM-dd")}", dashboardJsonString); | |
static async Task<IReadOnlyList<(string Asg, string EbEnv)>> GetAsgEbEnvs(IEnumerable<string> asgs) | |
{ | |
var asgEbEnvs = await GetAsgEbEnvsByCurrentAsg(); | |
var table = asgs.Select(asg => (asg, asgEbEnvs.SingleOrDefault(ae => ae.Asg == asg).EbEnv)).ToList(); | |
return table; | |
} | |
static async Task<ListMetricsResponse> ListMetricsUntilDone(ListMetricsRequest req, AmazonCloudWatchClient client) | |
{ | |
ListMetricsResponse? mainRespone = null; | |
while (true) | |
{ | |
var response = await client.ListMetricsAsync(req); | |
if (mainRespone == null) | |
{ | |
mainRespone = response; | |
} | |
else | |
{ | |
mainRespone.Metrics.AddRange(response.Metrics); | |
} | |
if (string.IsNullOrEmpty(response.NextToken)) | |
{ | |
return mainRespone; | |
} | |
req.NextToken = response.NextToken; | |
} | |
} | |
static async Task<ListMetricsResponse> GetMetrics() | |
{ | |
using var client = new Amazon.CloudWatch.AmazonCloudWatchClient(RegionEndpoint.APSoutheast2); | |
var request = new Amazon.CloudWatch.Model.ListMetricsRequest | |
{ | |
Namespace = Namespace, | |
MetricName = MetricName, | |
}; | |
var response = await ListMetricsUntilDone(request, client); | |
return response; | |
} | |
static IReadOnlyList<string> GetAsgForMetric(ListMetricsResponse response) | |
{ | |
var asgs = response.Metrics.Select(m => m.Dimensions.Single(d => d.Name == "AutoScalingGroupName").Value).Distinct().ToList(); | |
return asgs; | |
} | |
static async Task<IReadOnlyList<(string Asg, string EbEnv)>> GetAsgEbEnvsByCurrentAsg() | |
{ | |
using var client = new AmazonAutoScalingClient(RegionEndpoint.APSoutheast2); | |
var response = await client.DescribeAutoScalingGroupsAsync(new DescribeAutoScalingGroupsRequest()); | |
var asgEbEnvs = response.AutoScalingGroups.Select(asg => (asg.AutoScalingGroupName, asg.Tags.SingleOrDefault(t => t.Key == "elasticbeanstalk:environment-name")?.Value)).ToList(); | |
return asgEbEnvs; | |
} | |
static IReadOnlyDictionary<string, IEnumerable<string>> GetAsgInstanceDic(ListMetricsResponse response) => | |
response.Metrics.GroupBy(m => m.Dimensions.Single(d => d.Name == "AutoScalingGroupName").Value).ToDictionary(g => g.Key, g => g.Select(m => m.Dimensions.Single(d => d.Name == "InstanceId").Value)); | |
static object GetDashboardObj(IEnumerable<object> widgets) => new { widgets }; | |
static object GetDashboardWidgetObj(IEnumerable<string> instanceIds, string asg, string name, int idx) | |
{ | |
const int height = 10; | |
var obj = new | |
{ | |
metrics = instanceIds.Select(instanceId => new[] { "CWAgent", "TCPv4 Connections Established", "InstanceId", instanceId, "AutoScalingGroupName", asg, "objectname", "TCPv4" }), | |
title = $"Max(TCPv4 Conn Est) {asg} {name}", | |
stat = "Maximum", | |
view = "timeSeries", | |
stacked = false, | |
region = "ap-southeast-2", | |
}; | |
return new | |
{ | |
properties = obj, | |
type = "metric", | |
x = 0, | |
y = height * idx, | |
width = 24, | |
height = height | |
}; | |
} | |
static async Task CreateDashboard(string dashboardName, string dashboardBody) | |
{ | |
using var client = new AmazonCloudWatchClient(RegionEndpoint.APSoutheast2); | |
var request = new PutDashboardRequest | |
{ | |
DashboardName = dashboardName, | |
DashboardBody = dashboardBody | |
}; | |
var response = await client.PutDashboardAsync(request); | |
Console.WriteLine(response); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment