¡Ya está disponible la AWS SDK para .NET versión 4 (V4) del!
Para obtener información sobre los cambios importantes y la migración de sus aplicaciones, consulte el tema sobre https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html migración.
Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
CloudWatch ejemplos que utilizan SDK para .NET (v4)
Los siguientes ejemplos de código muestran cómo realizar acciones e implementar escenarios comunes mediante el uso de AWS SDK para .NET (v4) con CloudWatch.
Los conceptos básicos son ejemplos de código que muestran cómo realizar las operaciones esenciales dentro de un servicio.
Las acciones son extractos de código de programas más grandes y deben ejecutarse en contexto. Mientras las acciones muestran cómo llamar a las distintas funciones de servicio, es posible ver las acciones en contexto en los escenarios relacionados.
Los escenarios son ejemplos de código que muestran cómo llevar a cabo una tarea específica a través de llamadas a varias funciones dentro del servicio o combinado con otros Servicios de AWS.
En cada ejemplo se incluye un enlace al código de origen completo, con instrucciones de configuración y ejecución del código en el contexto.
Introducción
En el siguiente ejemplo de código se muestra cómo empezar a utilizar CloudWatch.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. 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(); if (response.Metrics != null) { 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(); } } } }-
Para obtener más información sobre la API, consulta ListMetrics la Referencia de AWS SDK para .NET API.
-
Conceptos básicos
En el siguiente ejemplo de código, se muestra cómo:
Enumera los CloudWatch espacios de nombres y las métricas.
Comience a OpenTelemetry enriquecer de manera que CloudWatch correlacione las métricas OTLP entrantes con los recursos que las generaron.
Vea cómo las métricas de OTLP llegan al punto final de las métricas. CloudWatch La ingesta de métricas mediante OTLP no es una AWS operación del SDK.
Cree una alarma que evalúe una consulta de PromQL.
Inspeccione los factores que contribuyen a la alarma y las series individuales con las que coincide la consulta.
Obtenga las estadísticas de una métrica y gráquela en un tablero.
Silencia la alarma durante un período de mantenimiento y, a continuación, límpiala.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. Ejecutar un escenario interactivo en un símbolo del sistema.
public class CloudWatchScenario { /* Before running this .NET code example, set up your development environment, including your credentials. This scenario demonstrates the Amazon CloudWatch OpenTelemetry (OTel) experience. CloudWatch ingests OpenTelemetry metrics natively, and this example walks through what you do with them: turning on enrichment so CloudWatch can correlate incoming OTLP metrics with the resources that produced them, alarming on those metrics with a PromQL query, and finding out which individual series drove the alarm. A PromQL alarm works differently from a classic metric alarm. Rather than watching one metric and counting breaching periods, it evaluates a query that can match many series at once, and tracks each matching series separately as a contributor. Note that sending OTLP metrics to CloudWatch is not an AWS SDK operation. Metrics arrive over the OTLP protocol through the CloudWatch agent, an OpenTelemetry Collector, or an ADOT SDK. Everything this scenario does is configuration and querying around that ingestion path. This .NET example performs the following tasks: 1. List metrics and namespaces from CloudWatch. 2. Start OpenTelemetry enrichment for the account. 3. Explain how OTLP metrics reach CloudWatch. 4. Create an alarm that evaluates a PromQL query. 5. Inspect the contributors to the PromQL alarm. 6. Get metric statistics and chart the metric on a dashboard. 7. Mute the alarm for a maintenance window. 8. Clean up resources. */ private static ILogger logger = null!; private static CloudWatchWrapper _cloudWatchWrapper = null!; private static CloudWatchOTelWrapper _otelWrapper = null!; private static IConfiguration _configuration = null!; private const string DefaultQuery = "avg by (host) (system_cpu_utilization) > 80"; // Valid evaluation intervals are 10, 20, 30, or any multiple of 60 up to 3600 seconds. private const int EvaluationInterval = 60; private const int PendingPeriod = 300; private const int RecoveryPeriod = 120; private static string _alarmName = null!; private static string _dashboardName = null!; private static string _muteRuleName = null!; // Tracks whether this run turned enrichment on, so that cleanup only turns off // enrichment that this run started. private static bool _startedEnrichment; private static bool _dashboardCreated; private static string _region = 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>() .AddTransient<CloudWatchOTelWrapper>() ) .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>(); _otelWrapper = host.Services.GetRequiredService<CloudWatchOTelWrapper>(); // A metric widget must name its region, because a dashboard can chart // metrics from several. _region = host.Services.GetRequiredService<IAmazonCloudWatch>() .Config.RegionEndpoint.SystemName; // Suffix the resource names so repeated runs do not collide. var suffix = Random.Shared.Next(1000, 9999).ToString(); _alarmName = $"doc-example-promql-alarm-{suffix}"; _dashboardName = $"doc-example-dashboard-{suffix}"; _muteRuleName = $"doc-example-mute-rule-{suffix}"; Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the Amazon CloudWatch Basics scenario."); Console.WriteLine(new string('-', 80)); Console.WriteLine( "\nCloudWatch now ingests OpenTelemetry metrics natively. This scenario walks through" + "\nthat experience: it turns on OTel enrichment so CloudWatch can correlate incoming" + "\nOTLP metrics with the resources that produced them, alarms on those metrics with a" + "\nPromQL query, and shows you which individual series drove the alarm." + "\n" + "\nA PromQL alarm works differently from a classic metric alarm. Rather than watching" + "\none metric and counting breaching periods, it evaluates a query that can match many" + "\nseries at once, and tracks each one separately as a contributor.\n"); try { var namespaces = await ListMetricsAndNamespaces(); await StartOTelEnrichment(); ExplainOtlpIngestion(); await CreatePromQlAlarm(); await InspectAlarmContributors(); await GetStatisticsAndChartMetric(namespaces); await MuteAlarmForMaintenance(); await CleanUp(); Console.WriteLine(new string('-', 80)); Console.WriteLine("CloudWatch Basics scenario is complete."); Console.WriteLine(new string('-', 80)); } catch (Exception ex) { Console.WriteLine(new string('-', 80)); logger.LogError(ex, "There was a problem executing the scenario."); await CleanUp(); Console.WriteLine(new string('-', 80)); } } /// <summary> /// List the metrics and namespaces already present in the account, to orient the /// reader before any configuration happens. /// </summary> /// <returns>The distinct namespaces found.</returns> private static async Task<List<string>> ListMetricsAndNamespaces() { Console.WriteLine(new string('-', 80)); Console.WriteLine("1. List metrics and namespaces"); Console.WriteLine( "\nBefore configuring anything, let's see what CloudWatch is already collecting in" + "\nthis account by calling ListMetrics.\n"); var metrics = await _cloudWatchWrapper.ListMetrics(); // Order by metric count descending, so the most-populated namespace comes first. // Step 6 charts a metric from that namespace, and a busy namespace is the one most // likely to have datapoints worth looking at. var namespaceCounts = metrics .GroupBy(m => m.Namespace) .Select(g => new { Namespace = g.Key, Count = g.Count() }) .OrderByDescending(n => n.Count) .ToList(); var namespaces = namespaceCounts.Select(n => n.Namespace).ToList(); Console.WriteLine($"\tFound {metrics.Count} metrics across {namespaces.Count} namespaces:"); foreach (var entry in namespaceCounts.Take(10)) { Console.WriteLine($"\t {entry.Namespace} ({entry.Count} metrics)"); } if (!namespaces.Any()) { Console.WriteLine( "\tNo metrics found in this account. The statistics and dashboard steps later on" + "\n\tneed an existing metric, so they will be skipped."); } Console.WriteLine(new string('-', 80)); return namespaces; } /// <summary> /// Start OTel enrichment, but only if it is not already running. Enrichment is what /// makes CloudWatch attach AWS resource context to incoming OTLP metrics. /// </summary> private static async Task StartOTelEnrichment() { Console.WriteLine(new string('-', 80)); Console.WriteLine("2. Start OpenTelemetry enrichment"); Console.WriteLine( "\nEnrichment is what lets CloudWatch attach AWS resource context to the OTLP metrics" + "\nyou send it. Without it, your metrics arrive as opaque series with no connection to" + "\nthe resources that emitted them." + "\n" + "\nWe check the current state first, and only start enrichment if it isn't already on.\n"); var status = await _otelWrapper.GetOTelEnrichmentStatus(); Console.WriteLine($"\tEnrichment status: {status}"); if (status != OTelEnrichmentStatus.Running) { // Record the attempt before making it. We already know enrichment was not running, // so stopping it during cleanup is always safe, and a call that starts enrichment // but then fails to report back (a timeout, say) would otherwise leave it running. _startedEnrichment = true; await _otelWrapper.StartOTelEnrichment(); status = await _otelWrapper.GetOTelEnrichmentStatus(); Console.WriteLine($"\tEnrichment status: {status}"); Console.WriteLine( "\n\tNote: this run started enrichment, so the cleanup step will stop it again."); } else { Console.WriteLine( "\n\tEnrichment was already running, so we will leave it alone. The cleanup step" + "\n\twill not stop it, because other workloads in this account may depend on it."); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Explain that OTLP metric ingestion is not an AWS SDK operation. This step makes no /// service call; naming the gap explicitly is the point. /// </summary> private static void ExplainOtlpIngestion() { Console.WriteLine(new string('-', 80)); Console.WriteLine("3. Send OTLP metrics to CloudWatch"); Console.WriteLine( "\nThis step is not an AWS SDK operation, and that's worth being explicit about." + "\nMetrics reach CloudWatch over the OTLP protocol, through the CloudWatch agent, an" + "\nOpenTelemetry Collector, or an ADOT SDK. There is no PutOTelMetrics API to call." + "\n" + "\nPoint your collector at the CloudWatch metrics endpoint, which follows the pattern" + "\n\thttps://monitoring.<region>.amazonaws.com/v1/metrics" + "\n" + "\nThe endpoint is HTTP/1.1 only and does not support gRPC, so use an otlphttp" + "\nexporter rather than otlp. The metrics endpoint signs as \"monitoring\".\n"); Console.WriteLine(new string('-', 80)); } /// <summary> /// Create an alarm whose evaluation is a PromQL query. /// </summary> private static async Task CreatePromQlAlarm() { Console.WriteLine(new string('-', 80)); Console.WriteLine("4. Create a PromQL alarm"); Console.WriteLine( "\nNow we alarm on those metrics. The comparison goes inside the query itself: a" + "\nPromQL alarm has no separate threshold, comparison operator, statistic, or period.\n"); Console.WriteLine($"Enter a PromQL query, or press <ENTER> for the default\n[{DefaultQuery}]:"); var input = Console.ReadLine(); var query = string.IsNullOrWhiteSpace(input) ? DefaultQuery : input.Trim(); await _otelWrapper.PutPromQLMetricAlarm(_alarmName, query, EvaluationInterval, PendingPeriod, RecoveryPeriod); Console.WriteLine($"\tCreated alarm {_alarmName}:"); Console.WriteLine($"\t query: {query}"); Console.WriteLine($"\t evaluationInterval: {EvaluationInterval} seconds"); Console.WriteLine($"\t pendingPeriod: {PendingPeriod} seconds"); Console.WriteLine($"\t recoveryPeriod: {RecoveryPeriod} seconds"); Console.WriteLine( "\n\tA PromQL alarm starts in the OK state rather than INSUFFICIENT_DATA, which is" + "\n\tanother way it differs from a classic alarm."); Console.WriteLine(new string('-', 80)); } /// <summary> /// Show which individual series the alarm's query matched. This is the step with no /// classic-alarm equivalent. /// </summary> private static async Task InspectAlarmContributors() { Console.WriteLine(new string('-', 80)); Console.WriteLine("5. Inspect the alarm's contributors"); Console.WriteLine( "\nEach contributor is one series the query matched, identified by its label set." + "\nThis is how you find out which host is unhealthy rather than only that something" + "\nis. Classic alarms have no equivalent.\n"); var contributors = await _otelWrapper.DescribeAlarmContributors(_alarmName); if (!contributors.Any()) { Console.WriteLine( "\tNo contributors yet. The query matched no series, which usually means no OTel" + "\n\tmetrics with these labels have arrived. Once your collector is sending data," + "\n\teach matching series appears here with its labels and why it breached."); } else { Console.WriteLine($"\tFound {contributors.Count} contributors:"); foreach (var contributor in contributors) { var labels = string.Join(", ", contributor.ContributorAttributes.Select(a => $"{a.Key}={a.Value}")); Console.WriteLine($"\t {contributor.ContributorId}: {labels}"); Console.WriteLine($"\t reason: {contributor.StateReason}"); } } Console.WriteLine(new string('-', 80)); } /// <summary> /// Get statistics for an existing metric and chart it on a dashboard, so the reader can /// see what the alarm is evaluating. /// </summary> /// <param name="namespaces">The namespaces discovered in step 1.</param> private static async Task GetStatisticsAndChartMetric(List<string> namespaces) { Console.WriteLine(new string('-', 80)); Console.WriteLine("6. Get statistics and chart the metric on a dashboard"); Console.WriteLine("\nStatistics and dashboards are how you see what the alarm is evaluating.\n"); if (!namespaces.Any()) { Console.WriteLine("\tSkipping statistics and dashboard because no metrics exist yet."); Console.WriteLine(new string('-', 80)); return; } var metricNamespace = namespaces.First(); var metrics = await _cloudWatchWrapper.ListMetrics(metricNamespace); var metric = metrics.FirstOrDefault(); if (metric != null) { var datapoints = await _cloudWatchWrapper.GetMetricStatistics( metricNamespace, metric.MetricName, new List<string> { "Average", "Maximum" }, metric.Dimensions, 1, 3600); Console.WriteLine( $"\tStatistics for {metricNamespace} {metric.MetricName} over the last day:"); Console.WriteLine($"\t Datapoints: {datapoints.Count}"); foreach (var datapoint in datapoints.Take(3)) { Console.WriteLine( $"\t {datapoint.Timestamp:u} average {datapoint.Average}, maximum {datapoint.Maximum}"); } var dashboardBody = BuildDashboardBody(metricNamespace, metric, _region); var validationMessages = await _cloudWatchWrapper.PutDashboard(_dashboardName, dashboardBody); _dashboardCreated = true; if (validationMessages.Any()) { foreach (var message in validationMessages) { Console.WriteLine($"\tDashboard validation message: {message.Message}"); } } Console.WriteLine($"\tCreated dashboard {_dashboardName}."); var dashboard = await _cloudWatchWrapper.GetDashboard(_dashboardName); Console.WriteLine($"\tRead the dashboard back, {dashboard.Length} characters of widget JSON."); } else { Console.WriteLine($"\tNo metrics found in namespace {metricNamespace}, skipping."); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Build a single-widget dashboard body that charts the given metric. /// </summary> /// <param name="metricNamespace">The namespace of the metric to chart.</param> /// <param name="metric">The metric to chart.</param> /// <param name="region">The region the metric is in. A metric widget must name its /// region, because a dashboard can chart metrics from several.</param> internal static string BuildDashboardBody(string metricNamespace, Metric metric, string region) { var dimensionParts = string.Concat( metric.Dimensions.Select(d => $", \"{d.Name}\", \"{d.Value}\"")); return $@"{{ ""widgets"": [ {{ ""type"": ""text"", ""x"": 0, ""y"": 0, ""width"": 24, ""height"": 2, ""properties"": {{ ""markdown"": ""This dashboard was created programmatically by an AWS SDK code example."" }} }}, {{ ""type"": ""metric"", ""x"": 0, ""y"": 2, ""width"": 12, ""height"": 6, ""properties"": {{ ""metrics"": [[ ""{metricNamespace}"", ""{metric.MetricName}""{dimensionParts} ]], ""view"": ""timeSeries"", ""stat"": ""Average"", ""period"": 300, ""region"": ""{region}"", ""title"": ""{metric.MetricName}"" }} }} ] }}"; } /// <summary> /// Create a mute rule so the alarm's actions are suppressed during a maintenance /// window, then read it back and find it in the account's rules. /// </summary> private static async Task MuteAlarmForMaintenance() { Console.WriteLine(new string('-', 80)); Console.WriteLine("7. Mute the alarm for a maintenance window"); Console.WriteLine( "\nWhile a mute rule is active the targeted alarms keep evaluating and keep changing" + "\nstate, but their actions do not fire. This is the supported way to suppress" + "\nnotifications during planned maintenance, instead of disabling alarm actions and" + "\nhoping someone remembers to turn them back on.\n"); // The expression is a five-field cron expression, // cron(Minutes Hours Day-of-month Month Day-of-week). Note that this is five fields, // not the six that Amazon EventBridge uses. For a one-time window, use // at(yyyy-MM-ddThh:mm), with no seconds. The duration is an ISO 8601 duration from // PT1M to P15D, so PT2H rather than 2h. const string expression = "cron(0 2 * * SUN)"; const string duration = "PT2H"; const string timezone = "America/Los_Angeles"; await _otelWrapper.PutAlarmMuteRule(_muteRuleName, expression, duration, timezone, new List<string> { _alarmName }); Console.WriteLine($"\tCreated mute rule {_muteRuleName}:"); Console.WriteLine($"\t schedule: {expression} for {duration}"); Console.WriteLine($"\t timezone: {timezone}"); Console.WriteLine($"\t targets: {_alarmName}"); Console.WriteLine( "\n\tNote the two formats here. The expression is a five-field cron expression, five" + "\n\trather than the six Amazon EventBridge uses. The duration is an ISO 8601" + "\n\tduration, so 'PT2H' and not '2h'." + "\n" + "\n\tAlso note that MuteTargets is set explicitly. If you leave it out, the rule" + "\n\tapplies to every alarm in the account."); var muteRule = await _otelWrapper.GetAlarmMuteRule(_muteRuleName); Console.WriteLine( $"\tRead the rule back: status {muteRule.Status}, mute type {muteRule.MuteType}."); var summaries = await _otelWrapper.ListAlarmMuteRules(_alarmName); Console.WriteLine($"\tFound {summaries.Count} mute rules targeting this alarm."); // Mute rule summaries carry no name field, only an ARN, so match on the ARN suffix. var match = summaries.FirstOrDefault(s => s.AlarmMuteRuleArn.EndsWith($"/{_muteRuleName}") || s.AlarmMuteRuleArn.EndsWith($":{_muteRuleName}")); if (match != null) { Console.WriteLine($"\t matched by ARN: {match.AlarmMuteRuleArn} ({match.Status})"); } Console.WriteLine(new string('-', 80)); } /// <summary> /// Delete the resources the scenario created. Each deletion is attempted independently /// so that one failure does not leave the remaining resources behind. /// </summary> private static async Task CleanUp() { Console.WriteLine(new string('-', 80)); Console.WriteLine("8. Clean up"); Console.WriteLine("\nDelete the resources this scenario created? (y/n)"); var response = Console.ReadLine(); if (!string.Equals(response?.Trim(), "y", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine( "\tSkipping cleanup. Note that the alarm, dashboard, and mute rule are still in" + "\n\tyour account, and enrichment may still be running."); Console.WriteLine(new string('-', 80)); return; } try { await _otelWrapper.DeleteAlarmMuteRule(_muteRuleName); Console.WriteLine($"\tDeleted mute rule {_muteRuleName}."); } catch (Exception ex) { Console.WriteLine($"\tCould not delete the mute rule: {ex.Message}"); } try { await _cloudWatchWrapper.DeleteAlarms(new List<string> { _alarmName }); Console.WriteLine($"\tDeleted alarm {_alarmName}."); } catch (Exception ex) { Console.WriteLine($"\tCould not delete the alarm: {ex.Message}"); } if (_dashboardCreated) { try { await _cloudWatchWrapper.DeleteDashboards(new List<string> { _dashboardName }); Console.WriteLine($"\tDeleted dashboard {_dashboardName}."); } catch (Exception ex) { Console.WriteLine($"\tCould not delete the dashboard: {ex.Message}"); } } if (_startedEnrichment) { try { await _otelWrapper.StopOTelEnrichment(); Console.WriteLine("\tStopped OTel enrichment, because this run started it."); } catch (Exception ex) { Console.WriteLine($"\tCould not stop OTel enrichment: {ex.Message}"); } } else { Console.WriteLine( "\tLeft OTel enrichment running, because it was already on before this run."); } Console.WriteLine(new string('-', 80)); } }Métodos de encapsulación utilizados por el escenario para las CloudWatch OpenTelemetry acciones.
/// <summary> /// Wrapper class for the OpenTelemetry features of Amazon CloudWatch: turning on OTel /// enrichment so that CloudWatch vended metrics are queryable with PromQL, alarming on a /// PromQL query, inspecting the individual series (contributors) that put a PromQL alarm /// into ALARM, and muting alarm actions on a schedule. /// /// Note that OTLP metric ingestion is not an AWS SDK operation. To send OpenTelemetry /// metrics to CloudWatch, point an OpenTelemetry collector or the AWS Distro for /// OpenTelemetry (ADOT) SDK at the CloudWatch OTLP metrics endpoint, /// https://monitoring.{region}.amazonaws.com/v1/metrics. The operations here cover /// everything you do after those metrics land in CloudWatch. /// </summary> public class CloudWatchOTelWrapper { private readonly IAmazonCloudWatch _amazonCloudWatch; private readonly ILogger<CloudWatchOTelWrapper> _logger; /// <summary> /// Constructor for the CloudWatch OpenTelemetry wrapper. /// </summary> /// <param name="amazonCloudWatch">The injected CloudWatch client.</param> /// <param name="logger">The injected logger for the wrapper.</param> public CloudWatchOTelWrapper(IAmazonCloudWatch amazonCloudWatch, ILogger<CloudWatchOTelWrapper> logger) { _logger = logger; _amazonCloudWatch = amazonCloudWatch; }Métodos de encapsulación utilizados por el escenario para las acciones de métrica, estadística y panel.
/// <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, StartTime = DateTime.UtcNow.AddDays(-days), EndTime = DateTime.UtcNow, Period = period }); return metricStatistics.Datapoints ?? new List<Datapoint>(); } /// <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 ?? new List<DashboardValidationMessage>(); } /// <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}"; // Add the plus sign for positive offsets. timeZoneString = timeZoneString.StartsWith('-') ? timeZoneString : "+" + timeZoneString; var paginatedMetricData = _amazonCloudWatch.Paginators.GetMetricData( new GetMetricDataRequest() { StartTime = startTimeUtc, EndTime = endDateUtc.Value, LabelOptions = new LabelOptions { Timezone = timeZoneString }, ScanBy = useDescendingTime ? ScanBy.TimestampDescending : ScanBy.TimestampAscending, MaxDatapoints = maxDataPoints, MetricDataQueries = dataQueries, }); if (paginatedMetricData.MetricDataResults != null) { 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 ?? new List<MetricAlarm>(); } /// <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, EndDate = DateTime.UtcNow, HistoryItemType = HistoryItemType.StateUpdate, StartDate = 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; } }Ejemplo de valores de settings.json para este escenario:
{ "dashboardName": "example-new-dashboard", "exampleAlarmName": "example-metric-alarm", "accountId": "1234567890", "region": "us-east-1", "emailTopic": "Default_CloudWatch_Alarms_Topic", "customMetricNamespace": "example-namespace", "customMetricName": "example-custom-metric", "dashboardExampleBody": { "widgets": [ { "height": 6, "width": 6, "y": 0, "x": 0, "type": "text", "properties": { "markdown": "# Code Example Dashboard \nThis dashboard was created by example code.\n" } }, { "height": 8, "width": 8, "y": 0, "x": 6, "type": "metric", "properties": { "metrics": [ [ "AWS/Billing", "EstimatedCharges", "Currency", "USD", { "region": "us-east-1" } ] ], "view": "timeSeries", "region": "us-east-1", "stat": "Maximum", "period": 86400, "yAxis": { "left": { "min": 0, "max": 100 } }, "stacked": false, "title": "Estimated Billing", "setPeriodToTimeRange": false, "liveData": true, "sparkline": true, "trend": true } }, { "height": 8, "width": 8, "y": 0, "x": 14, "type": "metric", "properties": { "metrics": [ [ "AWS/Usage", "CallCount", "Type", "API", "Resource", "ListMetrics", "Service", "CloudWatch", "Class", "None" ], [ "...", "GetMetricStatistics", ".", ".", ".", "." ], [ "...", "GetMetricData", ".", ".", ".", "." ], [ "...", "PutDashboard", ".", ".", ".", "." ], [ "...", "PutMetricData", ".", ".", ".", "." ] ], "view": "timeSeries", "yAxis": { "left": { "min": 0, "max": 200 } }, "stacked": false, "region": "us-east-1", "stat": "Sum", "period": 300, "title": "CloudWatch Usage", "setPeriodToTimeRange": false, "liveData": true, "sparkline": true, "trend": true } } ] } }-
Para obtener detalles sobre la API, consulte los siguientes temas en la Referencia de la API de AWS SDK para .NET .
-
Acciones
En el siguiente ejemplo de código, se muestra cómo utilizar DeleteAlarmMuteRule.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Delete an alarm mute rule. The alarms it targeted resume firing their actions. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAlarmMuteRule(string name) { var response = await _amazonCloudWatch.DeleteAlarmMuteRuleAsync( new DeleteAlarmMuteRuleRequest { AlarmMuteRuleName = name }); _logger.LogInformation($"Deleted alarm mute rule {name}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }-
Para obtener más información sobre la API, consulta DeleteAlarmMuteRule la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DeleteAlarms.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DeleteAlarms la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DeleteAnomalyDetector.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DeleteAnomalyDetector la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DeleteDashboards.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DeleteDashboards la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DescribeAlarmContributors.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Get the contributors for a PromQL alarm. Each contributor is one series that the /// alarm's query matched, identified by its label set. This is how you find out which /// hosts, services, or pods are breaching, rather than only that something is. /// </summary> /// <param name="alarmName">The name of the PromQL alarm.</param> /// <returns>The list of contributors.</returns> public async Task<List<AlarmContributor>> DescribeAlarmContributors(string alarmName) { var results = new List<AlarmContributor>(); string? nextToken = null; do { var response = await _amazonCloudWatch.DescribeAlarmContributorsAsync( new DescribeAlarmContributorsRequest { AlarmName = alarmName, NextToken = nextToken }); if (response.AlarmContributors != null) { results.AddRange(response.AlarmContributors); } nextToken = response.NextToken; } while (!string.IsNullOrEmpty(nextToken)); _logger.LogInformation($"Got {results.Count} contributors for alarm {alarmName}."); return results; }-
Para obtener más información sobre la API, consulta DescribeAlarmContributors la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DescribeAlarmHistory.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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, EndDate = DateTime.UtcNow, HistoryItemType = HistoryItemType.StateUpdate, StartDate = DateTime.UtcNow.AddDays(-historyDays) }); await foreach (var data in paginatedAlarmHistory.AlarmHistoryItems) { alarmHistory.Add(data); } return alarmHistory; }-
Para obtener más información sobre la API, consulta DescribeAlarmHistory la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DescribeAlarms.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DescribeAlarms la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DescribeAlarmsForMetric.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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 ?? new List<MetricAlarm>(); }-
Para obtener más información sobre la API, consulta DescribeAlarmsForMetric la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DescribeAnomalyDetectors.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DescribeAnomalyDetectors la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar DisableAlarmActions.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta DisableAlarmActions la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar EnableAlarmActions.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta EnableAlarmActions la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetAlarmMuteRule.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Get the full configuration of an alarm mute rule, including its schedule, the /// alarms it targets, and whether it is currently SCHEDULED, ACTIVE, or EXPIRED. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <returns>The mute rule.</returns> public async Task<GetAlarmMuteRuleResponse> GetAlarmMuteRule(string name) { var response = await _amazonCloudWatch.GetAlarmMuteRuleAsync( new GetAlarmMuteRuleRequest { AlarmMuteRuleName = name }); _logger.LogInformation($"Mute rule {response.Name} is {response.Status}."); return response; }-
Para obtener más información sobre la API, consulta GetAlarmMuteRule la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetDashboard.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta GetDashboard la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetMetricData.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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}"; // Add the plus sign for positive offsets. timeZoneString = timeZoneString.StartsWith('-') ? timeZoneString : "+" + timeZoneString; var paginatedMetricData = _amazonCloudWatch.Paginators.GetMetricData( new GetMetricDataRequest() { StartTime = startTimeUtc, EndTime = endDateUtc.Value, LabelOptions = new LabelOptions { Timezone = timeZoneString }, ScanBy = useDescendingTime ? ScanBy.TimestampDescending : ScanBy.TimestampAscending, MaxDatapoints = maxDataPoints, MetricDataQueries = dataQueries, }); if (paginatedMetricData.MetricDataResults != null) { await foreach (var data in paginatedMetricData.MetricDataResults) { metricData.Add(data); } } return metricData; }-
Para obtener más información sobre la API, consulta GetMetricData la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetMetricStatistics.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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, StartTime = DateTime.UtcNow.AddDays(-days), EndTime = DateTime.UtcNow, Period = period }); return metricStatistics.Datapoints ?? new List<Datapoint>(); }-
Para obtener más información sobre la API, consulta GetMetricStatistics la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetMetricWidgetImage.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta GetMetricWidgetImage la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar GetOTelEnrichment.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Get the current OTel enrichment status for the account. /// </summary> /// <returns>The status, either Running or Stopped.</returns> public async Task<OTelEnrichmentStatus> GetOTelEnrichmentStatus() { var response = await _amazonCloudWatch.GetOTelEnrichmentAsync( new GetOTelEnrichmentRequest()); _logger.LogInformation($"OTel enrichment status is {response.Status}."); return response.Status; }-
Para obtener más información sobre la API, consulta GetOTelEnrichment la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar ListAlarmMuteRules.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// List the alarm mute rules in the account, optionally filtered to the rules that /// target one alarm. /// </summary> /// <param name="alarmName">When specified, only rules that target this alarm are /// returned.</param> /// <returns>The list of mute rule summaries.</returns> public async Task<List<AlarmMuteRuleSummary>> ListAlarmMuteRules(string? alarmName = null) { var results = new List<AlarmMuteRuleSummary>(); string? nextToken = null; do { var response = await _amazonCloudWatch.ListAlarmMuteRulesAsync( new ListAlarmMuteRulesRequest { AlarmName = alarmName, NextToken = nextToken }); if (response.AlarmMuteRuleSummaries != null) { results.AddRange(response.AlarmMuteRuleSummaries); } nextToken = response.NextToken; } while (!string.IsNullOrEmpty(nextToken)); _logger.LogInformation($"Got {results.Count} alarm mute rules."); return results; }-
Para obtener más información sobre la API, consulta ListAlarmMuteRules la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar ListDashboards.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta ListDashboards la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar ListMetrics.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta ListMetrics la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar PutAlarmMuteRule.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Create or update an alarm mute rule. While a mute rule is active the targeted /// alarms keep evaluating and keep transitioning between states, but their configured /// actions do not fire. This is the supported way to suppress notifications during a /// known maintenance window, instead of disabling alarm actions and relying on /// someone to turn them back on. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <param name="expression">When the rule activates. For a recurring window, use a /// five-field cron expression, cron(Minutes Hours Day-of-month Month Day-of-week), /// such as cron(0 2 * * SUN) for every Sunday at 2:00 AM. Note that this is five /// fields, not the six that Amazon EventBridge uses. For a one-time window, use /// at(yyyy-MM-ddThh:mm), such as at(2026-09-05T02:00).</param> /// <param name="duration">How long the mute window lasts once it activates, in /// ISO 8601 duration format, from PT1M (one minute) to P15D (15 days). For example, /// PT2H is two hours and P2DT12H is two days and 12 hours.</param> /// <param name="timezone">The time zone the expression is evaluated in, such as /// America/Los_Angeles.</param> /// <param name="alarmNames">The names of up to 100 alarms to mute. If null or empty, /// the rule applies to all alarms in the account.</param> /// <returns>True if successful.</returns> public async Task<bool> PutAlarmMuteRule(string name, string expression, string duration, string timezone, List<string>? alarmNames = null) { var request = new PutAlarmMuteRuleRequest { Name = name, Description = "A mute rule created by the AWS SDK for .NET example.", Rule = new Rule { Schedule = new Schedule { Expression = expression, Duration = duration, Timezone = timezone } } }; if (alarmNames != null && alarmNames.Any()) { request.MuteTargets = new MuteTargets { AlarmNames = alarmNames }; } var response = await _amazonCloudWatch.PutAlarmMuteRuleAsync(request); _logger.LogInformation($"Put alarm mute rule {name}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }-
Para obtener más información sobre la API, consulta PutAlarmMuteRule la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar PutAnomalyDetector.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta PutAnomalyDetector la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar PutDashboard.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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 ?? new List<DashboardValidationMessage>(); }-
Para obtener más información sobre la API, consulta PutDashboard la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar PutMetricAlarm.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. Crea una alarma que evalúe una consulta de PromQL comparándola con las métricas. OpenTelemetry
/// <summary> /// Create an alarm that evaluates a PromQL query. /// /// A PromQL alarm differs from a classic metric alarm in a few ways. The query can /// match many series at once, and each matching series is tracked separately as a /// contributor. Instead of counting breaching periods, you specify durations: a /// contributor moves to ALARM after it breaches continuously for the pending period, /// and back to OK after it stops breaching for the recovery period. A PromQL alarm /// starts in the OK state rather than INSUFFICIENT_DATA. /// /// EvaluationCriteria is a union and is mutually exclusive with the classic /// MetricName and Metrics properties. When you use it you must also set /// EvaluationInterval, and you must not set Period, Statistic, Threshold, /// ComparisonOperator, EvaluationPeriods, DatapointsToAlarm, or TreatMissingData. /// </summary> /// <param name="alarmName">The name of the alarm, unique within the Region.</param> /// <param name="query">The PromQL query to evaluate, such as /// avg(cpu_utilization_percent) > 80. The comparison belongs in the query itself; /// there is no separate threshold property.</param> /// <param name="evaluationInterval">How often, in seconds, to run the query. Valid /// values are 10, 20, 30, and any multiple of 60, up to 3600.</param> /// <param name="pendingPeriod">How long, in seconds, a contributor must breach /// continuously before it moves to ALARM.</param> /// <param name="recoveryPeriod">How long, in seconds, a contributor must stop /// breaching before it moves back to OK.</param> /// <returns>True if successful.</returns> public async Task<bool> PutPromQLMetricAlarm(string alarmName, string query, int evaluationInterval = 60, int pendingPeriod = 300, int recoveryPeriod = 120) { var response = await _amazonCloudWatch.PutMetricAlarmAsync( new PutMetricAlarmRequest { AlarmName = alarmName, AlarmDescription = "A PromQL alarm created by the AWS SDK for .NET example.", EvaluationCriteria = new EvaluationCriteria { PromQLCriteria = new AlarmPromQLCriteria { Query = query, PendingPeriod = pendingPeriod, RecoveryPeriod = recoveryPeriod } }, EvaluationInterval = evaluationInterval }); _logger.LogInformation($"Created PromQL alarm {alarmName} for query {query}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }Cree una alarma que evalúe una sola métrica. CloudWatch
/// <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; }-
Para obtener más información sobre la API, consulte PutMetricAlarm la Referencia AWS SDK para .NET de API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar PutMetricData.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <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; }-
Para obtener más información sobre la API, consulta PutMetricData la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar StartOTelEnrichment.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Turn on OTel enrichment for the account. Once enrichment is running, CloudWatch /// vended metrics that carry a resource identifier dimension, such as the Amazon EC2 /// CPUUtilization metric with its InstanceId dimension, are decorated with resource /// ARN and resource tag labels and become queryable with PromQL. /// /// Resource tags on telemetry must already be enabled for the account before you /// call this operation. /// </summary> /// <returns>True if successful.</returns> public async Task<bool> StartOTelEnrichment() { var response = await _amazonCloudWatch.StartOTelEnrichmentAsync( new StartOTelEnrichmentRequest()); _logger.LogInformation("Started OTel enrichment for this account."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }-
Para obtener más información sobre la API, consulta StartOTelEnrichment la Referencia de AWS SDK para .NET API.
-
En el siguiente ejemplo de código, se muestra cómo utilizar StopOTelEnrichment.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. /// <summary> /// Turn off OTel enrichment for the account. Existing PromQL alarms are not deleted, /// but vended metrics stop being enriched with resource ARN and tag labels, so /// queries that select on those labels stop matching. /// </summary> /// <returns>True if successful.</returns> public async Task<bool> StopOTelEnrichment() { var response = await _amazonCloudWatch.StopOTelEnrichmentAsync( new StopOTelEnrichmentRequest()); _logger.LogInformation("Stopped OTel enrichment for this account."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }-
Para obtener más información sobre la API, consulta StopOTelEnrichment la Referencia de AWS SDK para .NET API.
-
Escenarios
En el siguiente ejemplo de código, se muestra cómo:
Envíe las métricas de OTLP al punto final de CloudWatch métricas con un recopilador. OpenTelemetry
Comience con OpenTelemetry el enriquecimiento de modo que CloudWatch correlacione esas métricas con sus recursos.
Cree una alarma que evalúe una consulta de PromQL en cada serie que devuelva la consulta.
Inspeccione las series individuales, denominadas contribuidoras, que pusieron la alarma en estado de ALARMA.
Silencia la alarma durante un período de mantenimiento y, a continuación, límpiala.
- SDK para .NET (v4)
-
nota
Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de AWS
. Métodos envolventes para las CloudWatch OpenTelemetry acciones.
/// <summary> /// Wrapper class for the OpenTelemetry features of Amazon CloudWatch: turning on OTel /// enrichment so that CloudWatch vended metrics are queryable with PromQL, alarming on a /// PromQL query, inspecting the individual series (contributors) that put a PromQL alarm /// into ALARM, and muting alarm actions on a schedule. /// /// Note that OTLP metric ingestion is not an AWS SDK operation. To send OpenTelemetry /// metrics to CloudWatch, point an OpenTelemetry collector or the AWS Distro for /// OpenTelemetry (ADOT) SDK at the CloudWatch OTLP metrics endpoint, /// https://monitoring.{region}.amazonaws.com/v1/metrics. The operations here cover /// everything you do after those metrics land in CloudWatch. /// </summary> public class CloudWatchOTelWrapper { private readonly IAmazonCloudWatch _amazonCloudWatch; private readonly ILogger<CloudWatchOTelWrapper> _logger; /// <summary> /// Constructor for the CloudWatch OpenTelemetry wrapper. /// </summary> /// <param name="amazonCloudWatch">The injected CloudWatch client.</param> /// <param name="logger">The injected logger for the wrapper.</param> public CloudWatchOTelWrapper(IAmazonCloudWatch amazonCloudWatch, ILogger<CloudWatchOTelWrapper> logger) { _logger = logger; _amazonCloudWatch = amazonCloudWatch; } /// <summary> /// Turn on OTel enrichment for the account. Once enrichment is running, CloudWatch /// vended metrics that carry a resource identifier dimension, such as the Amazon EC2 /// CPUUtilization metric with its InstanceId dimension, are decorated with resource /// ARN and resource tag labels and become queryable with PromQL. /// /// Resource tags on telemetry must already be enabled for the account before you /// call this operation. /// </summary> /// <returns>True if successful.</returns> public async Task<bool> StartOTelEnrichment() { var response = await _amazonCloudWatch.StartOTelEnrichmentAsync( new StartOTelEnrichmentRequest()); _logger.LogInformation("Started OTel enrichment for this account."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; } /// <summary> /// Get the current OTel enrichment status for the account. /// </summary> /// <returns>The status, either Running or Stopped.</returns> public async Task<OTelEnrichmentStatus> GetOTelEnrichmentStatus() { var response = await _amazonCloudWatch.GetOTelEnrichmentAsync( new GetOTelEnrichmentRequest()); _logger.LogInformation($"OTel enrichment status is {response.Status}."); return response.Status; } /// <summary> /// Create an alarm that evaluates a PromQL query. /// /// A PromQL alarm differs from a classic metric alarm in a few ways. The query can /// match many series at once, and each matching series is tracked separately as a /// contributor. Instead of counting breaching periods, you specify durations: a /// contributor moves to ALARM after it breaches continuously for the pending period, /// and back to OK after it stops breaching for the recovery period. A PromQL alarm /// starts in the OK state rather than INSUFFICIENT_DATA. /// /// EvaluationCriteria is a union and is mutually exclusive with the classic /// MetricName and Metrics properties. When you use it you must also set /// EvaluationInterval, and you must not set Period, Statistic, Threshold, /// ComparisonOperator, EvaluationPeriods, DatapointsToAlarm, or TreatMissingData. /// </summary> /// <param name="alarmName">The name of the alarm, unique within the Region.</param> /// <param name="query">The PromQL query to evaluate, such as /// avg(cpu_utilization_percent) > 80. The comparison belongs in the query itself; /// there is no separate threshold property.</param> /// <param name="evaluationInterval">How often, in seconds, to run the query. Valid /// values are 10, 20, 30, and any multiple of 60, up to 3600.</param> /// <param name="pendingPeriod">How long, in seconds, a contributor must breach /// continuously before it moves to ALARM.</param> /// <param name="recoveryPeriod">How long, in seconds, a contributor must stop /// breaching before it moves back to OK.</param> /// <returns>True if successful.</returns> public async Task<bool> PutPromQLMetricAlarm(string alarmName, string query, int evaluationInterval = 60, int pendingPeriod = 300, int recoveryPeriod = 120) { var response = await _amazonCloudWatch.PutMetricAlarmAsync( new PutMetricAlarmRequest { AlarmName = alarmName, AlarmDescription = "A PromQL alarm created by the AWS SDK for .NET example.", EvaluationCriteria = new EvaluationCriteria { PromQLCriteria = new AlarmPromQLCriteria { Query = query, PendingPeriod = pendingPeriod, RecoveryPeriod = recoveryPeriod } }, EvaluationInterval = evaluationInterval }); _logger.LogInformation($"Created PromQL alarm {alarmName} for query {query}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; } /// <summary> /// Get the contributors for a PromQL alarm. Each contributor is one series that the /// alarm's query matched, identified by its label set. This is how you find out which /// hosts, services, or pods are breaching, rather than only that something is. /// </summary> /// <param name="alarmName">The name of the PromQL alarm.</param> /// <returns>The list of contributors.</returns> public async Task<List<AlarmContributor>> DescribeAlarmContributors(string alarmName) { var results = new List<AlarmContributor>(); string? nextToken = null; do { var response = await _amazonCloudWatch.DescribeAlarmContributorsAsync( new DescribeAlarmContributorsRequest { AlarmName = alarmName, NextToken = nextToken }); if (response.AlarmContributors != null) { results.AddRange(response.AlarmContributors); } nextToken = response.NextToken; } while (!string.IsNullOrEmpty(nextToken)); _logger.LogInformation($"Got {results.Count} contributors for alarm {alarmName}."); return results; } /// <summary> /// Create or update an alarm mute rule. While a mute rule is active the targeted /// alarms keep evaluating and keep transitioning between states, but their configured /// actions do not fire. This is the supported way to suppress notifications during a /// known maintenance window, instead of disabling alarm actions and relying on /// someone to turn them back on. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <param name="expression">When the rule activates. For a recurring window, use a /// five-field cron expression, cron(Minutes Hours Day-of-month Month Day-of-week), /// such as cron(0 2 * * SUN) for every Sunday at 2:00 AM. Note that this is five /// fields, not the six that Amazon EventBridge uses. For a one-time window, use /// at(yyyy-MM-ddThh:mm), such as at(2026-09-05T02:00).</param> /// <param name="duration">How long the mute window lasts once it activates, in /// ISO 8601 duration format, from PT1M (one minute) to P15D (15 days). For example, /// PT2H is two hours and P2DT12H is two days and 12 hours.</param> /// <param name="timezone">The time zone the expression is evaluated in, such as /// America/Los_Angeles.</param> /// <param name="alarmNames">The names of up to 100 alarms to mute. If null or empty, /// the rule applies to all alarms in the account.</param> /// <returns>True if successful.</returns> public async Task<bool> PutAlarmMuteRule(string name, string expression, string duration, string timezone, List<string>? alarmNames = null) { var request = new PutAlarmMuteRuleRequest { Name = name, Description = "A mute rule created by the AWS SDK for .NET example.", Rule = new Rule { Schedule = new Schedule { Expression = expression, Duration = duration, Timezone = timezone } } }; if (alarmNames != null && alarmNames.Any()) { request.MuteTargets = new MuteTargets { AlarmNames = alarmNames }; } var response = await _amazonCloudWatch.PutAlarmMuteRuleAsync(request); _logger.LogInformation($"Put alarm mute rule {name}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; } /// <summary> /// Get the full configuration of an alarm mute rule, including its schedule, the /// alarms it targets, and whether it is currently SCHEDULED, ACTIVE, or EXPIRED. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <returns>The mute rule.</returns> public async Task<GetAlarmMuteRuleResponse> GetAlarmMuteRule(string name) { var response = await _amazonCloudWatch.GetAlarmMuteRuleAsync( new GetAlarmMuteRuleRequest { AlarmMuteRuleName = name }); _logger.LogInformation($"Mute rule {response.Name} is {response.Status}."); return response; } /// <summary> /// List the alarm mute rules in the account, optionally filtered to the rules that /// target one alarm. /// </summary> /// <param name="alarmName">When specified, only rules that target this alarm are /// returned.</param> /// <returns>The list of mute rule summaries.</returns> public async Task<List<AlarmMuteRuleSummary>> ListAlarmMuteRules(string? alarmName = null) { var results = new List<AlarmMuteRuleSummary>(); string? nextToken = null; do { var response = await _amazonCloudWatch.ListAlarmMuteRulesAsync( new ListAlarmMuteRulesRequest { AlarmName = alarmName, NextToken = nextToken }); if (response.AlarmMuteRuleSummaries != null) { results.AddRange(response.AlarmMuteRuleSummaries); } nextToken = response.NextToken; } while (!string.IsNullOrEmpty(nextToken)); _logger.LogInformation($"Got {results.Count} alarm mute rules."); return results; } /// <summary> /// Delete an alarm mute rule. The alarms it targeted resume firing their actions. /// </summary> /// <param name="name">The name of the mute rule.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteAlarmMuteRule(string name) { var response = await _amazonCloudWatch.DeleteAlarmMuteRuleAsync( new DeleteAlarmMuteRuleRequest { AlarmMuteRuleName = name }); _logger.LogInformation($"Deleted alarm mute rule {name}."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; } /// <summary> /// Turn off OTel enrichment for the account. Existing PromQL alarms are not deleted, /// but vended metrics stop being enriched with resource ARN and tag labels, so /// queries that select on those labels stop matching. /// </summary> /// <returns>True if successful.</returns> public async Task<bool> StopOTelEnrichment() { var response = await _amazonCloudWatch.StopOTelEnrichmentAsync( new StopOTelEnrichmentRequest()); _logger.LogInformation("Stopped OTel enrichment for this account."); return response.HttpStatusCode == System.Net.HttpStatusCode.OK; }-
Para obtener detalles sobre la API, consulte los siguientes temas en la Referencia de la API de AWS SDK para .NET .
-