CloudWatch 使用示例 Amazon SDK for .NET - Amazon SDK for .NET
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

CloudWatch 使用示例 Amazon SDK for .NET

以下代码示例向您展示了如何使用with来执行操作和实现常见场景 CloudWatch。Amazon SDK for .NET

操作是大型程序的代码摘录,必须在上下文中运行。您可以通过操作了解如何调用单个服务函数,还可以通过函数相关场景和跨服务示例的上下文查看操作。

场景是指显示如何通过在同一服务中调用多个函数来完成特定任务的代码示例。

每个示例都包含一个指向的链接 GitHub,您可以在其中找到有关如何在上下文中设置和运行代码的说明。

开始使用

以下代码示例演示了如何开始使用 CloudWatch。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

using Amazon.CloudWatch; using Amazon.CloudWatch.Model; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace CloudWatchActions; public static class HelloCloudWatch { static async Task Main(string[] args) { // Use the AWS .NET Core Setup package to set up dependency injection for the Amazon CloudWatch service. // Use your AWS profile name, or leave it blank to use the default profile. using var host = Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => services.AddAWSService<IAmazonCloudWatch>() ).Build(); // Now the client is available for injection. var cloudWatchClient = host.Services.GetRequiredService<IAmazonCloudWatch>(); // You can use await and any of the async methods to get a response. var metricNamespace = "AWS/Billing"; var response = await cloudWatchClient.ListMetricsAsync(new ListMetricsRequest { Namespace = metricNamespace }); Console.WriteLine($"Hello Amazon CloudWatch! Following are some metrics available in the {metricNamespace} namespace:"); Console.WriteLine(); foreach (var metric in response.Metrics.Take(5)) { Console.WriteLine($"\tMetric: {metric.MetricName}"); Console.WriteLine($"\tNamespace: {metric.Namespace}"); Console.WriteLine($"\tDimensions: {string.Join(", ", metric.Dimensions.Select(m => $"{m.Name}:{m.Value}"))}"); Console.WriteLine(); } } }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考ListMetrics中的。

操作

以下代码示例显示了如何创建 Amazon CloudWatch 控制面板。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Set up a dashboard using a call to the wrapper class. /// </summary> /// <param name="customMetricNamespace">The metric namespace.</param> /// <param name="customMetricName">The metric name.</param> /// <param name="dashboardName">The name of the dashboard.</param> /// <returns>A list of validation messages.</returns> private static async Task<List<DashboardValidationMessage>> SetupDashboard( string customMetricNamespace, string customMetricName, string dashboardName) { // Get the dashboard model from configuration. var newDashboard = new DashboardModel(); _configuration.GetSection("dashboardExampleBody").Bind(newDashboard); // Add a new metric to the dashboard. newDashboard.Widgets.Add(new Widget { Height = 8, Width = 8, Y = 8, X = 0, Type = "metric", Properties = new Properties { Metrics = new List<List<object>> { new() { customMetricNamespace, customMetricName } }, View = "timeSeries", Region = "us-east-1", Stat = "Sum", Period = 86400, YAxis = new YAxis { Left = new Left { Min = 0, Max = 100 } }, Title = "Custom Metric Widget", LiveData = true, Sparkline = true, Trend = true, Stacked = false, SetPeriodToTimeRange = false } }); var newDashboardString = JsonSerializer.Serialize(newDashboard, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); var validationMessages = await _cloudWatchWrapper.PutDashboard(dashboardName, newDashboardString); return validationMessages; } /// <summary> /// Wrapper to create or add to a dashboard with metrics. /// </summary> /// <param name="dashboardName">The name for the dashboard.</param> /// <param name="dashboardBody">The metric data in JSON for the dashboard.</param> /// <returns>A list of validation messages for the dashboard.</returns> public async Task<List<DashboardValidationMessage>> PutDashboard(string dashboardName, string dashboardBody) { // Updating a dashboard replaces all contents. // Best practice is to include a text widget indicating this dashboard was created programmatically. var dashboardResponse = await _amazonCloudWatch.PutDashboardAsync( new PutDashboardRequest() { DashboardName = dashboardName, DashboardBody = dashboardBody }); return dashboardResponse.DashboardValidationMessages; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考PutDashboard中的。

以下代码示例演示如何创建或更新 Amazon CloudWatch 警报,并将其与指定指标、指标数学表达式、异常检测模型或指标见解查询相关联。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Add a metric alarm to send an email when the metric passes a threshold. /// </summary> /// <param name="alarmDescription">A description of the alarm.</param> /// <param name="alarmName">The name for the alarm.</param> /// <param name="comparison">The type of comparison to use.</param> /// <param name="metricName">The name of the metric for the alarm.</param> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="threshold">The threshold value for the alarm.</param> /// <param name="alarmActions">Optional actions to execute when in an alarm state.</param> /// <returns>True if successful.</returns> public async Task<bool> PutMetricEmailAlarm(string alarmDescription, string alarmName, ComparisonOperator comparison, string metricName, string metricNamespace, double threshold, List<string> alarmActions = null!) { try { var putEmailAlarmResponse = await _amazonCloudWatch.PutMetricAlarmAsync( new PutMetricAlarmRequest() { AlarmActions = alarmActions, AlarmDescription = alarmDescription, AlarmName = alarmName, ComparisonOperator = comparison, Threshold = threshold, Namespace = metricNamespace, MetricName = metricName, EvaluationPeriods = 1, Period = 10, Statistic = new Statistic("Maximum"), DatapointsToAlarm = 1, TreatMissingData = "ignore" }); return putEmailAlarmResponse.HttpStatusCode == HttpStatusCode.OK; } catch (LimitExceededException lex) { _logger.LogError(lex, $"Unable to add alarm {alarmName}. Alarm quota has already been reached."); } return false; } /// <summary> /// Add specific email actions to a list of action strings for a CloudWatch alarm. /// </summary> /// <param name="accountId">The AccountId for the alarm.</param> /// <param name="region">The region for the alarm.</param> /// <param name="emailTopicName">An Amazon Simple Notification Service (SNS) topic for the alarm email.</param> /// <param name="alarmActions">Optional list of existing alarm actions to append to.</param> /// <returns>A list of string actions for an alarm.</returns> public List<string> AddEmailAlarmAction(string accountId, string region, string emailTopicName, List<string>? alarmActions = null) { alarmActions ??= new List<string>(); var snsAlarmAction = $"arn:aws:sns:{region}:{accountId}:{emailTopicName}"; alarmActions.Add(snsAlarmAction); return alarmActions; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考PutMetricAlarm中的。

以下代码示例显示了如何创建 Amazon CloudWatch 异常检测器。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Add an anomaly detector for a single metric. /// </summary> /// <param name="anomalyDetector">A single metric anomaly detector.</param> /// <returns>True if successful.</returns> public async Task<bool> PutAnomalyDetector(SingleMetricAnomalyDetector anomalyDetector) { var putAlarmDetectorResult = await _amazonCloudWatch.PutAnomalyDetectorAsync( new PutAnomalyDetectorRequest() { SingleMetricAnomalyDetector = anomalyDetector }); return putAlarmDetectorResult.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考PutAnomalyDetector中的。

以下代码示例显示了如何删除 Amazon CloudWatch 警报。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Delete a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAlarms(List<string> alarmNames) { var deleteAlarmsResult = await _amazonCloudWatch.DeleteAlarmsAsync( new DeleteAlarmsRequest() { AlarmNames = alarmNames }); return deleteAlarmsResult.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考DeleteAlarms中的。

以下代码示例显示如何删除 Amazon CloudWatch 异常检测器。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Delete a single metric anomaly detector. /// </summary> /// <param name="anomalyDetector">The anomaly detector to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAnomalyDetector(SingleMetricAnomalyDetector anomalyDetector) { var deleteAnomalyDetectorResponse = await _amazonCloudWatch.DeleteAnomalyDetectorAsync( new DeleteAnomalyDetectorRequest() { SingleMetricAnomalyDetector = anomalyDetector }); return deleteAnomalyDetectorResponse.HttpStatusCode == HttpStatusCode.OK; }

以下代码示例显示了如何删除 Amazon CloudWatch 控制面板。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Delete a list of CloudWatch dashboards. /// </summary> /// <param name="dashboardNames">List of dashboard names to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteDashboards(List<string> dashboardNames) { var deleteDashboardsResponse = await _amazonCloudWatch.DeleteDashboardsAsync( new DeleteDashboardsRequest() { DashboardNames = dashboardNames }); return deleteDashboardsResponse.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考DeleteDashboards中的。

以下代码示例显示了如何描述 Amazon CloudWatch 警报历史记录。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Describe the history of an alarm for a number of days in the past. /// </summary> /// <param name="alarmName">The name of the alarm.</param> /// <param name="historyDays">The number of days in the past.</param> /// <returns>The list of alarm history data.</returns> public async Task<List<AlarmHistoryItem>> DescribeAlarmHistory(string alarmName, int historyDays) { List<AlarmHistoryItem> alarmHistory = new List<AlarmHistoryItem>(); var paginatedAlarmHistory = _amazonCloudWatch.Paginators.DescribeAlarmHistory( new DescribeAlarmHistoryRequest() { AlarmName = alarmName, EndDateUtc = DateTime.UtcNow, HistoryItemType = HistoryItemType.StateUpdate, StartDateUtc = DateTime.UtcNow.AddDays(-historyDays) }); await foreach (var data in paginatedAlarmHistory.AlarmHistoryItems) { alarmHistory.Add(data); } return alarmHistory; }

以下代码示例显示了如何描述 Amazon CloudWatch 警报。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Describe the current alarms, optionally filtered by state. /// </summary> /// <param name="stateValue">Optional filter for alarm state.</param> /// <returns>The list of alarm data.</returns> public async Task<List<MetricAlarm>> DescribeAlarms(StateValue? stateValue = null) { List<MetricAlarm> alarms = new List<MetricAlarm>(); var paginatedDescribeAlarms = _amazonCloudWatch.Paginators.DescribeAlarms( new DescribeAlarmsRequest() { StateValue = stateValue }); await foreach (var data in paginatedDescribeAlarms.MetricAlarms) { alarms.Add(data); } return alarms; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考DescribeAlarms中的。

以下代码示例显示了如何描述某个指标的 Amazon CloudWatch 警报。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Describe the current alarms for a specific metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The name of the metric.</param> /// <returns>The list of alarm data.</returns> public async Task<List<MetricAlarm>> DescribeAlarmsForMetric(string metricNamespace, string metricName) { var alarmsResult = await _amazonCloudWatch.DescribeAlarmsForMetricAsync( new DescribeAlarmsForMetricRequest() { Namespace = metricNamespace, MetricName = metricName }); return alarmsResult.MetricAlarms; }

以下代码示例显示了如何描述 Amazon CloudWatch 异常检测器。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Describe anomaly detectors for a metric and namespace. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The metric of the anomaly detectors.</param> /// <returns>The list of detectors.</returns> public async Task<List<AnomalyDetector>> DescribeAnomalyDetectors(string metricNamespace, string metricName) { List<AnomalyDetector> detectors = new List<AnomalyDetector>(); var paginatedDescribeAnomalyDetectors = _amazonCloudWatch.Paginators.DescribeAnomalyDetectors( new DescribeAnomalyDetectorsRequest() { MetricName = metricName, Namespace = metricNamespace }); await foreach (var data in paginatedDescribeAnomalyDetectors.AnomalyDetectors) { detectors.Add(data); } return detectors; }

以下代码示例显示了如何禁用 Amazon CloudWatch 警报操作。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Disable the actions for a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms.</param> /// <returns>True if successful.</returns> public async Task<bool> DisableAlarmActions(List<string> alarmNames) { var disableAlarmActionsResult = await _amazonCloudWatch.DisableAlarmActionsAsync( new DisableAlarmActionsRequest() { AlarmNames = alarmNames }); return disableAlarmActionsResult.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考DisableAlarmActions中的。

以下代码示例显示了如何启用 Amazon CloudWatch 警报操作。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Enable the actions for a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms.</param> /// <returns>True if successful.</returns> public async Task<bool> EnableAlarmActions(List<string> alarmNames) { var enableAlarmActionsResult = await _amazonCloudWatch.EnableAlarmActionsAsync( new EnableAlarmActionsRequest() { AlarmNames = alarmNames }); return enableAlarmActionsResult.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考EnableAlarmActions中的。

以下代码示例显示了如何获取 Amazon CloudWatch 指标数据图片。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Get an image for a metric graphed over time. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metric">The name of the metric.</param> /// <param name="stat">The name of the stat to chart.</param> /// <param name="period">The period to use for the chart.</param> /// <returns>A memory stream for the chart image.</returns> public async Task<MemoryStream> GetTimeSeriesMetricImage(string metricNamespace, string metric, string stat, int period) { var metricImageWidget = new { title = "Example Metric Graph", view = "timeSeries", stacked = false, period = period, width = 1400, height = 600, metrics = new List<List<object>> { new() { metricNamespace, metric, new { stat } } } }; var metricImageWidgetString = JsonSerializer.Serialize(metricImageWidget); var imageResponse = await _amazonCloudWatch.GetMetricWidgetImageAsync( new GetMetricWidgetImageRequest() { MetricWidget = metricImageWidgetString }); return imageResponse.MetricWidgetImage; } /// <summary> /// Save a metric image to a file. /// </summary> /// <param name="memoryStream">The MemoryStream for the metric image.</param> /// <param name="metricName">The name of the metric.</param> /// <returns>The path to the file.</returns> public string SaveMetricImage(MemoryStream memoryStream, string metricName) { var metricFileName = $"{metricName}_{DateTime.Now.Ticks}.png"; using var sr = new StreamReader(memoryStream); // Writes the memory stream to a file. File.WriteAllBytes(metricFileName, memoryStream.ToArray()); var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, metricFileName); return filePath; }

以下代码示例显示了如何获取 Amazon CloudWatch 控制面板的详细信息。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Get information on a dashboard. /// </summary> /// <param name="dashboardName">The name of the dashboard.</param> /// <returns>A JSON object with dashboard information.</returns> public async Task<string> GetDashboard(string dashboardName) { var dashboardResponse = await _amazonCloudWatch.GetDashboardAsync( new GetDashboardRequest() { DashboardName = dashboardName }); return dashboardResponse.DashboardBody; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考GetDashboard中的。

以下代码示例显示了如何获取 Amazon CloudWatch 指标数据。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Get data for CloudWatch metrics. /// </summary> /// <param name="minutesOfData">The number of minutes of data to include.</param> /// <param name="useDescendingTime">True to return the data descending by time.</param> /// <param name="endDateUtc">The end date for the data, in UTC.</param> /// <param name="maxDataPoints">The maximum data points to include.</param> /// <param name="dataQueries">Optional data queries to include.</param> /// <returns>A list of the requested metric data.</returns> public async Task<List<MetricDataResult>> GetMetricData(int minutesOfData, bool useDescendingTime, DateTime? endDateUtc = null, int maxDataPoints = 0, List<MetricDataQuery>? dataQueries = null) { var metricData = new List<MetricDataResult>(); // If no end time is provided, use the current time for the end time. endDateUtc ??= DateTime.UtcNow; var timeZoneOffset = TimeZoneInfo.Local.GetUtcOffset(endDateUtc.Value.ToLocalTime()); var startTimeUtc = endDateUtc.Value.AddMinutes(-minutesOfData); // The timezone string should be in the format +0000, so use the timezone offset to format it correctly. var timeZoneString = $"{timeZoneOffset.Hours:D2}{timeZoneOffset.Minutes:D2}"; var paginatedMetricData = _amazonCloudWatch.Paginators.GetMetricData( new GetMetricDataRequest() { StartTimeUtc = startTimeUtc, EndTimeUtc = endDateUtc.Value, LabelOptions = new LabelOptions { Timezone = timeZoneString }, ScanBy = useDescendingTime ? ScanBy.TimestampDescending : ScanBy.TimestampAscending, MaxDatapoints = maxDataPoints, MetricDataQueries = dataQueries, }); await foreach (var data in paginatedMetricData.MetricDataResults) { metricData.Add(data); } return metricData; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考GetMetricData中的。

以下代码示例显示了如何获取 Amazon CloudWatch 指标统计数据。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Get billing statistics using a call to a wrapper class. /// </summary> /// <returns>A collection of billing statistics.</returns> private static async Task<List<Datapoint>> SetupBillingStatistics() { // Make a request for EstimatedCharges with a period of one day for the past seven days. var billingStatistics = await _cloudWatchWrapper.GetMetricStatistics( "AWS/Billing", "EstimatedCharges", new List<string>() { "Maximum" }, new List<Dimension>() { new Dimension { Name = "Currency", Value = "USD" } }, 7, 86400); billingStatistics = billingStatistics.OrderBy(n => n.Timestamp).ToList(); return billingStatistics; } /// <summary> /// Wrapper to get statistics for a specific CloudWatch metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The name of the metric.</param> /// <param name="statistics">The list of statistics to include.</param> /// <param name="dimensions">The list of dimensions to include.</param> /// <param name="days">The number of days in the past to include.</param> /// <param name="period">The period for the data.</param> /// <returns>A list of DataPoint objects for the statistics.</returns> public async Task<List<Datapoint>> GetMetricStatistics(string metricNamespace, string metricName, List<string> statistics, List<Dimension> dimensions, int days, int period) { var metricStatistics = await _amazonCloudWatch.GetMetricStatisticsAsync( new GetMetricStatisticsRequest() { Namespace = metricNamespace, MetricName = metricName, Dimensions = dimensions, Statistics = statistics, StartTimeUtc = DateTime.UtcNow.AddDays(-days), EndTimeUtc = DateTime.UtcNow, Period = period }); return metricStatistics.Datapoints; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考GetMetricStatistics中的。

以下代码示例显示了如何列出 Amazon CloudWatch 控制面板。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Get a list of dashboards. /// </summary> /// <returns>A list of DashboardEntry objects.</returns> public async Task<List<DashboardEntry>> ListDashboards() { var results = new List<DashboardEntry>(); var paginateDashboards = _amazonCloudWatch.Paginators.ListDashboards( new ListDashboardsRequest()); // Get the entire list using the paginator. await foreach (var data in paginateDashboards.DashboardEntries) { results.Add(data); } return results; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考ListDashboards中的。

以下代码示例显示如何列出 Amazon CloudWatch 指标的元数据。要获取指标的数据,请使用 GetMetricData 或 GetMetricStatistics 操作。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// List metrics available, optionally within a namespace. /// </summary> /// <param name="metricNamespace">Optional CloudWatch namespace to use when listing metrics.</param> /// <param name="filter">Optional dimension filter.</param> /// <param name="metricName">Optional metric name filter.</param> /// <returns>The list of metrics.</returns> public async Task<List<Metric>> ListMetrics(string? metricNamespace = null, DimensionFilter? filter = null, string? metricName = null) { var results = new List<Metric>(); var paginateMetrics = _amazonCloudWatch.Paginators.ListMetrics( new ListMetricsRequest { Namespace = metricNamespace, Dimensions = filter != null ? new List<DimensionFilter> { filter } : null, MetricName = metricName }); // Get the entire list using the paginator. await foreach (var metric in paginateMetrics.Metrics) { results.Add(metric); } return results; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考ListMetrics中的。

以下代码示例展示了如何将指标数据点发布到 Amazon CloudWatch。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

/// <summary> /// Add some metric data using a call to a wrapper class. /// </summary> /// <param name="customMetricName">The metric name.</param> /// <param name="customMetricNamespace">The metric namespace.</param> /// <returns></returns> private static async Task<List<MetricDatum>> PutRandomMetricData(string customMetricName, string customMetricNamespace) { List<MetricDatum> customData = new List<MetricDatum>(); Random rnd = new Random(); // Add 10 random values up to 100, starting with a timestamp 15 minutes in the past. var utcNowMinus15 = DateTime.UtcNow.AddMinutes(-15); for (int i = 0; i < 10; i++) { var metricValue = rnd.Next(0, 100); customData.Add( new MetricDatum { MetricName = customMetricName, Value = metricValue, TimestampUtc = utcNowMinus15.AddMinutes(i) } ); } await _cloudWatchWrapper.PutMetricData(customMetricNamespace, customData); return customData; } /// <summary> /// Wrapper to add metric data to a CloudWatch metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricData">A data object for the metric data.</param> /// <returns>True if successful.</returns> public async Task<bool> PutMetricData(string metricNamespace, List<MetricDatum> metricData) { var putDataResponse = await _amazonCloudWatch.PutMetricDataAsync( new PutMetricDataRequest() { MetricData = metricData, Namespace = metricNamespace, }); return putDataResponse.HttpStatusCode == HttpStatusCode.OK; }
  • 有关 API 的详细信息,请参阅 Amazon SDK for .NETAPI 参考PutMetricData中的。

场景

以下代码示例显示了操作流程:

  • 列出 CloudWatch 命名空间和指标。

  • 获取指标和预估账单的统计数据。

  • 创建和更新控制面板。

  • 创建数据并将数据添加到指标。

  • 创建并触发告警,然后查看告警历史记录。

  • 添加异常检测器

  • 获取指标映像,然后清理资源。

Amazon SDK for .NET
注意

还有更多相关信息 GitHub。在 Amazon 代码示例存储库中查找完整示例,了解如何进行设置和运行。

在命令提示符中运行交互式场景。

public class CloudWatchScenario { /* Before running this .NET code example, set up your development environment, including your credentials. To enable billing metrics and statistics for this example, make sure billing alerts are enabled for your account: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html#turning_on_billing_metrics This .NET example performs the following tasks: 1. List and select a CloudWatch namespace. 2. List and select a CloudWatch metric. 3. Get statistics for a CloudWatch metric. 4. Get estimated billing statistics for the last week. 5. Create a new CloudWatch dashboard with two metrics. 6. List current CloudWatch dashboards. 7. Create a CloudWatch custom metric and add metric data. 8. Add the custom metric to the dashboard. 9. Create a CloudWatch alarm for the custom metric. 10. Describe current CloudWatch alarms. 11. Get recent data for the custom metric. 12. Add data to the custom metric to trigger the alarm. 13. Wait for an alarm state. 14. Get history for the CloudWatch alarm. 15. Add an anomaly detector. 16. Describe current anomaly detectors. 17. Get and display a metric image. 18. Clean up resources. */ private static ILogger logger = null!; private static CloudWatchWrapper _cloudWatchWrapper = null!; private static IConfiguration _configuration = null!; private static readonly List<string> _statTypes = new List<string> { "SampleCount", "Average", "Sum", "Minimum", "Maximum" }; private static SingleMetricAnomalyDetector? anomalyDetector = null!; static async Task Main(string[] args) { // Set up dependency injection for the Amazon service. using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Debug) .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddAWSService<IAmazonCloudWatch>() .AddTransient<CloudWatchWrapper>() ) .Build(); _configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("settings.json") // Load settings from .json file. .AddJsonFile("settings.local.json", true) // Optionally, load local settings. .Build(); logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) .CreateLogger<CloudWatchScenario>(); _cloudWatchWrapper = host.Services.GetRequiredService<CloudWatchWrapper>(); Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the Amazon CloudWatch example scenario."); Console.WriteLine(new string('-', 80)); try { var selectedNamespace = await SelectNamespace(); var selectedMetric = await SelectMetric(selectedNamespace); await GetAndDisplayMetricStatistics(selectedNamespace, selectedMetric); await GetAndDisplayEstimatedBilling(); await CreateDashboardWithMetrics(); await ListDashboards(); await CreateNewCustomMetric(); await AddMetricToDashboard(); await CreateMetricAlarm(); await DescribeAlarms(); await GetCustomMetricData(); await AddMetricDataForAlarm(); await CheckForMetricAlarm(); await GetAlarmHistory(); anomalyDetector = await AddAnomalyDetector(); await DescribeAnomalyDetectors(); await GetAndOpenMetricImage(); await CleanupResources(); } catch (Exception ex) { logger.LogError(ex, "There was a problem executing the scenario."); await CleanupResources(); } } /// <summary> /// Select a namespace. /// </summary> /// <returns>The selected namespace.</returns> private static async Task<string> SelectNamespace() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"1. Select a CloudWatch Namespace from a list of Namespaces."); var metrics = await _cloudWatchWrapper.ListMetrics(); // Get a distinct list of namespaces. var namespaces = metrics.Select(m => m.Namespace).Distinct().ToList(); for (int i = 0; i < namespaces.Count; i++) { Console.WriteLine($"\t{i + 1}. {namespaces[i]}"); } var namespaceChoiceNumber = 0; while (namespaceChoiceNumber < 1 || namespaceChoiceNumber > namespaces.Count) { Console.WriteLine( "Select a namespace by entering a number from the preceding list:"); var choice = Console.ReadLine(); Int32.TryParse(choice, out namespaceChoiceNumber); } var selectedNamespace = namespaces[namespaceChoiceNumber - 1]; Console.WriteLine(new string('-', 80)); return selectedNamespace; } /// <summary> /// Select a metric from a namespace. /// </summary> /// <param name="metricNamespace">The namespace for metrics.</param> /// <returns>The metric name.</returns> private static async Task<Metric> SelectMetric(string metricNamespace) { Console.WriteLine(new string('-', 80)); Console.WriteLine($"2. Select a CloudWatch metric from a namespace."); var namespaceMetrics = await _cloudWatchWrapper.ListMetrics(metricNamespace); for (int i = 0; i < namespaceMetrics.Count && i < 15; i++) { var dimensionsWithValues = namespaceMetrics[i].Dimensions .Where(d => !string.Equals("None", d.Value)); Console.WriteLine($"\t{i + 1}. {namespaceMetrics[i].MetricName} " + $"{string.Join(", :", dimensionsWithValues.Select(d => d.Value))}"); } var metricChoiceNumber = 0; while (metricChoiceNumber < 1 || metricChoiceNumber > namespaceMetrics.Count) { Console.WriteLine( "Select a metric by entering a number from the preceding list:"); var choice = Console.ReadLine(); Int32.TryParse(choice, out metricChoiceNumber); } var selectedMetric = namespaceMetrics[metricChoiceNumber - 1]; Console.WriteLine(new string('-', 80)); return selectedMetric; } /// <summary> /// Get and display metric statistics for a specific metric. /// </summary> /// <param name="metricNamespace">The namespace for metrics.</param> /// <param name="metric">The CloudWatch metric.</param> /// <returns>Async task.</returns> private static async Task GetAndDisplayMetricStatistics(string metricNamespace, Metric metric) { Console.WriteLine(new string('-', 80)); Console.WriteLine($"3. Get CloudWatch metric statistics for the last day."); for (int i = 0; i < _statTypes.Count; i++) { Console.WriteLine($"\t{i + 1}. {_statTypes[i]}"); } var statisticChoiceNumber = 0; while (statisticChoiceNumber < 1 || statisticChoiceNumber > _statTypes.Count) { Console.WriteLine( "Select a metric statistic by entering a number from the preceding list:"); var choice = Console.ReadLine(); Int32.TryParse(choice, out statisticChoiceNumber); } var selectedStatistic = _statTypes[statisticChoiceNumber - 1]; var statisticsList = new List<string> { selectedStatistic }; var metricStatistics = await _cloudWatchWrapper.GetMetricStatistics(metricNamespace, metric.MetricName, statisticsList, metric.Dimensions, 1, 60); if (!metricStatistics.Any()) { Console.WriteLine($"No {selectedStatistic} statistics found for {metric} in namespace {metricNamespace}."); } metricStatistics = metricStatistics.OrderBy(s => s.Timestamp).ToList(); for (int i = 0; i < metricStatistics.Count && i < 10; i++) { var metricStat = metricStatistics[i]; var statValue = metricStat.GetType().GetProperty(selectedStatistic)!.GetValue(metricStat, null); Console.WriteLine($"\t{i + 1}. Timestamp {metricStatistics[i].Timestamp:G} {selectedStatistic}: {statValue}"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Get and display estimated billing statistics. /// </summary> /// <param name="metricNamespace">The namespace for metrics.</param> /// <param name="metric">The CloudWatch metric.</param> /// <returns>Async task.</returns> private static async Task GetAndDisplayEstimatedBilling() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"4. Get CloudWatch estimated billing for the last week."); var billingStatistics = await SetupBillingStatistics(); for (int i = 0; i < billingStatistics.Count; i++) { Console.WriteLine($"\t{i + 1}. Timestamp {billingStatistics[i].Timestamp:G} : {billingStatistics[i].Maximum}"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Get billing statistics using a call to a wrapper class. /// </summary> /// <returns>A collection of billing statistics.</returns> private static async Task<List<Datapoint>> SetupBillingStatistics() { // Make a request for EstimatedCharges with a period of one day for the past seven days. var billingStatistics = await _cloudWatchWrapper.GetMetricStatistics( "AWS/Billing", "EstimatedCharges", new List<string>() { "Maximum" }, new List<Dimension>() { new Dimension { Name = "Currency", Value = "USD" } }, 7, 86400); billingStatistics = billingStatistics.OrderBy(n => n.Timestamp).ToList(); return billingStatistics; } /// <summary> /// Create a dashboard with metrics. /// </summary> /// <param name="metricNamespace">The namespace for metrics.</param> /// <param name="metric">The CloudWatch metric.</param> /// <returns>Async task.</returns> private static async Task CreateDashboardWithMetrics() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"5. Create a new CloudWatch dashboard with metrics."); var dashboardName = _configuration["dashboardName"]; var newDashboard = new DashboardModel(); _configuration.GetSection("dashboardExampleBody").Bind(newDashboard); var newDashboardString = JsonSerializer.Serialize( newDashboard, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); var validationMessages = await _cloudWatchWrapper.PutDashboard(dashboardName, newDashboardString); Console.WriteLine(validationMessages.Any() ? $"\tValidation messages:" : null); for (int i = 0; i < validationMessages.Count; i++) { Console.WriteLine($"\t{i + 1}. {validationMessages[i].Message}"); } Console.WriteLine($"\tDashboard {dashboardName} was created."); Console.WriteLine(new string('-', 80)); } /// <summary> /// List dashboards. /// </summary> /// <returns>Async task.</returns> private static async Task ListDashboards() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"6. List the CloudWatch dashboards in the current account."); var dashboards = await _cloudWatchWrapper.ListDashboards(); for (int i = 0; i < dashboards.Count; i++) { Console.WriteLine($"\t{i + 1}. {dashboards[i].DashboardName}"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Create and add data for a new custom metric. /// </summary> /// <returns>Async task.</returns> private static async Task CreateNewCustomMetric() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"7. Create and add data for a new custom metric."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var customData = await PutRandomMetricData(customMetricName, customMetricNamespace); var valuesString = string.Join(',', customData.Select(d => d.Value)); Console.WriteLine($"\tAdded metric values for for metric {customMetricName}: \n\t{valuesString}"); Console.WriteLine(new string('-', 80)); } /// <summary> /// Add some metric data using a call to a wrapper class. /// </summary> /// <param name="customMetricName">The metric name.</param> /// <param name="customMetricNamespace">The metric namespace.</param> /// <returns></returns> private static async Task<List<MetricDatum>> PutRandomMetricData(string customMetricName, string customMetricNamespace) { List<MetricDatum> customData = new List<MetricDatum>(); Random rnd = new Random(); // Add 10 random values up to 100, starting with a timestamp 15 minutes in the past. var utcNowMinus15 = DateTime.UtcNow.AddMinutes(-15); for (int i = 0; i < 10; i++) { var metricValue = rnd.Next(0, 100); customData.Add( new MetricDatum { MetricName = customMetricName, Value = metricValue, TimestampUtc = utcNowMinus15.AddMinutes(i) } ); } await _cloudWatchWrapper.PutMetricData(customMetricNamespace, customData); return customData; } /// <summary> /// Add the custom metric to the dashboard. /// </summary> /// <returns>Async task.</returns> private static async Task AddMetricToDashboard() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"8. Add the new custom metric to the dashboard."); var dashboardName = _configuration["dashboardName"]; var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var validationMessages = await SetupDashboard(customMetricNamespace, customMetricName, dashboardName); Console.WriteLine(validationMessages.Any() ? $"\tValidation messages:" : null); for (int i = 0; i < validationMessages.Count; i++) { Console.WriteLine($"\t{i + 1}. {validationMessages[i].Message}"); } Console.WriteLine($"\tDashboard {dashboardName} updated with metric {customMetricName}."); Console.WriteLine(new string('-', 80)); } /// <summary> /// Set up a dashboard using a call to the wrapper class. /// </summary> /// <param name="customMetricNamespace">The metric namespace.</param> /// <param name="customMetricName">The metric name.</param> /// <param name="dashboardName">The name of the dashboard.</param> /// <returns>A list of validation messages.</returns> private static async Task<List<DashboardValidationMessage>> SetupDashboard( string customMetricNamespace, string customMetricName, string dashboardName) { // Get the dashboard model from configuration. var newDashboard = new DashboardModel(); _configuration.GetSection("dashboardExampleBody").Bind(newDashboard); // Add a new metric to the dashboard. newDashboard.Widgets.Add(new Widget { Height = 8, Width = 8, Y = 8, X = 0, Type = "metric", Properties = new Properties { Metrics = new List<List<object>> { new() { customMetricNamespace, customMetricName } }, View = "timeSeries", Region = "us-east-1", Stat = "Sum", Period = 86400, YAxis = new YAxis { Left = new Left { Min = 0, Max = 100 } }, Title = "Custom Metric Widget", LiveData = true, Sparkline = true, Trend = true, Stacked = false, SetPeriodToTimeRange = false } }); var newDashboardString = JsonSerializer.Serialize(newDashboard, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); var validationMessages = await _cloudWatchWrapper.PutDashboard(dashboardName, newDashboardString); return validationMessages; } /// <summary> /// Create a CloudWatch alarm for the new metric. /// </summary> /// <returns>Async task.</returns> private static async Task CreateMetricAlarm() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"9. Create a CloudWatch alarm for the new metric."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var alarmName = _configuration["exampleAlarmName"]; var accountId = _configuration["accountId"]; var region = _configuration["region"]; var emailTopic = _configuration["emailTopic"]; var alarmActions = new List<string>(); if (GetYesNoResponse( $"\tAdd an email action for topic {emailTopic} to alarm {alarmName}? (y/n)")) { _cloudWatchWrapper.AddEmailAlarmAction(accountId, region, emailTopic, alarmActions); } await _cloudWatchWrapper.PutMetricEmailAlarm( "Example metric alarm", alarmName, ComparisonOperator.GreaterThanOrEqualToThreshold, customMetricName, customMetricNamespace, 100, alarmActions); Console.WriteLine($"\tAlarm {alarmName} added for metric {customMetricName}."); Console.WriteLine(new string('-', 80)); } /// <summary> /// Describe Alarms. /// </summary> /// <returns>Async task.</returns> private static async Task DescribeAlarms() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"10. Describe CloudWatch alarms in the current account."); var alarms = await _cloudWatchWrapper.DescribeAlarms(); alarms = alarms.OrderByDescending(a => a.StateUpdatedTimestamp).ToList(); for (int i = 0; i < alarms.Count && i < 10; i++) { var alarm = alarms[i]; Console.WriteLine($"\t{i + 1}. {alarm.AlarmName}"); Console.WriteLine($"\tState: {alarm.StateValue} for {alarm.MetricName} {alarm.ComparisonOperator} {alarm.Threshold}"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Get the recent data for the metric. /// </summary> /// <returns>Async task.</returns> private static async Task GetCustomMetricData() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"11. Get current data for new custom metric."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var accountId = _configuration["accountId"]; var query = new List<MetricDataQuery> { new MetricDataQuery { AccountId = accountId, Id = "m1", Label = "Custom Metric Data", MetricStat = new MetricStat { Metric = new Metric { MetricName = customMetricName, Namespace = customMetricNamespace, }, Period = 1, Stat = "Maximum" } } }; var metricData = await _cloudWatchWrapper.GetMetricData( 20, true, DateTime.UtcNow.AddMinutes(1), 20, query); for (int i = 0; i < metricData.Count; i++) { for (int j = 0; j < metricData[i].Values.Count; j++) { Console.WriteLine( $"\tTimestamp {metricData[i].Timestamps[j]:G} Value: {metricData[i].Values[j]}"); } } Console.WriteLine(new string('-', 80)); } /// <summary> /// Add metric data to trigger an alarm. /// </summary> /// <returns>Async task.</returns> private static async Task AddMetricDataForAlarm() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"12. Add metric data to the custom metric to trigger an alarm."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var nowUtc = DateTime.UtcNow; List<MetricDatum> customData = new List<MetricDatum> { new MetricDatum { MetricName = customMetricName, Value = 101, TimestampUtc = nowUtc.AddMinutes(-2) }, new MetricDatum { MetricName = customMetricName, Value = 101, TimestampUtc = nowUtc.AddMinutes(-1) }, new MetricDatum { MetricName = customMetricName, Value = 101, TimestampUtc = nowUtc } }; var valuesString = string.Join(',', customData.Select(d => d.Value)); Console.WriteLine($"\tAdded metric values for for metric {customMetricName}: \n\t{valuesString}"); await _cloudWatchWrapper.PutMetricData(customMetricNamespace, customData); Console.WriteLine(new string('-', 80)); } /// <summary> /// Check for a metric alarm using the DescribeAlarmsForMetric action. /// </summary> /// <returns>Async task.</returns> private static async Task CheckForMetricAlarm() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"13. Checking for an alarm state."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var hasAlarm = false; var retries = 10; while (!hasAlarm && retries > 0) { var alarms = await _cloudWatchWrapper.DescribeAlarmsForMetric(customMetricNamespace, customMetricName); hasAlarm = alarms.Any(a => a.StateValue == StateValue.ALARM); retries--; Thread.Sleep(20000); } Console.WriteLine(hasAlarm ? $"\tAlarm state found for {customMetricName}." : $"\tNo Alarm state found for {customMetricName} after 10 retries."); Console.WriteLine(new string('-', 80)); } /// <summary> /// Get history for an alarm. /// </summary> /// <returns>Async task.</returns> private static async Task GetAlarmHistory() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"14. Get alarm history."); var exampleAlarmName = _configuration["exampleAlarmName"]; var alarmHistory = await _cloudWatchWrapper.DescribeAlarmHistory(exampleAlarmName, 2); for (int i = 0; i < alarmHistory.Count; i++) { var history = alarmHistory[i]; Console.WriteLine($"\t{i + 1}. {history.HistorySummary}, time {history.Timestamp:g}"); } if (!alarmHistory.Any()) { Console.WriteLine($"\tNo alarm history data found for {exampleAlarmName}."); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Add an anomaly detector. /// </summary> /// <returns>Async task.</returns> private static async Task<SingleMetricAnomalyDetector> AddAnomalyDetector() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"15. Add an anomaly detector."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var detector = new SingleMetricAnomalyDetector { MetricName = customMetricName, Namespace = customMetricNamespace, Stat = "Maximum" }; await _cloudWatchWrapper.PutAnomalyDetector(detector); Console.WriteLine($"\tAdded anomaly detector for metric {customMetricName}."); Console.WriteLine(new string('-', 80)); return detector; } /// <summary> /// Describe anomaly detectors. /// </summary> /// <returns>Async task.</returns> private static async Task DescribeAnomalyDetectors() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"16. Describe anomaly detectors in the current account."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var detectors = await _cloudWatchWrapper.DescribeAnomalyDetectors(customMetricNamespace, customMetricName); for (int i = 0; i < detectors.Count; i++) { var detector = detectors[i]; Console.WriteLine($"\t{i + 1}. {detector.SingleMetricAnomalyDetector.MetricName}, state {detector.StateValue}"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Fetch and open a metrics image for a CloudWatch metric and namespace. /// </summary> /// <returns>Async task.</returns> private static async Task GetAndOpenMetricImage() { Console.WriteLine(new string('-', 80)); Console.WriteLine("17. Get a metric image from CloudWatch."); Console.WriteLine($"\tGetting Image data for custom metric."); var customMetricNamespace = _configuration["customMetricNamespace"]; var customMetricName = _configuration["customMetricName"]; var memoryStream = await _cloudWatchWrapper.GetTimeSeriesMetricImage(customMetricNamespace, customMetricName, "Maximum", 10); var file = _cloudWatchWrapper.SaveMetricImage(memoryStream, "MetricImages"); ProcessStartInfo info = new ProcessStartInfo(); Console.WriteLine($"\tFile saved as {Path.GetFileName(file)}."); Console.WriteLine($"\tPress enter to open the image."); Console.ReadLine(); info.FileName = Path.Combine("ms-photos://", file); info.UseShellExecute = true; info.CreateNoWindow = true; info.Verb = string.Empty; Process.Start(info); Console.WriteLine(new string('-', 80)); } /// <summary> /// Clean up created resources. /// </summary> /// <param name="metricNamespace">The namespace for metrics.</param> /// <param name="metric">The CloudWatch metric.</param> /// <returns>Async task.</returns> private static async Task CleanupResources() { Console.WriteLine(new string('-', 80)); Console.WriteLine($"18. Clean up resources."); var dashboardName = _configuration["dashboardName"]; if (GetYesNoResponse($"\tDelete dashboard {dashboardName}? (y/n)")) { Console.WriteLine($"\tDeleting dashboard."); var dashboardList = new List<string> { dashboardName }; await _cloudWatchWrapper.DeleteDashboards(dashboardList); } var alarmName = _configuration["exampleAlarmName"]; if (GetYesNoResponse($"\tDelete alarm {alarmName}? (y/n)")) { Console.WriteLine($"\tCleaning up alarms."); var alarms = new List<string> { alarmName }; await _cloudWatchWrapper.DeleteAlarms(alarms); } if (GetYesNoResponse($"\tDelete anomaly detector? (y/n)") && anomalyDetector != null) { Console.WriteLine($"\tCleaning up anomaly detector."); await _cloudWatchWrapper.DeleteAnomalyDetector( anomalyDetector); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Get a yes or no response from the user. /// </summary> /// <param name="question">The question string to print on the console.</param> /// <returns>True if the user responds with a yes.</returns> private static bool GetYesNoResponse(string question) { Console.WriteLine(question); var ynResponse = Console.ReadLine(); var response = ynResponse != null && ynResponse.Equals("y", StringComparison.InvariantCultureIgnoreCase); return response; } }

场景用于 CloudWatch 操作的封装方法。

/// <summary> /// Wrapper class for Amazon CloudWatch methods. /// </summary> public class CloudWatchWrapper { private readonly IAmazonCloudWatch _amazonCloudWatch; private readonly ILogger<CloudWatchWrapper> _logger; /// <summary> /// Constructor for the CloudWatch wrapper. /// </summary> /// <param name="amazonCloudWatch">The injected CloudWatch client.</param> /// <param name="logger">The injected logger for the wrapper.</param> public CloudWatchWrapper(IAmazonCloudWatch amazonCloudWatch, ILogger<CloudWatchWrapper> logger) { _logger = logger; _amazonCloudWatch = amazonCloudWatch; } /// <summary> /// List metrics available, optionally within a namespace. /// </summary> /// <param name="metricNamespace">Optional CloudWatch namespace to use when listing metrics.</param> /// <param name="filter">Optional dimension filter.</param> /// <param name="metricName">Optional metric name filter.</param> /// <returns>The list of metrics.</returns> public async Task<List<Metric>> ListMetrics(string? metricNamespace = null, DimensionFilter? filter = null, string? metricName = null) { var results = new List<Metric>(); var paginateMetrics = _amazonCloudWatch.Paginators.ListMetrics( new ListMetricsRequest { Namespace = metricNamespace, Dimensions = filter != null ? new List<DimensionFilter> { filter } : null, MetricName = metricName }); // Get the entire list using the paginator. await foreach (var metric in paginateMetrics.Metrics) { results.Add(metric); } return results; } /// <summary> /// Wrapper to get statistics for a specific CloudWatch metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The name of the metric.</param> /// <param name="statistics">The list of statistics to include.</param> /// <param name="dimensions">The list of dimensions to include.</param> /// <param name="days">The number of days in the past to include.</param> /// <param name="period">The period for the data.</param> /// <returns>A list of DataPoint objects for the statistics.</returns> public async Task<List<Datapoint>> GetMetricStatistics(string metricNamespace, string metricName, List<string> statistics, List<Dimension> dimensions, int days, int period) { var metricStatistics = await _amazonCloudWatch.GetMetricStatisticsAsync( new GetMetricStatisticsRequest() { Namespace = metricNamespace, MetricName = metricName, Dimensions = dimensions, Statistics = statistics, StartTimeUtc = DateTime.UtcNow.AddDays(-days), EndTimeUtc = DateTime.UtcNow, Period = period }); return metricStatistics.Datapoints; } /// <summary> /// Wrapper to create or add to a dashboard with metrics. /// </summary> /// <param name="dashboardName">The name for the dashboard.</param> /// <param name="dashboardBody">The metric data in JSON for the dashboard.</param> /// <returns>A list of validation messages for the dashboard.</returns> public async Task<List<DashboardValidationMessage>> PutDashboard(string dashboardName, string dashboardBody) { // Updating a dashboard replaces all contents. // Best practice is to include a text widget indicating this dashboard was created programmatically. var dashboardResponse = await _amazonCloudWatch.PutDashboardAsync( new PutDashboardRequest() { DashboardName = dashboardName, DashboardBody = dashboardBody }); return dashboardResponse.DashboardValidationMessages; } /// <summary> /// Get information on a dashboard. /// </summary> /// <param name="dashboardName">The name of the dashboard.</param> /// <returns>A JSON object with dashboard information.</returns> public async Task<string> GetDashboard(string dashboardName) { var dashboardResponse = await _amazonCloudWatch.GetDashboardAsync( new GetDashboardRequest() { DashboardName = dashboardName }); return dashboardResponse.DashboardBody; } /// <summary> /// Get a list of dashboards. /// </summary> /// <returns>A list of DashboardEntry objects.</returns> public async Task<List<DashboardEntry>> ListDashboards() { var results = new List<DashboardEntry>(); var paginateDashboards = _amazonCloudWatch.Paginators.ListDashboards( new ListDashboardsRequest()); // Get the entire list using the paginator. await foreach (var data in paginateDashboards.DashboardEntries) { results.Add(data); } return results; } /// <summary> /// Wrapper to add metric data to a CloudWatch metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricData">A data object for the metric data.</param> /// <returns>True if successful.</returns> public async Task<bool> PutMetricData(string metricNamespace, List<MetricDatum> metricData) { var putDataResponse = await _amazonCloudWatch.PutMetricDataAsync( new PutMetricDataRequest() { MetricData = metricData, Namespace = metricNamespace, }); return putDataResponse.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Get an image for a metric graphed over time. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metric">The name of the metric.</param> /// <param name="stat">The name of the stat to chart.</param> /// <param name="period">The period to use for the chart.</param> /// <returns>A memory stream for the chart image.</returns> public async Task<MemoryStream> GetTimeSeriesMetricImage(string metricNamespace, string metric, string stat, int period) { var metricImageWidget = new { title = "Example Metric Graph", view = "timeSeries", stacked = false, period = period, width = 1400, height = 600, metrics = new List<List<object>> { new() { metricNamespace, metric, new { stat } } } }; var metricImageWidgetString = JsonSerializer.Serialize(metricImageWidget); var imageResponse = await _amazonCloudWatch.GetMetricWidgetImageAsync( new GetMetricWidgetImageRequest() { MetricWidget = metricImageWidgetString }); return imageResponse.MetricWidgetImage; } /// <summary> /// Save a metric image to a file. /// </summary> /// <param name="memoryStream">The MemoryStream for the metric image.</param> /// <param name="metricName">The name of the metric.</param> /// <returns>The path to the file.</returns> public string SaveMetricImage(MemoryStream memoryStream, string metricName) { var metricFileName = $"{metricName}_{DateTime.Now.Ticks}.png"; using var sr = new StreamReader(memoryStream); // Writes the memory stream to a file. File.WriteAllBytes(metricFileName, memoryStream.ToArray()); var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, metricFileName); return filePath; } /// <summary> /// Get data for CloudWatch metrics. /// </summary> /// <param name="minutesOfData">The number of minutes of data to include.</param> /// <param name="useDescendingTime">True to return the data descending by time.</param> /// <param name="endDateUtc">The end date for the data, in UTC.</param> /// <param name="maxDataPoints">The maximum data points to include.</param> /// <param name="dataQueries">Optional data queries to include.</param> /// <returns>A list of the requested metric data.</returns> public async Task<List<MetricDataResult>> GetMetricData(int minutesOfData, bool useDescendingTime, DateTime? endDateUtc = null, int maxDataPoints = 0, List<MetricDataQuery>? dataQueries = null) { var metricData = new List<MetricDataResult>(); // If no end time is provided, use the current time for the end time. endDateUtc ??= DateTime.UtcNow; var timeZoneOffset = TimeZoneInfo.Local.GetUtcOffset(endDateUtc.Value.ToLocalTime()); var startTimeUtc = endDateUtc.Value.AddMinutes(-minutesOfData); // The timezone string should be in the format +0000, so use the timezone offset to format it correctly. var timeZoneString = $"{timeZoneOffset.Hours:D2}{timeZoneOffset.Minutes:D2}"; var paginatedMetricData = _amazonCloudWatch.Paginators.GetMetricData( new GetMetricDataRequest() { StartTimeUtc = startTimeUtc, EndTimeUtc = endDateUtc.Value, LabelOptions = new LabelOptions { Timezone = timeZoneString }, ScanBy = useDescendingTime ? ScanBy.TimestampDescending : ScanBy.TimestampAscending, MaxDatapoints = maxDataPoints, MetricDataQueries = dataQueries, }); await foreach (var data in paginatedMetricData.MetricDataResults) { metricData.Add(data); } return metricData; } /// <summary> /// Add a metric alarm to send an email when the metric passes a threshold. /// </summary> /// <param name="alarmDescription">A description of the alarm.</param> /// <param name="alarmName">The name for the alarm.</param> /// <param name="comparison">The type of comparison to use.</param> /// <param name="metricName">The name of the metric for the alarm.</param> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="threshold">The threshold value for the alarm.</param> /// <param name="alarmActions">Optional actions to execute when in an alarm state.</param> /// <returns>True if successful.</returns> public async Task<bool> PutMetricEmailAlarm(string alarmDescription, string alarmName, ComparisonOperator comparison, string metricName, string metricNamespace, double threshold, List<string> alarmActions = null!) { try { var putEmailAlarmResponse = await _amazonCloudWatch.PutMetricAlarmAsync( new PutMetricAlarmRequest() { AlarmActions = alarmActions, AlarmDescription = alarmDescription, AlarmName = alarmName, ComparisonOperator = comparison, Threshold = threshold, Namespace = metricNamespace, MetricName = metricName, EvaluationPeriods = 1, Period = 10, Statistic = new Statistic("Maximum"), DatapointsToAlarm = 1, TreatMissingData = "ignore" }); return putEmailAlarmResponse.HttpStatusCode == HttpStatusCode.OK; } catch (LimitExceededException lex) { _logger.LogError(lex, $"Unable to add alarm {alarmName}. Alarm quota has already been reached."); } return false; } /// <summary> /// Add specific email actions to a list of action strings for a CloudWatch alarm. /// </summary> /// <param name="accountId">The AccountId for the alarm.</param> /// <param name="region">The region for the alarm.</param> /// <param name="emailTopicName">An Amazon Simple Notification Service (SNS) topic for the alarm email.</param> /// <param name="alarmActions">Optional list of existing alarm actions to append to.</param> /// <returns>A list of string actions for an alarm.</returns> public List<string> AddEmailAlarmAction(string accountId, string region, string emailTopicName, List<string>? alarmActions = null) { alarmActions ??= new List<string>(); var snsAlarmAction = $"arn:aws:sns:{region}:{accountId}:{emailTopicName}"; alarmActions.Add(snsAlarmAction); return alarmActions; } /// <summary> /// Describe the current alarms, optionally filtered by state. /// </summary> /// <param name="stateValue">Optional filter for alarm state.</param> /// <returns>The list of alarm data.</returns> public async Task<List<MetricAlarm>> DescribeAlarms(StateValue? stateValue = null) { List<MetricAlarm> alarms = new List<MetricAlarm>(); var paginatedDescribeAlarms = _amazonCloudWatch.Paginators.DescribeAlarms( new DescribeAlarmsRequest() { StateValue = stateValue }); await foreach (var data in paginatedDescribeAlarms.MetricAlarms) { alarms.Add(data); } return alarms; } /// <summary> /// Describe the current alarms for a specific metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The name of the metric.</param> /// <returns>The list of alarm data.</returns> public async Task<List<MetricAlarm>> DescribeAlarmsForMetric(string metricNamespace, string metricName) { var alarmsResult = await _amazonCloudWatch.DescribeAlarmsForMetricAsync( new DescribeAlarmsForMetricRequest() { Namespace = metricNamespace, MetricName = metricName }); return alarmsResult.MetricAlarms; } /// <summary> /// Describe the history of an alarm for a number of days in the past. /// </summary> /// <param name="alarmName">The name of the alarm.</param> /// <param name="historyDays">The number of days in the past.</param> /// <returns>The list of alarm history data.</returns> public async Task<List<AlarmHistoryItem>> DescribeAlarmHistory(string alarmName, int historyDays) { List<AlarmHistoryItem> alarmHistory = new List<AlarmHistoryItem>(); var paginatedAlarmHistory = _amazonCloudWatch.Paginators.DescribeAlarmHistory( new DescribeAlarmHistoryRequest() { AlarmName = alarmName, EndDateUtc = DateTime.UtcNow, HistoryItemType = HistoryItemType.StateUpdate, StartDateUtc = DateTime.UtcNow.AddDays(-historyDays) }); await foreach (var data in paginatedAlarmHistory.AlarmHistoryItems) { alarmHistory.Add(data); } return alarmHistory; } /// <summary> /// Delete a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAlarms(List<string> alarmNames) { var deleteAlarmsResult = await _amazonCloudWatch.DeleteAlarmsAsync( new DeleteAlarmsRequest() { AlarmNames = alarmNames }); return deleteAlarmsResult.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Disable the actions for a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms.</param> /// <returns>True if successful.</returns> public async Task<bool> DisableAlarmActions(List<string> alarmNames) { var disableAlarmActionsResult = await _amazonCloudWatch.DisableAlarmActionsAsync( new DisableAlarmActionsRequest() { AlarmNames = alarmNames }); return disableAlarmActionsResult.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Enable the actions for a list of alarms from CloudWatch. /// </summary> /// <param name="alarmNames">A list of names of alarms.</param> /// <returns>True if successful.</returns> public async Task<bool> EnableAlarmActions(List<string> alarmNames) { var enableAlarmActionsResult = await _amazonCloudWatch.EnableAlarmActionsAsync( new EnableAlarmActionsRequest() { AlarmNames = alarmNames }); return enableAlarmActionsResult.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Add an anomaly detector for a single metric. /// </summary> /// <param name="anomalyDetector">A single metric anomaly detector.</param> /// <returns>True if successful.</returns> public async Task<bool> PutAnomalyDetector(SingleMetricAnomalyDetector anomalyDetector) { var putAlarmDetectorResult = await _amazonCloudWatch.PutAnomalyDetectorAsync( new PutAnomalyDetectorRequest() { SingleMetricAnomalyDetector = anomalyDetector }); return putAlarmDetectorResult.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Describe anomaly detectors for a metric and namespace. /// </summary> /// <param name="metricNamespace">The namespace of the metric.</param> /// <param name="metricName">The metric of the anomaly detectors.</param> /// <returns>The list of detectors.</returns> public async Task<List<AnomalyDetector>> DescribeAnomalyDetectors(string metricNamespace, string metricName) { List<AnomalyDetector> detectors = new List<AnomalyDetector>(); var paginatedDescribeAnomalyDetectors = _amazonCloudWatch.Paginators.DescribeAnomalyDetectors( new DescribeAnomalyDetectorsRequest() { MetricName = metricName, Namespace = metricNamespace }); await foreach (var data in paginatedDescribeAnomalyDetectors.AnomalyDetectors) { detectors.Add(data); } return detectors; } /// <summary> /// Delete a single metric anomaly detector. /// </summary> /// <param name="anomalyDetector">The anomaly detector to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAnomalyDetector(SingleMetricAnomalyDetector anomalyDetector) { var deleteAnomalyDetectorResponse = await _amazonCloudWatch.DeleteAnomalyDetectorAsync( new DeleteAnomalyDetectorRequest() { SingleMetricAnomalyDetector = anomalyDetector }); return deleteAnomalyDetectorResponse.HttpStatusCode == HttpStatusCode.OK; } /// <summary> /// Delete a list of CloudWatch dashboards. /// </summary> /// <param name="dashboardNames">List of dashboard names to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteDashboards(List<string> dashboardNames) { var deleteDashboardsResponse = await _amazonCloudWatch.DeleteDashboardsAsync( new DeleteDashboardsRequest() { DashboardNames = dashboardNames }); return deleteDashboardsResponse.HttpStatusCode == HttpStatusCode.OK; } }