

# Query your CloudWatch metrics with CloudWatch Metrics Insights
Query metrics with CloudWatch Metrics Insights

CloudWatch Metrics Insights is a powerful high-performance SQL query engine that you can use to query your metrics at scale. You can identify trends and patterns within all of your CloudWatch metrics in real time, with access to up to two weeks of historical data for comprehensive trend analysis.

You can also set alarms on any Metrics Insights queries that return a single time series. This can be especially useful to create alarms that watch aggregated metrics across a fleet of your infrastructure or applications. Create the alarm once, and it dynamically adjusts as resources are added to or removed from the fleet.

 You can perform a CloudWatch Metrics Insights query in the console with the CloudWatch Metrics Insights query editor. You can also perform a CloudWatch Metrics Insights query with the AWS CLI or an AWS SDK by running `GetMetricData` or `PutDashboard`. There's no charge for queries that you run with the CloudWatch Metrics Insights query editor. For more information about CloudWatch pricing, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/). 

 With the CloudWatch Metrics Insights query editor, you can choose from a variety of prebuilt sample queries and also create your own queries. As you create your queries, you can use a builder view to browse your existing metrics and dimensions. Alternatively, use an editor view to manually write queries. 

With Metrics Insights, you can run queries at scale. With the **GROUP BY** clause, you can group your metrics in real time into separate time series per specific dimension value. Because Metrics Insights queries include an **ORDER BY** ability, you can use Metrics Insights to make "Top N" type queries. For example, "Top N" type queries can scan millions of metrics in your account and return the 10 instances that consume the most CPU. This can help you pinpoint and remedy latency issues in your applications. To use tags with alarms, opt in through CloudWatch Settings. After tags is enabled, you can also filter and group metrics using AWS resource tags, enabling you to query metrics aligned with your organizational structure, such as by application, environment, or team.

**Topics**
+ [

# Building your queries in CloudWatch Metrics Insights
](cloudwatch-metrics-insights-buildquery.md)
+ [

# Query components and syntax in CloudWatch Metrics Insights
](cloudwatch-metrics-insights-querylanguage.md)
+ [

# Alarms on CloudWatch Metrics Insights queries in CloudWatch
](cloudwatch-metrics-insights-alarms.md)
+ [

# Use Metrics Insights queries with metric math
](cloudwatch-metrics-insights-math.md)
+ [

# Use natural language to generate and update CloudWatch Metrics Insights queries
](cloudwatch-metrics-insights-query-assist.md)
+ [

# SQL inference
](cloudwatch-metrics-insights-inference.md)
+ [

# Metrics Insights quotas
](cloudwatch-metrics-insights-limits.md)
+ [

# Metrics Insights sample queries
](cloudwatch-metrics-insights-queryexamples.md)
+ [

# Metrics Insights glossary
](cloudwatch-metrics-insights-glossary.md)
+ [

# Troubleshooting Metrics Insights
](cloudwatch-metrics-insights-troubleshooting.md)

# Building your queries in CloudWatch Metrics Insights
Building queries

You can run a CloudWatch Metrics Insights query using the CloudWatch console, the AWS CLI, or the AWS SDKs. Queries run in the console are free of charge. For more information about CloudWatch pricing, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/).

With CloudWatch Metrics Insights, you can analyze metric data across extended time periods of up to two weeks, allowing for more comprehensive historical analysis and trend identification compared to shorter retention periods. For optimal performance when querying longer time ranges, consider using larger periods (such as 5 minutes or 1 hour) to reduce the number of data points returned. When analyzing trends over the full two-week period, use aggregate functions like AVG() or MAX() in your ORDER BY clauses to efficiently identify patterns.

For more information about using the AWS SDKs to perform a Metrics Insights query, see [GetMetricData](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricData.html).

To run a query using the CloudWatch console, follow these steps:

**To query your metrics using Metrics Insights**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. In the navigation pane, choose **Metrics**, **All metrics**.

1. (Optional) To run a pre-built sample query, choose **Add query** and select the query to run. If you are satisfied with this query, you can skip the rest of this procedure. Or, you can choose **Editor** to edit the sample query and then choose **Run** to run the modified query. 

1. To create your own query, choose **Multi source query**. You can then use the **Builder** view (default) to get a guided experience, or the **Editor** view if you prefer to see the query syntax. You can switch between the two views anytime and see your work in progress in both views. 

   In the **Builder** view, click on the namespace, metric name, filter, group, order, and limit fields to browse and select possible values. You can start typing any part of the value you are looking for to filter the list presented by the builder. You can reference resource tags in the filter and group inputs.

   In the **Editor** view, you can write the query using the subset of SQL supported by Metrics Insights. The editor offers auto-complete options based on the characters you have typed so far, including name of resource tags for metrics that support them.

   CloudWatch Metrics Insights supports querying metrics by AWS resource tags. You can use tags to filter and group your metric data for more targeted monitoring and analysis.

   The following examples shows how you can use queries with tags.

   To see the CPU utilization for Amazon EC2 instances within your production environment:

   ```
   SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2") WHERE tag.env='prod'
   ```

   To group the metrics by environment using the GROUP BY clause:

   ```
   SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2") GROUP BY tag.env
   ```

   To use the GROUP BY clause where you specify the tag name:

   ```
   SELECT AVG(CPUUtilization) FROM "AWS/EC2" GROUP BY tag."aws:cloudformation:stack-name"
   ```

   To combine tag queries with existing metric dimensions:

   ```
   SELECT MAX(CPUUtilization) FROM SCHEMA("AWS/EC2") WHERE tag.env='prod' AND InstanceId='i-1234567890abcdef0'
   ```

1. When you are satisfied with your query, choose **Run**.

1. (Optional) Another way to edit a query that you have graphed is to choose the **Graphed metrics** tab and choose the edit icon next to the query formula in the **Details** column.

1. (Optional) To remove a query from the graph, choose **Graphed metrics** and choose the **X** icon at the right side of the row that displays your query.

# Query components and syntax in CloudWatch Metrics Insights
Query components and syntax

CloudWatch Metrics Insights syntax is as follows.

```
SELECT FUNCTION(metricName)
FROM namespace | SCHEMA(...)
[ WHERE labelKey OPERATOR labelValue [AND ... ] ]
[ GROUP BY labelKey [ , ... ] ]
[ ORDER BY FUNCTION() [ DESC | ASC ] ]
[ LIMIT number ]
```

The possible clauses in a Metrics Insights query are as follows. None of the keywords are case sensitive, but the identifiers such as the names of metrics, namespaces, and dimensions are case sensitive.

**SELECT**  
Required. Specifies the function to use to aggregate observations in each time bucket (determined by the provided period). Also specifies the name of the metric to query.  
The valid values for **FUNCTION** are `AVG`, `COUNT`, `MAX`, `MIN`, and `SUM`.  
+ `AVG` calculates the average of the observations matched by the query.
+ `COUNT` returns the count of the observations matched by the query.
+ `MAX` returns the maximum value of the observations matched by the query.
+ `MIN` returns the minimum value of the observations matched by the query.
+ `SUM` calculates the sum of the observations matched by the query.

**FROM**  
Required. Specifies the source of the metric. You can specify either the metric namespace that contains the metric that is to be queried, or a **SCHEMA** table function. Examples of metric namespaces include `"AWS/EC2"`, `"AWS/Lambda"`, and metric namespaces that you have created for your custom metrics.  
Metric namespaces that include **/** or any other character that is not a letter, number, or underscore must be surrounded by double quotation marks. For more information, see [What needs quotation marks or escape characters?](#cloudwatch-metrics-insights-syntaxdetails).  
**SCHEMA**  
An optional table function that can be used within a **FROM** clause. Use **SCHEMA** to scope down the query results to only the metrics that exactly match a list of dimensions, or to metrics that have no dimensions.   
If you use a **SCHEMA** clause, it must contain at least one argument, and this first argument must be the metric namespace being queried. If you specify **SCHEMA** with only this namespace argument, the results are scoped down to only metrics that do not have any dimensions.  
If you specify **SCHEMA** with additional arguments, the additional arguments after the namespace argument must be *label* keys. Label keys must be dimension names. If you specify one or more of these label keys, the results are scoped down to only those metrics that have that exact set of dimensions. The order of these label keys does not matter.  
For example:  
+ **SELECT AVG(CPUUtilization) FROM "AWS/EC2"** matches all `CPUUtilization` metrics in the `AWS/EC2` namespace, no matter their dimensions, and returns a single aggregated time series. 
+ **SELECT AVG(CPUUtilization) FROM SCHEMA("AWS/EC2")** matches only the `CPUUtilization` metrics in the `AWS/EC2` namespace that do not have any dimensions defined.
+ **SELECT AVG(CPUUtilization) FROM SCHEMA("AWS/EC2", InstanceId)** matches only the `CPUUtilization` metrics that were reported to CloudWatch with exactly one dimension, `InstanceId`.
+ **SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)** matches only the `RequestCount` metrics that were reported to CloudWatch from `AWS/ApplicationELB` with exactly two dimensions, `LoadBalancer` and `AvailabilityZone`.

**WHERE**  
Optional. Filters the results to only those metrics that match your specified expression using specific label values for one or more label keys. For example, **WHERE InstanceType = 'c3.4xlarge'** filters the results to only `c3.4xlarge` instance types, and **WHERE InstanceType \$1= 'c3.4xlarge'** filters the results to all instance types except `c3.4xlarge`.  
When you run a query in a monitoring account, you can use `WHERE AWS.AccountId` to limit results to only the account that you specify. For example, `WHERE AWS.AccountId=444455556666` queries metrics from only account `444455556666`. To limit your query to only metrics in the monitoring account itself, use `WHERE AWS.AccountId=CURRENT_ACCOUNT_ID()`.  
Label values must always be enclosed with single quotation marks.  
**Using tags in WHERE clauses**  
You can filter results by AWS resource tags using the syntax `tag.keyName`. Tag filters follow the same operator rules as dimension filters. For example:  
+ WHERE `tag.env = 'prod'` filters to metrics from resources tagged with *env=prod*
+ WHERE `tag.department != 'test'` excludes metrics from resources tagged with *department=test*
Tag filters can be combined with dimension filters:  
`WHERE tag.env = 'prod' AND InstanceType = 'm5.large'`  
**Supported operators**  
The **WHERE** clause supports the following operators:  
+ **=** Label value must match the specified string.
+ **\$1=** Label value must not match the specified string.
+ **AND** Both conditions that are specified must be true to match. You can use multiple **AND** keywords to specify two or more conditions.

**GROUP BY**  
Optional. Groups the query results into multiple time series, each one corresponding to a different value for the specified label key or keys. For example, using `GROUP BY InstanceId` returns a different time series for each value of `InstanceId`. Using `GROUP BY ServiceName, Operation` creates a different time series for each possible combination of the values of `ServiceName` and `Operation`.  
With a **GROUP BY** clause, by default the results are ordered in alphabetical ascending order, using the sequence of labels specified in the **GROUP BY** clause. To change the order of the results, add an **ORDER BY** clause to your query.   
When you run a query in a monitoring account, you can use `GROUP BY AWS.AccountId` to group the results based on the accounts they are from.  
**Using tags in GROUP BY clauses**  
You can group results by AWS resource tag values using the syntax `tag.keyName`. For example:  
+ *GROUP BY tag.environment* creates separate time series for each environment tag value
+ *GROUP BY tag.team, InstanceType* groups by both tag and dimension values
+ *GROUP BY tag.team, AWS.AccountId* groups by both tag and linked source AccountIDs
If some of the matching metrics don't include a specific label key specified in the **GROUP BY** clause, a null group named `Other` is returned. For example, if you specify `GROUP BY ServiceName, Operation` and some of the returned metrics don't include `ServiceName` as a dimension, then those metrics are displayed as having `Other` as the value for `ServiceName`.

**ORDER BY**  
Optional. Specifies the order to use for the returned time series, if the query returns more than one time series. The order is based on the values found by the **FUNCTION** that you specify in the **ORDER BY** clause. The **FUNCTION** is used to calculate a single scalar value from each returned time series, and that value is used to determine the order.  
You also specify whether to use ascending **ASC** or descending **DESC** order. If you omit this, the default is ascending **ASC**.  
For example, adding an `ORDER BY MAX() DESC` clause orders the results by the maximum data point observed within the time range, in descending order: meaning that the time series that has the highest maximum data point is returned first.  
The valid functions to use within an **ORDER BY** clause are `AVG()`, `COUNT()`, `MAX()`, `MIN()`, and `SUM()`.  
If you use an **ORDER BY** clause with a **LIMIT** clause, the resulting query is a "Top N" query. **ORDER BY** is also useful for queries that might return a large number of metrics, because each query can return no more than 500 time series. If a query matches more than 500 time series, and you use an **ORDER BY** clause, the time series are sorted and then the 500 time series that come first in the sort order are the ones that are returned.

**LIMIT**  
Optional. Limits the number of time series returned by the query to the value that you specify. The maximum value that you can specify is 500, and a query that does not specify a **LIMIT** can also return no more than 500 time series.  
Using a **LIMIT** clause with an **ORDER BY** clause gives you a "Top N" query.

## What needs quotation marks or escape characters?


In a query, label values must always be surrounded with single quotation marks. For example, **SELECT MAX(CPUUtilization) FROM "AWS/EC2" WHERE AutoScalingGroupName = 'my-production-fleet'**. 

Metric namespaces, metric names, and label keys that contain characters other than letters, numbers, and underscore (\$1) must be surrounded by double quote marks. For example, **SELECT MAX("My.Metric")**.

If one of these contains a double quotation mark or single quotation mark itself (such as `Bytes"Input"`), you must escape each quotation mark with a backslash, as in **SELECT AVG("Bytes\$1"Input\$1"")**. 

If a metric namespace, metric name, or label key, contains a word that is a reserved keyword in Metrics Insights, these must also be enclosed in double quotation marks. For example, if you have a metric named `LIMIT`, you would use `SELECT AVG("LIMIT")`. It is also valid to enclose any namespace, metric name, or label in double quotation marks even if it does not include a reserved keyword.

For a complete list of reserved keywords, see [Reserved keywords](cloudwatch-metrics-insights-reserved-keywords.md).

## Build a rich query step by step


This section illustrates building a full example that uses all possible clauses, step by step.

You can start with the following query, which aggregates all of the Application Load Balancer `RequestCount` metrics that are collected with both the dimensions `LoadBalancer` and `AvailabilityZone`.

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
```

To see metrics only from a specific load balancer, you can add a **WHERE** clause to limit the metrics returned to only those metrics where the value of the `LoadBalancer` dimension is `app/load-balancer-1`.

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
```

The preceding query aggregates the `RequestCount` metrics from all Availability Zones for this load balancer into one time series. If you want to see different time series for each Availability Zone, we can add a **GROUP BY** clause.

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
```

Next, you can order the results to see the highest values first. The following **ORDER BY** clause orders the time series in descending order, by the maximum value reported by each time series during the query time range:

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
ORDER BY MAX() DESC
```

You can also use tags to further filter the results. For example, if you want to see results only for load balancers tagged with a specific environment, we can add tag filtering to the WHERE clause:

```
SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone) WHERE LoadBalancer = 'app/load-balancer-1' AND tag.Environment = 'prod' GROUP BY AvailabilityZone ORDER BY MAX() DESC
```

You can also group the results by tag values instead of (or in addition to) dimensions. For example, grouping by the Application tag:

```
SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone) WHERE tag.Environment = 'prod' GROUP BY tag.Application ORDER BY MAX() DESC
```

Finally, if we are primarily interested in a "Top N" type of query, we can use a **LIMIT** clause. This final example limits the results to only the time series with the five highest `MAX` values.

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
ORDER BY MAX() DESC
LIMIT 5
```

## Cross-account query examples


These examples are valid when run in an account set up as a monitoring account in CloudWatch cross-account observability. 

The following example searches all Amazon EC2 instances in the source account 123456789012 and returns the average.

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
WHERE AWS.AccountId ='123456789012'
```

The following example queries the `CPUUtilization` metric in `AWS/EC2` in all the linked source accounts, and groups the results by account ID and instance type.

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
GROUP BY AWS.AccountId, InstanceType
```

The following example queries the `CPUUtilization` in the monitoring account itself.

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
WHERE AWS.AccountId = CURRENT_ACCOUNT_ID()
```

# Reserved keywords


The following are reserved keywords in CloudWatch Metrics Insights. If any of these words are in a namespace, metric name, or label key in a query, you must enclose them in double quote marks. Reserved keywords are not case sensitive.

```
"ABORT" "ABORTSESSION" "ABS" "ABSOLUTE" "ACCESS" "ACCESSIBLE" "ACCESS_LOCK" "ACCOUNT" "ACOS" "ACOSH" "ACTION" "ADD" "ADD_MONTHS"
"ADMIN" "AFTER" "AGGREGATE" "ALIAS" "ALL" "ALLOCATE" "ALLOW" "ALTER" "ALTERAND" "AMP" "ANALYSE" "ANALYZE" "AND" "ANSIDATE" "ANY" "ARE" "ARRAY",
"ARRAY_AGG" "ARRAY_EXISTS" "ARRAY_MAX_CARDINALITY" "AS" "ASC" "ASENSITIVE" "ASIN" "ASINH" "ASSERTION" "ASSOCIATE" "ASUTIME" "ASYMMETRIC" "AT",
"ATAN" "ATAN2" "ATANH" "ATOMIC" "AUDIT" "AUTHORIZATION" "AUX" "AUXILIARY" "AVE" "AVERAGE" "AVG" "BACKUP" "BEFORE" "BEGIN" "BEGIN_FRAME" "BEGIN_PARTITION",
"BETWEEN" "BIGINT" "BINARY" "BIT" "BLOB" "BOOLEAN" "BOTH" "BREADTH" "BREAK" "BROWSE" "BT" "BUFFERPOOL" "BULK" "BUT" "BY" "BYTE" "BYTEINT" "BYTES" "CALL",
"CALLED" "CAPTURE" "CARDINALITY" "CASCADE" "CASCADED" "CASE" "CASESPECIFIC" "CASE_N" "CAST" "CATALOG" "CCSID" "CD" "CEIL" "CEILING" "CHANGE" "CHAR",
"CHAR2HEXINT" "CHARACTER" "CHARACTERS" "CHARACTER_LENGTH" "CHARS" "CHAR_LENGTH" "CHECK" "CHECKPOINT" "CLASS" "CLASSIFIER" "CLOB" "CLONE" "CLOSE" "CLUSTER",
"CLUSTERED" "CM" "COALESCE" "COLLATE" "COLLATION" "COLLECT" "COLLECTION" "COLLID" "COLUMN" "COLUMN_VALUE" "COMMENT" "COMMIT" "COMPLETION" "COMPRESS" "COMPUTE",
"CONCAT" "CONCURRENTLY" "CONDITION" "CONNECT" "CONNECTION" "CONSTRAINT" "CONSTRAINTS" "CONSTRUCTOR" "CONTAINS" "CONTAINSTABLE" "CONTENT" "CONTINUE" "CONVERT",
"CONVERT_TABLE_HEADER" "COPY" "CORR" "CORRESPONDING" "COS" "COSH" "COUNT" "COVAR_POP" "COVAR_SAMP" "CREATE" "CROSS" "CS" "CSUM" "CT" "CUBE" "CUME_DIST",
"CURRENT" "CURRENT_CATALOG" "CURRENT_DATE" "CURRENT_DEFAULT_TRANSFORM_GROUP" "CURRENT_LC_CTYPE" "CURRENT_PATH" "CURRENT_ROLE" "CURRENT_ROW" "CURRENT_SCHEMA",
"CURRENT_SERVER" "CURRENT_TIME" "CURRENT_TIMESTAMP" "CURRENT_TIMEZONE" "CURRENT_TRANSFORM_GROUP_FOR_TYPE" "CURRENT_USER" "CURRVAL" "CURSOR" "CV" "CYCLE" "DATA",
"DATABASE" "DATABASES" "DATABLOCKSIZE" "DATE" "DATEFORM" "DAY" "DAYS" "DAY_HOUR" "DAY_MICROSECOND" "DAY_MINUTE" "DAY_SECOND" "DBCC" "DBINFO" "DEALLOCATE" "DEC",
"DECFLOAT" "DECIMAL" "DECLARE" "DEFAULT" "DEFERRABLE" "DEFERRED" "DEFINE" "DEGREES" "DEL" "DELAYED" "DELETE" "DENSE_RANK" "DENY" "DEPTH" "DEREF" "DESC" "DESCRIBE",
"DESCRIPTOR" "DESTROY" "DESTRUCTOR" "DETERMINISTIC" "DIAGNOSTIC" "DIAGNOSTICS" "DICTIONARY" "DISABLE" "DISABLED" "DISALLOW" "DISCONNECT" "DISK" "DISTINCT",
"DISTINCTROW" "DISTRIBUTED" "DIV" "DO" "DOCUMENT" "DOMAIN" "DOUBLE" "DROP" "DSSIZE" "DUAL" "DUMP" "DYNAMIC" "EACH" "ECHO" "EDITPROC" "ELEMENT" "ELSE" "ELSEIF",
"EMPTY" "ENABLED" "ENCLOSED" "ENCODING" "ENCRYPTION" "END" "END-EXEC" "ENDING" "END_FRAME" "END_PARTITION" "EQ" "EQUALS" "ERASE" "ERRLVL" "ERROR" "ERRORFILES",
"ERRORTABLES" "ESCAPE" "ESCAPED" "ET" "EVERY" "EXCEPT" "EXCEPTION" "EXCLUSIVE" "EXEC" "EXECUTE" "EXISTS" "EXIT" "EXP" "EXPLAIN" "EXTERNAL" "EXTRACT" "FALLBACK
"FALSE" "FASTEXPORT" "FENCED" "FETCH" "FIELDPROC" "FILE" "FILLFACTOR" "FILTER" "FINAL" "FIRST" "FIRST_VALUE" "FLOAT" "FLOAT4" "FLOAT8" "FLOOR" 
"FOR" "FORCE" "FOREIGN" "FORMAT" "FOUND" "FRAME_ROW" "FREE" "FREESPACE" "FREETEXT" "FREETEXTTABLE" "FREEZE" "FROM" "FULL" "FULLTEXT" "FUNCTION" 
"FUSION" "GE" "GENERAL" "GENERATED" "GET" "GIVE" "GLOBAL" "GO" "GOTO" "GRANT" "GRAPHIC" "GROUP" "GROUPING" "GROUPS" "GT" "HANDLER" "HASH" 
"HASHAMP" "HASHBAKAMP" "HASHBUCKET" "HASHROW" "HAVING" "HELP" "HIGH_PRIORITY" "HOLD" "HOLDLOCK" "HOUR" "HOURS" "HOUR_MICROSECOND" "HOUR_MINUTE" 
"HOUR_SECOND" "IDENTIFIED" "IDENTITY" "IDENTITYCOL" "IDENTITY_INSERT" "IF" "IGNORE" "ILIKE" "IMMEDIATE" "IN" "INCLUSIVE" "INCONSISTENT" "INCREMENT" 
"INDEX" "INDICATOR" "INFILE" "INHERIT" "INITIAL" "INITIALIZE" "INITIALLY" "INITIATE" "INNER" "INOUT" "INPUT" "INS" "INSENSITIVE" "INSERT" "INSTEAD" 
"INT" "INT1" "INT2" "INT3" "INT4" "INT8" "INTEGER" "INTEGERDATE" "INTERSECT" "INTERSECTION" "INTERVAL" "INTO" "IO_AFTER_GTIDS" "IO_BEFORE_GTIDS" 
"IS" "ISNULL" "ISOBID" "ISOLATION" "ITERATE" "JAR" "JOIN" "JOURNAL" "JSON_ARRAY" "JSON_ARRAYAGG" "JSON_EXISTS" "JSON_OBJECT" "JSON_OBJECTAGG" 
"JSON_QUERY" "JSON_TABLE" "JSON_TABLE_PRIMITIVE" "JSON_VALUE" "KEEP" "KEY" "KEYS" "KILL" "KURTOSIS" "LABEL" "LAG" "LANGUAGE" "LARGE" "LAST" 
"LAST_VALUE" "LATERAL" "LC_CTYPE" "LE" "LEAD" "LEADING" "LEAVE" "LEFT" "LESS" "LEVEL" "LIKE" "LIKE_REGEX" "LIMIT" "LINEAR" "LINENO" "LINES" 
"LISTAGG" "LN" "LOAD" "LOADING" "LOCAL" "LOCALE" "LOCALTIME" "LOCALTIMESTAMP" "LOCATOR" "LOCATORS" "LOCK" "LOCKING" "LOCKMAX" "LOCKSIZE" "LOG" 
"LOG10" "LOGGING" "LOGON" "LONG" "LONGBLOB" "LONGTEXT" "LOOP" "LOWER" "LOW_PRIORITY" "LT" "MACRO" "MAINTAINED" "MAP" "MASTER_BIND" 
"MASTER_SSL_VERIFY_SERVER_CERT" "MATCH" "MATCHES" "MATCH_NUMBER" "MATCH_RECOGNIZE" "MATERIALIZED" "MAVG" "MAX" "MAXEXTENTS" "MAXIMUM" "MAXVALUE" 
"MCHARACTERS" "MDIFF" "MEDIUMBLOB" "MEDIUMINT" "MEDIUMTEXT" "MEMBER" "MERGE" "METHOD" "MICROSECOND" "MICROSECONDS" "MIDDLEINT" "MIN" "MINDEX" 
"MINIMUM" "MINUS" "MINUTE" "MINUTES" "MINUTE_MICROSECOND" "MINUTE_SECOND" "MLINREG" "MLOAD" "MLSLABEL" "MOD" "MODE" "MODIFIES" "MODIFY" 
"MODULE" "MONITOR" "MONRESOURCE" "MONSESSION" "MONTH" "MONTHS" "MSUBSTR" "MSUM" "MULTISET" "NAMED" "NAMES" "NATIONAL" "NATURAL" "NCHAR" "NCLOB" 
"NE" "NESTED_TABLE_ID" "NEW" "NEW_TABLE" "NEXT" "NEXTVAL" "NO" "NOAUDIT" "NOCHECK" "NOCOMPRESS" "NONCLUSTERED" "NONE" "NORMALIZE" "NOT" "NOTNULL" 
"NOWAIT" "NO_WRITE_TO_BINLOG" "NTH_VALUE" "NTILE" "NULL" "NULLIF" "NULLIFZERO" "NULLS" "NUMBER" "NUMERIC" "NUMPARTS" "OBID" "OBJECT" "OBJECTS" 
"OCCURRENCES_REGEX" "OCTET_LENGTH" "OF" "OFF" "OFFLINE" "OFFSET" "OFFSETS" "OLD" "OLD_TABLE" "OMIT" "ON" "ONE" "ONLINE" "ONLY" "OPEN" "OPENDATASOURCE" 
"OPENQUERY" "OPENROWSET" "OPENXML" "OPERATION" "OPTIMIZATION" "OPTIMIZE" "OPTIMIZER_COSTS" "OPTION" "OPTIONALLY" "OR" "ORDER" "ORDINALITY" "ORGANIZATION" 
"OUT" "OUTER" "OUTFILE" "OUTPUT" "OVER" "OVERLAPS" "OVERLAY" "OVERRIDE" "PACKAGE" "PAD" "PADDED" "PARAMETER" "PARAMETERS" "PART" "PARTIAL" "PARTITION" 
"PARTITIONED" "PARTITIONING" "PASSWORD" "PATH" "PATTERN" "PCTFREE" "PER" "PERCENT" "PERCENTILE" "PERCENTILE_CONT" "PERCENTILE_DISC" "PERCENT_RANK" "PERIOD" "PERM" 
"PERMANENT" "PIECESIZE" "PIVOT" "PLACING" "PLAN" "PORTION" "POSITION" "POSITION_REGEX" "POSTFIX" "POWER" "PRECEDES" "PRECISION" "PREFIX" "PREORDER" 
"PREPARE" "PRESERVE" "PREVVAL" "PRIMARY" "PRINT" "PRIOR" "PRIQTY" "PRIVATE" "PRIVILEGES" "PROC" "PROCEDURE" "PROFILE" "PROGRAM" "PROPORTIONAL" 
"PROTECTION" "PSID" "PTF" "PUBLIC" "PURGE" "QUALIFIED" "QUALIFY" "QUANTILE" "QUERY" "QUERYNO" "RADIANS" "RAISERROR" "RANDOM" "RANGE" "RANGE_N" "RANK" 
"RAW" "READ" "READS" "READTEXT" "READ_WRITE" "REAL" "RECONFIGURE" "RECURSIVE" "REF" "REFERENCES" "REFERENCING" "REFRESH" "REGEXP" "REGR_AVGX" "REGR_AVGY" 
"REGR_COUNT" "REGR_INTERCEPT" "REGR_R2" "REGR_SLOPE" "REGR_SXX" "REGR_SXY" "REGR_SYY" "RELATIVE" "RELEASE" "RENAME" "REPEAT" "REPLACE" "REPLICATION" 
"REPOVERRIDE" "REQUEST" "REQUIRE" "RESIGNAL" "RESOURCE" "RESTART" "RESTORE" "RESTRICT" "RESULT" "RESULT_SET_LOCATOR" "RESUME" "RET" "RETRIEVE" "RETURN" 
"RETURNING" "RETURNS" "REVALIDATE" "REVERT" "REVOKE" "RIGHT" "RIGHTS" "RLIKE" "ROLE" "ROLLBACK" "ROLLFORWARD" "ROLLUP" "ROUND_CEILING" "ROUND_DOWN" 
"ROUND_FLOOR" "ROUND_HALF_DOWN" "ROUND_HALF_EVEN" "ROUND_HALF_UP" "ROUND_UP" "ROUTINE" "ROW" "ROWCOUNT" "ROWGUIDCOL" "ROWID" "ROWNUM" "ROWS" "ROWSET" 
"ROW_NUMBER" "RULE" "RUN" "RUNNING" "SAMPLE" "SAMPLEID" "SAVE" "SAVEPOINT" "SCHEMA" "SCHEMAS" "SCOPE" "SCRATCHPAD" "SCROLL" "SEARCH" "SECOND" "SECONDS" 
"SECOND_MICROSECOND" "SECQTY" "SECTION" "SECURITY" "SECURITYAUDIT" "SEEK" "SEL" "SELECT" "SEMANTICKEYPHRASETABLE" "SEMANTICSIMILARITYDETAILSTABLE" 
"SEMANTICSIMILARITYTABLE" "SENSITIVE" "SEPARATOR" "SEQUENCE" "SESSION" "SESSION_USER" "SET" "SETRESRATE" "SETS" "SETSESSRATE" "SETUSER" "SHARE" "SHOW" 
"SHUTDOWN" "SIGNAL" "SIMILAR" "SIMPLE" "SIN" "SINH" "SIZE" "SKEW" "SKIP" "SMALLINT" "SOME" "SOUNDEX" "SOURCE" "SPACE" "SPATIAL" "SPECIFIC" "SPECIFICTYPE" 
"SPOOL" "SQL" "SQLEXCEPTION" "SQLSTATE" "SQLTEXT" "SQLWARNING" "SQL_BIG_RESULT" "SQL_CALC_FOUND_ROWS" "SQL_SMALL_RESULT" "SQRT" "SS" "SSL" "STANDARD" 
"START" "STARTING" "STARTUP" "STAT" "STATE" "STATEMENT" "STATIC" "STATISTICS" "STAY" "STDDEV_POP" "STDDEV_SAMP" "STEPINFO" "STOGROUP" "STORED" "STORES" 
"STRAIGHT_JOIN" "STRING_CS" "STRUCTURE" "STYLE" "SUBMULTISET" "SUBSCRIBER" "SUBSET" "SUBSTR" "SUBSTRING" "SUBSTRING_REGEX" "SUCCEEDS" "SUCCESSFUL" 
"SUM" "SUMMARY" "SUSPEND" "SYMMETRIC" "SYNONYM" "SYSDATE" "SYSTEM" "SYSTEM_TIME" "SYSTEM_USER" "SYSTIMESTAMP" "TABLE" "TABLESAMPLE" "TABLESPACE" "TAN" 
"TANH" "TBL_CS" "TEMPORARY" "TERMINATE" "TERMINATED" "TEXTSIZE" "THAN" "THEN" "THRESHOLD" "TIME" "TIMESTAMP" "TIMEZONE_HOUR" "TIMEZONE_MINUTE" "TINYBLOB" 
"TINYINT" "TINYTEXT" "TITLE" "TO" "TOP" "TRACE" "TRAILING" "TRAN" "TRANSACTION" "TRANSLATE" "TRANSLATE_CHK" "TRANSLATE_REGEX" "TRANSLATION" "TREAT" 
"TRIGGER" "TRIM" "TRIM_ARRAY" "TRUE" "TRUNCATE" "TRY_CONVERT" "TSEQUAL" "TYPE" "UC" "UESCAPE" "UID" "UNDEFINED" "UNDER" "UNDO" "UNION" "UNIQUE" 
"UNKNOWN" "UNLOCK" "UNNEST" "UNPIVOT" "UNSIGNED" "UNTIL" "UPD" "UPDATE" "UPDATETEXT" "UPPER" "UPPERCASE" "USAGE" "USE" "USER" "USING" "UTC_DATE" 
"UTC_TIME" "UTC_TIMESTAMP" "VALIDATE" "VALIDPROC" "VALUE" "VALUES" "VALUE_OF" "VARBINARY" "VARBYTE" "VARCHAR" "VARCHAR2" "VARCHARACTER" "VARGRAPHIC" 
"VARIABLE" "VARIADIC" "VARIANT" "VARYING" "VAR_POP" "VAR_SAMP" "VCAT" "VERBOSE" "VERSIONING" "VIEW" "VIRTUAL" "VOLATILE" "VOLUMES" "WAIT" "WAITFOR" 
"WHEN" "WHENEVER" "WHERE" "WHILE" "WIDTH_BUCKET" "WINDOW" "WITH" "WITHIN" "WITHIN_GROUP" "WITHOUT" "WLM" "WORK" "WRITE" "WRITETEXT" "XMLCAST" "XMLEXISTS" 
"XMLNAMESPACES" "XOR" "YEAR" "YEARS" "YEAR_MONTH" "ZEROFILL" "ZEROIFNULL" "ZONE"
```

# Alarms on CloudWatch Metrics Insights queries in CloudWatch
Alarms on queries

You can create alarms on Metrics Insights queries. This helps you have alarms that track multiple resources without needing to be updated later. The query catches new resources and resources that change. For example, you can create an alarm that watches the CPU utilization of your fleet, and the alarm automatically evaluates new instances that you launch after creating the alarm.

In a monitoring account that is set up for CloudWatch cross-account observability, your Metrics Insights alarms can watch resources in source accounts and in the monitoring account itself. For more information about how to limit your alarm queries to a specific account or to group the results by account ID, see the `WHERE` and `GROUP BY` sections in [Query components and syntax in CloudWatch Metrics Insights](cloudwatch-metrics-insights-querylanguage.md).

**Using tags in alarm queries**

You can create alarms on Metrics Insights queries that use AWS resource tags to filter and group metrics. To use tags with alarms, on the [https://console.aws.amazon.com/connect/](https://console.aws.amazon.com/connect/), choose **Settings**. On the **CloudWatch Settings** page, under **Enable resource tags on telemetry**, choose **Enable**. Context-aware alarms monitor specific applications, environments, or teams automatically as resources change.

For example, you can create an alarm that monitors CPU utilization for all Amazon EC2 instances tagged with a specific application.

```
SELECT MAX(CPUUtilization) FROM "AWS/EC2" WHERE tag.Application = 'Orders' AND tag.Environment = 'Prod'
```

Tag-based alarms automatically adapt as you add or remove resources with matching tags, providing dynamic monitoring aligned with your operational structure.

**Contents**
+ [

# Creating a Metrics Insights CloudWatch alarm
](cloudwatch-metrics-insights-alarm-create.md)

# Creating a Metrics Insights CloudWatch alarm
Creating a Metrics Insights alarm

**To create an alarm on a Metrics Insights query using the console**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. In the navigation pane, choose **Metrics**, **All metrics**.

1. (Optional) To run a pre-built sample query, choose **Add query** and select the query to run. Or, you can choose **Editor** to edit the sample query and then choose **Run** to run the modified query. 

1. To create your own query, choose **Multi source query**. You can then use the **Builder** view, the **Editor** view, and also use a combination of both. You can switch between the two views anytime and see your work in progress in both views. 

   In the **Builder** view, you can browse and select the metric namespace, metric name, filter, group, and order options. For each of these options, the query builder offers you a list of possible selections from your environment to choose from.

   In the **Editor** view, you can start writing your query. As you type, the editor offers suggestions based on the characters that you have typed so far.

   For example, when creating your Metrics Insights query for the alarm, you can use tags to filter and group metrics for more targeted monitoring.
   + Filter by tags – Use `WHERE tag.keyName = 'value'` to monitor resources with specific tags

     ```
     SELECT MAX(CPUUtilization) FROM "AWS/EC2" WHERE tag.Environment = 'Prod'
     ```
   + Combine tags with dimensions – Mix tag filters with existing metric dimensions

     ```
     SELECT AVG(Duration) FROM "AWS/Lambda" WHERE tag.Application = 'OrderService' AND FunctionName = 'process%'
     ```
**Note**  
When using tags, alarms will match the metrics only if the specified tags existed on the associated resources during the evaluated time period.

1. When you are satisfied with your query, choose **Run**.

1. Choose **Create alarm**.

1. Under **Conditions**, specify the following:

   1. For **Whenever *metric* is**, specify whether the metric must be greater than, less than, or equal to the threshold. Under **than...**, specify the threshold value.

   1. Choose **Additional configuration**. For **Datapoints to alarm**, specify how many evaluation periods (data points) must be in the `ALARM` state to trigger the alarm. If the two values here match, you create an alarm that goes to `ALARM` state if that many consecutive periods are breaching.

      To create an M out of N alarm, specify a lower number for the first value than you specify for the second value. For more information, see [Alarm evaluation](alarm-evaluation.md).

   1. For **Missing data treatment**, choose how to have the alarm behave when some data points are missing. For more information, see [Configuring how CloudWatch alarms treat missing data](alarms-and-missing-data.md).

1. Choose **Next**.

1. Under **Notification**, select an SNS topic to notify when the alarm is in `ALARM` state, `OK` state, or `INSUFFICIENT_DATA` state.

   To have the alarm send multiple notifications for the same alarm state or for different alarm states, choose **Add notification**.

   To have the alarm not send notifications, choose **Remove**.

1. To have the alarm perform Auto Scaling, EC2, or Systems Manager actions, choose the appropriate button and choose the alarm state and action to perform. Alarms can perform Systems Manager actions only when they go into ALARM state. For more information about Systems Manager actions, see [ Configuring CloudWatch to create OpsItems from alarms](https://docs.aws.amazon.com/systems-manager/latest/userguide/OpsCenter-create-OpsItems-from-CloudWatch-Alarms.html) and [ Incident creation](https://docs.aws.amazon.com/incident-manager/latest/userguide/incident-creation.html).
**Note**  
To create an alarm that performs an SSM Incident Manager action, you must have certain permissions. For more information, see [ Identity-based policy examples for AWS Systems Manager Incident Manager](https://docs.aws.amazon.com/incident-manager/latest/userguide/security_iam_id-based-policy-examples.html).

1. When finished, choose **Next**.

1. Enter a name and description for the alarm. The name must contain only ASCII characters. Then choose **Next**.

1. Under **Preview and create**, confirm that the information and conditions are what you want, then choose **Create alarm**.

**To create an alarm on a Metrics Insights query using the AWS CLI**

Use the `put-metric-alarm` command and specify a Metrics Insights query in the `metrics` parameter. For example, the following command sets an alarm that goes into ALARM state if any of your instances go above 50% in CPU utilization.

```
aws cloudwatch put-metric-alarm —alarm-name Prod-App-CPU-Alarm —evaluation-periods 1 —comparison-operator GreaterThanThreshold —metrics '[{"Id":"m1","Expression":"SELECT MAX(CPUUtilization) FROM \"AWS/EC2\" WHERE tag.Environment = '\''Prod'\'' AND tag.Application = '\''OrderService'\''", "Period":60}]' —threshold 80
```

# Use Metrics Insights queries with metric math


You can use a Metrics Insights query as an input to a metric math function. For more information about metric math, see [Using math expressions with CloudWatch metrics](using-metric-math.md).

A Metrics Insights query that does not include a **GROUP BY** clause returns a single time series. Therefore, its returned results can be used with any metric math function that takes a single time series as input.

A Metrics Insights query that includes a **GROUP BY** clause returns multiple time series. Therefore, its returned results can be used with any metric math function that takes an array of time series as input.

For example, the following query returns the total number of bytes downloaded for each bucket in the Region, as an array of time series:

```
SELECT SUM(BytesDownloaded) 
FROM SCHEMA("AWS/S3", BucketName, FilterId) 
WHERE FilterId = 'EntireBucket'
GROUP BY BucketName
```

On a graph in the console or in a [GetMetricData](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricData.html) operation, the results of this query are `q1`. This query returns the result in bytes, so if you want to see the result as MB instead, you can use the following math function:

```
q1/1024/1024
```

# Use natural language to generate and update CloudWatch Metrics Insights queries


 CloudWatch supports a natural language query capability to help you generate and update queries for [CloudWatch Metrics Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/query_with_cloudwatch-metrics-insights.html) and [CloudWatch Logs Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html). 

 With this capability, you can ask questions about or describe the CloudWatch data you're looking for in plain English. The natural language capability generates a query based on a prompt that you enter and provides a line-by-line explanation of how the query works. You can also update your query to further investigate your data. 

 Depending on your environment, you can enter prompts like "Which Amazon Elastic Compute Cloud instance has the highest network out?" and "Show me the top 10 Amazon DynamoDB Tables by consumed reads." 

**Note**  
The natural-language query feature is generally available in 10 Regions. For some Regions, the feature makes cross-Region calls to Regions in the United States to process the query prompts. The following table lists the supported Regions, and shows where each Region processes its prompts.  


| Supported Region | Region where prompt is processed | 
| --- | --- | 
|  US East (N. Virginia)  |  US East (N. Virginia)  | 
|  US East (Ohio)  |  US East (N. Virginia)  | 
|  US West (Oregon)  |  US West (Oregon)  | 
|  Asia Pacific (Hong Kong)  |  US West (Oregon)  | 
|  Asia Pacific (Singapore)  |  US West (Oregon)  | 
|  Asia Pacific (Sydney)  |  US West (Oregon)  | 
|  Asia Pacific (Tokyo)  |  Asia Pacific (Tokyo)  | 
|  Europe (Frankfurt)  |  Europe (Frankfurt)  | 
|  Europe (Ireland)  |  US East (N. Virginia)  | 
|  Europe (Stockholm)  |  US East (N. Virginia)  | 

 To generate a CloudWatch Metrics Insights query with this capability, open the CloudWatch Metrics Insights query editor in the *builder* or *editor* view and choose **Generate query**. 

**Important**  
 To use the natural language query capability, you must use the [CloudWatchFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/CloudWatchFullAccess.html), [CloudWatchReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/CloudWatchReadOnlyAccess.html), [CloudWatchFullAccessV2](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/CloudWatchFullAccessV2.html), [AdministratorAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess.html), or [ReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html) policy.   
 You can also include the `cloudwatch:GenerateQuery` action in a new or existing customer managed or inline policy. 

## Example queries


 The examples in this section describe how to generate and update queries using the natural language capability. 

**Note**  
 For more information on the CloudWatch Metrics Insights query editor and syntax, see [CloudWatch Metrics Insights query components and syntax](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-metrics-insights-querylanguage.html). 

### Example: Generate a natural language query


 To generate a query using natural language, enter a prompt and choose **Generate new query**. This example shows a query that performs a basic search. 

**Prompt**  
 The following is an example of a prompt that directs the capability to search for the top 10 DynamoDB Tables that consume the most read capacity. 

```
Show top 10 DynamoDB Tables by consumed reads
```

**Query**  
 The following is an example of a query that the natural language capability generates based on the prompt. Notice how the prompt appears in a comment before the query. After the query, you can read an explanation that describes how the query works. 

```
# Show top 10 DynamoDB Tables by consumed reads
SELECT SUM("ConsumedReadCapacityUnits")
FROM "AWS/DynamoDB"
GROUP BY TableName
ORDER BY SUM() DESC
LIMIT 10
# This query selects the sum of consumed read capacity units for each DynamoDB table, groups the results by table name, orders the results from highest to lowest read capacity consumption, and limits the results to the top 10 tables.
```

**Note**  
 To turn off the appearance of your prompt and the explanation of how the query works, use the gear icon in your editor. 

### Example: Update a natural language query


 You can update a query by editing the initial prompt and then choosing **Update query**. 

**Updated prompt**  
 The following example shows an updated version of the previous prompt. Instead of a prompt that searches for the top 10 DynamoDB Tables that consume the most read capacity, this prompt now directs the capability to sort the results by the number of bytes returned. 

```
Sort by bytes returned instead
```

**Updated query**  
 The following is an example of the updated query. Notice how the updated prompt appears in a comment before the updated query. After the query, you can read an explanation that describes how the original query has been updated. 

```
# Sort by bytes returned instead
SELECT SUM("ReturnedBytes")
FROM "AWS/DynamoDB"
GROUP BY TableName
ORDER BY SUM() DESC
LIMIT 10
# This query modifies the original query to select the sum of returned bytes instead of consumed read capacity units, and orders the results from highest to lowest sum of returned bytes, limiting the results to the top 10 tables.
```

## Opting out of using your data for service improvement


 The natural language prompt data you provide to train the AI model and generate relevant queries is used solely to provide and maintain your service. This data might be used to improve the quality of CloudWatch Metrics Insights. Your trust and privacy, as well as the security of your content, is our highest priority. For more information, see [AWS Service Terms](https://aws.amazon.com/service-terms/) and [AWS responsible AI policy](https://aws.amazon.com/machine-learning/responsible-ai/policy/). 

 You can opt out of having your content used to develop or improve the quality of natural language queries by creating an AI service opt-out policy. To opt-out of data collection for all CloudWatch AI features, including the query generation capability, you must create an opt-out policy for CloudWatch. For more information, see [AI services opt-out policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_ai-opt-out.html) in the *AWS Organizations User Guide*. 

# SQL inference


CloudWatch Metrics Insights uses several mechanisms to infer the intention of a given SQL query.

**Topics**
+ [

## Time bucketing
](#cloudwatch-metrics-insights-inference-timebucketing)
+ [

## Fields projection
](#cloudwatch-metrics-insights-inference-fieldsprojection)
+ [

## ORDER BY global aggregation
](#cloudwatch-metrics-insights-inference-OrderBy)

## Time bucketing


Time series data points resulting from a query are rolled up into time buckets based on the requested period. To aggregate values in standard SQL, an explicit GROUP BY clause must be defined to collect all the observations of a given period together. Because this is the standard way to query time series data, CloudWatch Metrics Insights infers time bucketing without the need to express an explicit **GROUP BY** clause. 

For example, when a query is performed with a period of one minute, all the observations belonging to that minute until the next (excluded) are rolled up to the start time of the time bucket. This makes Metrics Insights SQL statements more concise and less verbose. 

```
SELECT AVG(CPUUtilization)
FROM SCHEMA("AWS/EC2", InstanceId)
```

The previous query returns a single time series (timestamp-value pairs), representing the average CPU utilization of all Amazon EC2 instances. Assuming the requested period is one minute, each data point returned represents the average of all observations measured within a specific one-minute interval (start time inclusive, end time exclusive). The timestamp related to the specific data point is the start time of the bucket

## Fields projection


Metrics Insights queries always return the timestamp projection. You don’t need to specify a timestamp column in the **SELECT** clause to get the timestamp of each corresponding data point value. For details about how timestamp is calculated, see [Time bucketing](#cloudwatch-metrics-insights-inference-timebucketing).

When using **GROUP BY**, each group name is also inferred and projected in the result, so that you can group the returned time series. 

```
SELECT AVG(CPUUtilization)
FROM SCHEMA("AWS/EC2", InstanceId)
GROUP BY InstanceId
```

The previous query returns a time series for each Amazon EC2 instance. Each time series is labeled after the value of the instance ID.

## ORDER BY global aggregation


When using **ORDER BY**, **FUNCTION()** infers which aggregate function that you want to order by (the data point values of the queried metrics). The aggregate operation is performed across all the matched data points of each individual time series across the queried time window. 

```
SELECT AVG(CPUUtilization)
FROM SCHEMA("AWS/EC2", InstanceId)
GROUP BY InstanceId
ORDER BY MAX()
LIMIT 10
```

The previous query returns the CPU utilization for each Amazon EC2 instance, limiting the result set to 10 entries. The results are ordered based on the maximum value of the individual time series within the requested time window. The **ORDER BY** clause is applied before **LIMIT**, so that the ordering is calculated against more than 10 time series.

# Metrics Insights quotas


CloudWatch Metrics Insights currently has the following quotas:
+ Query up to two weeks of data for visualization in your metrics, widgets, and alarm graphs. You can query the most recent three hours of data for alarm condition evaluations.
+ A single query can process no more than 10,000 metrics. This means that if the **SELECT**, **FROM**, and **WHERE** clauses match more than 10,000 metrics, the query only processes the first 10,000 of these metrics that it finds.
+ A single query can return no more than 500 time series. This means that if the query would return more than 500 metrics, not all metrics will be returned in the query results. If you use an **ORDER BY** clause, then all the metrics being processed are sorted, and the 500 that have the highest or lowest values according to your **ORDER BY** clause are returned.

  If you do not include an **ORDER BY** clause, you can't control which 500 matching metrics are returned.
+ You can have as many as 200 Metrics Insights alarms per Region. 
+ Metrics Insights does not support high-resolution data, which is metric data reported with a granularity of less than one minute. If you request high-resolution data, the request does not fail, but the output is aggregated at one-minute granularity.
+ Each [GetMetricData](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricData.html) operation can have only one query, but you can have multiple widgets in a dashboard that each include a query.
+ If a query using tag(s) with a **GROUP BY** or **WHERE** matches a metric that has more than 10 tag updates, only the most recent 10 tagged versions of the metric will be included in the query results.

# Metrics Insights sample queries
Sample queries

This section contains examples of useful CloudWatch Metrics Insights queries that you can copy and use directly or copy and modify in query editor. Some of these examples are already available in the console, and you can access them by choosing **Add query** in the **Metrics** view.

## Application Load Balancer examples


**Total requests across all load balancers**

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer)
```

**Top 10 most active load balancers **

```
SELECT MAX(ActiveConnectionCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer) 
GROUP BY LoadBalancer 
ORDER BY SUM() DESC 
LIMIT 10
```

## AWS API usage examples


**Top 20 AWS APIs by the number of calls in your account**

```
SELECT COUNT(CallCount) 
FROM SCHEMA("AWS/Usage", Class, Resource, Service, Type) 
WHERE Type = 'API' 
GROUP BY Service, Resource 
ORDER BY COUNT() DESC 
LIMIT 20
```

**CloudWatch APIs sorted by calls**

```
SELECT COUNT(CallCount) 
FROM SCHEMA("AWS/Usage", Class, Resource, Service, Type) 
WHERE Type = 'API' AND Service = 'CloudWatch' 
GROUP BY Resource 
ORDER BY COUNT() DESC
```

## DynamoDB examples


**Top 10 tables by consumed reads**

```
SELECT SUM(ProvisionedWriteCapacityUnits)
FROM SCHEMA("AWS/DynamoDB", TableName) 
GROUP BY TableName
ORDER BY MAX() DESC LIMIT 10
```

**Top 10 tables by returned bytes**

```
SELECT SUM(ReturnedBytes)
FROM SCHEMA("AWS/DynamoDB", TableName) 
GROUP BY TableName
ORDER BY MAX() DESC LIMIT 10
```

**Top 10 tables by user errors**

```
SELECT SUM(UserErrors)
FROM SCHEMA("AWS/DynamoDB", TableName) 
GROUP BY TableName
ORDER BY MAX() DESC LIMIT 10
```

## Amazon Elastic Block Store examples


**Top 10 Amazon EBS volumes by bytes written**

```
SELECT SUM(VolumeWriteBytes) 
FROM SCHEMA("AWS/EBS", VolumeId) 
GROUP BY VolumeId 
ORDER BY SUM() DESC 
LIMIT 10
```

**Average Amazon EBS volume write time**

```
SELECT AVG(VolumeTotalWriteTime) 
FROM SCHEMA("AWS/EBS", VolumeId)
```

## Amazon EC2 examples


**CPU utilization of EC2 instances sorted by highest **

```
SELECT AVG(CPUUtilization) 
  FROM SCHEMA("AWS/EC2", InstanceId) 
  GROUP BY InstanceId 
  ORDER BY AVG() DESC
```

**Average CPU utilization across the entire fleet**

```
SELECT AVG(CPUUtilization) 
FROM SCHEMA("AWS/EC2", InstanceId)
```

**Top 10 instances by highest CPU utilization**

```
SELECT MAX(CPUUtilization) 
FROM SCHEMA("AWS/EC2", InstanceId) 
GROUP BY InstanceId 
ORDER BY MAX() DESC 
LIMIT 10
```

**In this case, the CloudWatch agent is collecting a `CPUUtilization` metric per application. This query filters the average of this metric for a specific application name.**

```
SELECT AVG(CPUUtilization)
FROM "AWS/CWAgent"
WHERE ApplicationName = 'eCommerce'
```

## Amazon Elastic Container Service examples


**Average CPU utilization across all ECS clusters **

```
SELECT AVG(CPUUtilization) 
FROM SCHEMA("AWS/ECS", ClusterName)
```

**Top 10 clusters by memory utilization**

```
SELECT AVG(MemoryUtilization) 
FROM SCHEMA("AWS/ECS", ClusterName) 
GROUP BY ClusterName 
ORDER BY AVG() DESC
LIMIT 10
```

**Top 10 services by CPU utilization**

```
SELECT AVG(CPUUtilization) 
FROM SCHEMA("AWS/ECS", ClusterName, ServiceName) 
GROUP BY ClusterName, ServiceName 
ORDER BY AVG() DESC 
LIMIT 10
```

**Top 10 services by running tasks (Container Insights)**

```
SELECT AVG(RunningTaskCount) 
FROM SCHEMA("ECS/ContainerInsights", ClusterName, ServiceName) 
GROUP BY ClusterName, ServiceName 
ORDER BY AVG() DESC 
LIMIT 10
```

## Amazon Elastic Kubernetes Service Container Insights examples


**Average CPU utilization across all EKS clusters **

```
SELECT AVG(pod_cpu_utilization) 
FROM SCHEMA("ContainerInsights", ClusterName)
```

**Top 10 clusters by node CPU utilization**

```
SELECT AVG(node_cpu_utilization) 
FROM SCHEMA("ContainerInsights", ClusterName) 
GROUP BY ClusterName
ORDER BY AVG() DESC LIMIT 10
```

**Top 10 clusters by pod memory utilization**

```
SELECT AVG(pop_memory_utilization) 
FROM SCHEMA("ContainerInsights", ClusterName) 
GROUP BY ClusterName
ORDER BY AVG() DESC LIMIT 10
```

**Top 10 nodes by CPU utilization**

```
SELECT AVG(node_cpu_utilization) 
FROM SCHEMA("ContainerInsights", ClusterName, NodeName) 
GROUP BY ClusterName, NodeName 
ORDER BY AVG() DESC LIMIT 10
```

**Top 10 pods by memory utilization**

```
SELECT AVG(pod_memory_utilization) 
FROM SCHEMA("ContainerInsights", ClusterName, PodName) 
GROUP BY ClusterName, PodName 
ORDER BY AVG() DESC LIMIT 10
```

## EventBridge examples


**Top 10 rules by invocations**

```
SELECT SUM(Invocations)
FROM SCHEMA("AWS/Events", RuleName) 
GROUP BY RuleName
ORDER BY MAX() DESC LIMIT 10
```

**Top 10 rules by failed invocations**

```
SELECT SUM(FailedInvocations)
FROM SCHEMA("AWS/Events", RuleName) 
GROUP BY RuleName
ORDER BY MAX() DESC LIMIT 10
```

**Top 10 rules by matched rules**

```
SELECT SUM(MatchedEvents)
FROM SCHEMA("AWS/Events", RuleName) 
GROUP BY RuleName
ORDER BY MAX() DESC LIMIT 10
```

## Kinesis examples


**Top 10 streams by bytes written**

```
SELECT SUM("PutRecords.Bytes") 
FROM SCHEMA("AWS/Kinesis", StreamName) 
GROUP BY StreamName
ORDER BY SUM() DESC LIMIT 10
```

**Top 10 streams by earliest items in the stream**

```
SELECT MAX("GetRecords.IteratorAgeMilliseconds") 
FROM SCHEMA("AWS/Kinesis", StreamName) 
GROUP BY StreamName
ORDER BY MAX() DESC LIMIT 10
```

## Lambda examples


**Lambda functions ordered by number of invocations**

```
SELECT SUM(Invocations) 
FROM SCHEMA("AWS/Lambda", FunctionName) 
GROUP BY FunctionName 
ORDER BY SUM() DESC
```

**Top 10 Lambda functions by longest runtime**

```
SELECT AVG(Duration) 
FROM SCHEMA("AWS/Lambda", FunctionName) 
GROUP BY FunctionName 
ORDER BY MAX() DESC 
LIMIT 10
```

**Top 10 Lambda functions by error count**

```
SELECT SUM(Errors) 
FROM SCHEMA("AWS/Lambda", FunctionName) 
GROUP BY FunctionName 
ORDER BY SUM() DESC 
LIMIT 10
```

## CloudWatch Logs examples


**Top 10 log groups by incoming events**

```
SELECT SUM(IncomingLogEvents)
FROM SCHEMA("AWS/Logs", LogGroupName) 
GROUP BY LogGroupName
ORDER BY SUM() DESC LIMIT 10
```

**Top 10 log groups by written bytes**

```
SELECT SUM(IncomingBytes)
FROM SCHEMA("AWS/Logs", LogGroupName) 
GROUP BY LogGroupName
ORDER BY SUM() DESC LIMIT 10
```

## Amazon RDS examples


**Top 10 Amazon RDS instances by highest CPU utilization**

```
SELECT MAX(CPUUtilization)
FROM SCHEMA("AWS/RDS", DBInstanceIdentifier) 
GROUP BY DBInstanceIdentifier
ORDER BY MAX() DESC 
LIMIT 10
```

**Top 10 Amazon RDS clusters by writes**

```
SELECT SUM(WriteIOPS)
FROM SCHEMA("AWS/RDS", DBClusterIdentifier) 
GROUP BY DBClusterIdentifier
ORDER BY MAX() DESC 
LIMIT 10
```

## Amazon Simple Storage Service examples


**Average latency by bucket**

```
SELECT AVG(TotalRequestLatency) 
FROM SCHEMA("AWS/S3", BucketName, FilterId) 
WHERE FilterId = 'EntireBucket' 
GROUP BY BucketName 
ORDER BY AVG() DESC
```

**Top 10 buckets by bytes downloaded**

```
SELECT SUM(BytesDownloaded) 
FROM SCHEMA("AWS/S3", BucketName, FilterId) 
WHERE FilterId = 'EntireBucket'
GROUP BY BucketName 
ORDER BY SUM() DESC 
LIMIT 10
```

## Amazon Simple Notification Service examples


**Total messages published by SNS topics**

```
SELECT SUM(NumberOfMessagesPublished) 
FROM SCHEMA("AWS/SNS", TopicName)
```

**Top 10 topics by messages published**

```
SELECT SUM(NumberOfMessagesPublished) 
FROM SCHEMA("AWS/SNS", TopicName) 
GROUP BY TopicName 
ORDER BY SUM() DESC 
LIMIT 10
```

**Top 10 topics by message delivery failures**

```
SELECT SUM(NumberOfNotificationsFailed) 
FROM SCHEMA("AWS/SNS", TopicName)
GROUP BY TopicName 
ORDER BY SUM() DESC 
LIMIT 10
```

## Amazon SQS examples


**Top 10 queues by number of visible messages**

```
SELECT AVG(ApproximateNumberOfMessagesVisible)
FROM SCHEMA("AWS/SQS", QueueName) 
GROUP BY QueueName
ORDER BY AVG() DESC 
LIMIT 10
```

**Top 10 most active queues**

```
SELECT SUM(NumberOfMessagesSent)
FROM SCHEMA("AWS/SQS", QueueName) 
GROUP BY QueueName
ORDER BY SUM() DESC 
LIMIT 10
```

**Top 10 queues by age of earliest message**

```
SELECT AVG(ApproximateAgeOfOldestMessage)
FROM SCHEMA("AWS/SQS", QueueName) 
GROUP BY QueueName
ORDER BY AVG() DESC 
LIMIT 10
```

# Metrics Insights glossary


**label**  
In Metrics Insights, a label is a key-value pair that is used to scope a query to return a particular set of data, or to define criteria by which query results are to be separated into separate time series. A label key is similar to a column name in SQL. Labels must be CloudWatch metric dimensions. 

**observation**  
An observation is a value recorded for a given metric at a given time.

# Troubleshooting Metrics Insights


## The results include "Other," but I don't have this as a dimension


This means that the query includes a **GROUP BY** clause that specifies a label key that is not used in some of the metrics that are returned by the query. In this case, a null group named `Other` is returned. The metrics that do not include that label key are probably aggregated metrics that return values aggregated across all values of that label key.

 For example, suppose we have the following query:

```
SELECT AVG(Faults) 
FROM MyCustomNamespace 
GROUP BY Operation, ServiceName
```

If some of the returned metrics don't include `ServiceName` as a dimension, then those metrics are displayed as having `Other` as the value for `ServiceName`.

To prevent seeing "Other" in your results, use **SCHEMA** in your **FROM** clause, as in the following example:

```
SELECT AVG(Faults) 
FROM SCHEMA(MyCustomNamespace, Operation)
GROUP BY Operation, ServiceName
```

This limits the returned results to only the metrics that have both the `Operation` and `ServiceName` dimensions.

## The oldest timestamp in my graph has a lower metric value than the others


CloudWatch Metrics Insights supports up to two weeks of historical data. When you graph with a period larger than one minute, there could be cases where the oldest data point differs from the expected value. This is because the CloudWatch Metrics Insights queries return only data within the two-week retention period. In this case, the oldest data point in the query returns only the observations that have been measured within the two-week boundary, instead of returning all the observations within the period of that data point.

## Inconsistent metric values across different time periods when using tag-based queries


When you use `WHERE` or `GROUP BY` clauses with tags in CloudWatch Metrics Insights queries, you might see different metric values depending on the selected time period. For example, a 6-hour period might show a peak value of 20, while a 1-hour period shows only 2 for the same time window.

This occurs because tag timestamps are stored with second-level resolution, while metric data points are aligned to period boundaries (for example, the start of each minute or hour). To determine which data points match a tag time range, CloudWatch adjusts the start of the range by subtracting one period. With larger periods, this adjustment creates a wider gap between the tag timestamp and the earliest included data point, which can cause data points near the start of the range to be excluded.

The following example shows how this affects query results. A metric has two tag values: `env=beta` (from 00:00 to 01:30) and `env=gamma` (from 01:30 to 03:00). Each tag covers 90 minutes of data with a SUM of 270.

![\[Two CloudWatch metric graphs comparing tag-based query results with 1-minute and 3-hour periods.\]](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/images/metrics-insights-tag-alignment.png)



| **env=beta with 1-minute period** | Statistic | Expected | Returned | Difference | 
| --- | --- | --- | --- | --- | 
| SUM | 270 | 271 | \$11 | 
| AVG | 3.0 | 3.0 | 0 | 
| MIN | 1 | 1 | 0 | 
| MAX | 5 | 5 | 0 | 
| SAMPLE\$1COUNT | 90 | 91 | \$11 | 


| **env=gamma with 1-minute period** | Statistic | Expected | Returned | Difference | 
| --- | --- | --- | --- | --- | 
| SUM | 270 | 275 | \$15 | 
| AVG | 3.0 | 3.0 | 0 | 
| MIN | 1 | 1 | 0 | 
| MAX | 5 | 5 | 0 | 
| SAMPLE\$1COUNT | 90 | 91 | \$11 | 

With a 1-minute period, the alignment adjustment is small (1 minute), so only 1 extra data point is included per tag. With a 3-hour period, the adjustment spans the entire query range:


| **env=beta with 3-hour period** | Statistic | Expected | Returned | Difference | 
| --- | --- | --- | --- | --- | 
| SUM | 270 | 540 | \$1270 | 
| AVG | 3.0 | 3.0 | 0 | 
| MIN | 1 | 1 | 0 | 
| MAX | 5 | 5 | 0 | 
| SAMPLE\$1COUNT | 90 | 180 | \$190 | 


| **env=gamma with 3-hour period** | Statistic | Expected | Returned | Difference | 
| --- | --- | --- | --- | --- | 
| SUM | 270 | 540 | \$1270 | 
| AVG | 3.0 | 3.0 | 0 | 
| MIN | 1 | 1 | 0 | 
| MAX | 5 | 5 | 0 | 
| SAMPLE\$1COUNT | 90 | 180 | \$190 | 

With the 3-hour period, both tags return the entire dataset (SUM=540, SAMPLE\$1COUNT=180) because the single aggregated data point's timestamp falls within both adjusted ranges. The tag boundary is effectively erased.

To reduce the impact of this behaviour, try the following approaches:
+ **Use smaller aggregation periods.** Smaller periods (such as 1 minute or 5 minutes) more closely match the second-level resolution of tag timestamps, which minimizes the alignment gap and makes it more likely that all relevant data points are included.
+ **Use dimension-based filtering instead of tags.** If your use case allows it, filter by dimensions rather than tags. Dimension-based queries are not affected by this behaviour. For example, use `WHERE InstanceId = 'i-1234567890abcdef0'` instead of `WHERE tag."my-tag" = 'my-value'`.
+ **Query at a consistent granularity.** When comparing metric data across different time windows, use the same period to avoid unexpected differences caused by the alignment adjustment.