Metric Filters and Custom Metrics
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Lesson: Mastering Metric Filters and Custom Metrics in Amazon CloudWatch
Introduction: Why Monitoring Matters
In the world of distributed systems and cloud infrastructure, the ability to observe your applications is not just a luxury—it is a fundamental requirement for operational stability. When you deploy an application to the cloud, you are essentially launching a black box. Without effective monitoring, you have no way of knowing how your application is behaving, whether it is running into errors, or how users are interacting with your services. CloudWatch serves as the primary observability tool for AWS, and at its heart lie two critical features: Metric Filters and Custom Metrics.
Metric Filters allow you to extract numerical data from unstructured text logs, turning raw event streams into actionable data points. Custom Metrics, on the other hand, provide a way to publish data that AWS doesn't track automatically, such as application-specific business logic or granular performance data. By mastering these two concepts, you move from reactive troubleshooting—where you wait for a user to report a problem—to proactive monitoring, where you catch issues before they impact your customers. This lesson will guide you through the technical intricacies of these features, providing you with the skills to build a truly observable environment.
Understanding CloudWatch Logs and Metric Filters
CloudWatch Logs are the central repository for your application's standard output (stdout), standard error (stderr), and custom application logs. While logs are invaluable for debugging specific incidents, they are often too voluminous to scan manually. If you have an application generating hundreds of gigabytes of logs per day, finding a specific "NullPointerException" or "404 Not Found" error is like searching for a needle in a haystack. This is where Metric Filters come into play.
A Metric Filter is a rule that you apply to a CloudWatch Log Group. It scans incoming log events for specific patterns or keywords. When a match is found, the filter extracts a value—either a constant increment (like counting the occurrence of an error) or a specific numerical value found within the log line—and publishes it as a data point to a CloudWatch Metric.
How Metric Filters Work
When you define a Metric Filter, you are essentially writing a pattern that instructs CloudWatch on what to look for. The syntax is powerful but requires precision. You can search for simple strings, complex patterns, or even specific JSON fields. Once a match is found, the filter increments a metric. This transformed data allows you to create alarms based on the frequency of events rather than the existence of an event.
Callout: Logs vs. Metrics Logs are like a diary; they provide a historical, line-by-line account of what happened at a specific moment. Metrics are like a dashboard; they provide a numerical, time-series representation of the state of your system. Metric Filters act as the bridge, converting the narrative of the diary into the numbers on the dashboard.
Step-by-Step: Creating a Metric Filter
To create a Metric Filter, you follow a structured approach within the AWS Management Console or via Infrastructure as Code (IaC) tools like Terraform or CloudFormation.
- Navigate to Log Groups: Open the CloudWatch console and select "Log groups" from the left-hand navigation pane.
- Select the Log Group: Click on the name of the log group that contains the logs you want to monitor.
- Create Metric Filter: Navigate to the "Metric filters" tab and click the "Create metric filter" button.
- Define the Pattern: Enter the filter pattern. For example, if you want to count every time your application logs the word "ERROR", your pattern would simply be
ERROR. - Assign a Namespace and Metric Name: Choose a namespace (e.g.,
MyApp/Errors) and a metric name (e.g.,ErrorCount). - Set the Metric Value: Define what happens when a match occurs. Usually, this is
1for a counter. - Review and Create: Finalize the settings and save.
Tip: Always use descriptive namespaces for your metrics. If you have multiple environments (development, staging, production), include the environment name in the namespace (e.g.,
Prod/MyApp/Errors) to avoid data collision and simplify alarm management.
Deep Dive: Advanced Pattern Matching
The power of Metric Filters lies in their pattern syntax. If you are logging in JSON format, CloudWatch can automatically parse the fields for you. If you are using plain text, you need to use the CloudWatch filter pattern syntax to isolate specific information.
Filtering JSON Logs
Modern applications often log in JSON to make parsing easier. If your log line looks like this:
{"level": "ERROR", "latency": 150, "user_id": "123"}
You can create a metric filter that specifically captures the latency field. The pattern would be:
{ $.latency > 100 }
This tells CloudWatch to only trigger the metric when the latency value inside the JSON object exceeds 100 milliseconds. This is incredibly useful for tracking performance degradation without needing to change your application code.
Filtering Plain Text Logs
For legacy applications or those using standard logging libraries, you might have logs like:
2023-10-27 10:00:00 [INFO] Request processed in 250ms
To capture the latency here, you would use a pattern that uses brackets to signify "capture groups":
[timestamp, level, message, request, duration, unit]
By defining the structure, you can target the duration variable and treat it as a numerical value for your metric. This allows you to graph average latency over time, providing clear visibility into how your application performance changes during peak traffic hours.
Custom Metrics: Beyond Log-Based Data
While Metric Filters are excellent for log-based data, there are times when you need to send metrics directly to CloudWatch from your code. This is where Custom Metrics come in. Custom Metrics are data points that you push to CloudWatch using the AWS SDK or the CloudWatch agent.
Why Use Custom Metrics?
You should use Custom Metrics when:
- You need to track business-level metrics, such as "number of items added to cart" or "total value of transactions."
- You want to monitor internal application states, like the number of threads currently active in a pool.
- You need high-resolution monitoring (sub-minute granularity) that log-based metrics cannot provide.
Implementing Custom Metrics with the AWS SDK
Using the AWS SDK (for Python, Java, Node.js, etc.), you can publish metrics with a few lines of code. Below is an example using the Boto3 library for Python:
import boto3
# Initialize the CloudWatch client
cw = boto3.client('cloudwatch', region_name='us-east-1')
# Publish a custom metric
cw.put_metric_data(
Namespace='MyApplication',
MetricData=[
{
'MetricName': 'ItemsPurchased',
'Dimensions': [
{'Name': 'Environment', 'Value': 'Production'}
],
'Unit': 'Count',
'Value': 1.0
}
]
)
In this example, we are sending a single data point to the ItemsPurchased metric. The Dimensions are crucial here; they allow you to slice and dice your data. By adding an Environment dimension, you can filter your dashboard to show only production traffic.
Warning: Be mindful of the cost. CloudWatch charges per custom metric and per API call. If you publish metrics too frequently (e.g., every millisecond), your costs will escalate quickly. Always batch your metric data points if the SDK supports it.
Comparison: Metric Filters vs. Custom Metrics
It is important to understand when to use one over the other. The following table provides a quick reference to help you decide.
| Feature | Metric Filters | Custom Metrics |
|---|---|---|
| Source | CloudWatch Logs | Application Code / Agents |
| Effort | Low (Configuration only) | Medium (Requires code changes) |
| Flexibility | Limited to log content | High (Any numerical value) |
| Cost | Low (Per log group/filter) | Higher (Per metric/API call) |
| Latency | Near real-time | Real-time |
| Use Case | Error counting, log-based alerts | Business KPIs, system internals |
Best Practices for Monitoring Strategy
Developing a robust monitoring strategy is about more than just setting up a few filters; it is about creating a system that tells you the truth about your infrastructure.
1. Use Meaningful Dimensions
Dimensions are the key-value pairs that help you categorize your metrics. Instead of creating a metric called UserLogin_Production and UserLogin_Staging, create one metric called UserLogin and use a dimension Environment. This allows you to use the same dashboard for all environments and simply toggle the view.
2. Standardize Your Log Format
If you are working in a microservices environment, ensure that all services log in the same format—preferably JSON. This makes it significantly easier to write reusable Metric Filters across your entire organization. If Service A logs in JSON and Service B logs in plain text, your monitoring dashboards will become a nightmare to maintain.
3. Set Alarms on Metrics, Not Logs
Never try to set an alarm directly on a log stream. Logs are for investigation; metrics are for alerting. By creating a Metric Filter that increments a counter on every error, you can set a CloudWatch Alarm on that metric. This is much more efficient and reliable than trying to trigger an alarm based on a log entry scan.
4. Clean Up Unused Metrics
CloudWatch does not automatically delete custom metrics, even if they stop receiving data. Over time, you may accumulate hundreds of "zombie" metrics that clutter your UI and potentially increase your costs. Perform a quarterly audit of your custom metrics and delete those that are no longer providing value.
5. Monitor Your Monitoring
It is a common pitfall to assume that your monitoring system is always working. However, if your application stops sending logs or if a log rotation policy wipes out your data, your monitoring might fail silently. Create a "heartbeat" metric that sends a signal every minute. If that signal stops, you know something is wrong with your logging pipeline.
Callout: High Cardinality High cardinality occurs when you add too many unique dimension values to a metric (e.g., using
User_IDas a dimension). CloudWatch has limits on the number of unique time series you can store. If you create a metric with a dimension that has millions of possible values, you will quickly hit these limits and cause your monitoring system to become unstable. Stick to low-cardinality dimensions likeRegion,InstanceType, orEnvironment.
Common Pitfalls and How to Avoid Them
Pitfall 1: Over-logging
Many developers log everything "just in case." This leads to massive log volumes, higher costs, and a "signal-to-noise" problem where the important errors are buried under millions of lines of debug logs.
- The Fix: Use log levels effectively. Log
DEBUGorTRACEonly in development. In production, useINFOfor major lifecycle events andERRORorWARNfor issues. Use Metric Filters to track the frequency of these errors without needing to store the entire verbose log.
Pitfall 2: Ignoring Metric Resolution
By default, custom metrics are stored with a 1-minute resolution. If you need sub-minute data (e.g., 1-second resolution), you must explicitly configure them as "High-Resolution" metrics.
- The Fix: Use high-resolution metrics only for critical components where every second counts. Remember that high-resolution metrics are more expensive and should be used sparingly.
Pitfall 3: Hardcoding Metric Names
Hardcoding strings like MetricName = "OrderCount" throughout your codebase makes it difficult to refactor later.
- The Fix: Use constants or configuration files to define your metric names. This ensures that if you decide to rename a metric, you only have to change it in one location.
Pitfall 4: Misunderstanding "Namespace"
A common mistake is putting all metrics in a single namespace like General. This makes it impossible to manage permissions or find specific metrics in the console.
- The Fix: Use a hierarchical namespace structure, such as
Application/Service/Environment. This makes the CloudWatch console much more navigable and allows you to apply IAM policies that restrict access to specific metric namespaces.
Step-by-Step: Setting Up an Alarm on a Metric Filter
Once you have your Metric Filter capturing data, the next logical step is to set up an alarm so you are notified when things go wrong.
- Go to the Metric: Find the metric you created in the CloudWatch "Metrics" console.
- Select Graphed Metrics: Select the metric and ensure the "Graphed metrics" tab is active.
- Create Alarm: Click the bell icon (or the "Create alarm" button) next to the metric.
- Define Conditions: Choose the threshold type (Static or Anomaly Detection). For a simple error counter, a static threshold is best. Set the condition to "Greater than" and the threshold value to your limit (e.g., 5 errors in 5 minutes).
- Configure Actions: Choose an SNS topic to notify you via email or SMS when the alarm state changes to "ALARM."
- Name and Create: Give your alarm a clear name (e.g.,
Production-OrderService-ErrorRate-High) and finalize the creation.
This workflow transforms your logs from passive text files into an active surveillance system. By setting these thresholds, you move from "I hope the system is working" to "I will be notified if the system stops working."
The Role of the CloudWatch Agent
While the AWS SDK is great for custom code, sometimes you want to monitor system-level metrics (like memory usage or disk space) that aren't available by default. The CloudWatch Agent is a software package you install on your EC2 instances or on-premises servers that collects this data and pushes it to CloudWatch.
Configuring the Agent
The agent is configured via a JSON file. This file defines what to collect and where to send it. A typical configuration might look like this:
{
"metrics": {
"metrics_collected": {
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
},
"disk": {
"measurement": ["used_percent"],
"resources": ["/"],
"metrics_collection_interval": 60
}
}
}
}
By installing this agent and using this configuration, you gain visibility into the health of the underlying server. This is critical for catching issues like memory leaks, where the application might be running fine but slowly consuming more and more RAM until the instance crashes.
Note: The CloudWatch Agent is not just for metrics. It can also be configured to collect log files from the server and push them into CloudWatch Logs. This is the recommended way to get logs from EC2 instances into the cloud.
Advanced Topic: Anomaly Detection
One of the more sophisticated features in CloudWatch is Anomaly Detection. Sometimes, a hard threshold is not enough. For example, your traffic might naturally spike every Monday morning. If you set a static alarm at 100 requests per minute, you might get a false positive every Monday.
Anomaly Detection uses machine learning to analyze the historical patterns of your metric. It creates a "normal" range of expected values and alerts you only when the metric falls outside of that range. This significantly reduces "alert fatigue," which occurs when developers are bombarded with unnecessary notifications, eventually leading them to ignore all alerts.
To enable this:
- In the alarm creation screen, select "Anomaly detection" as the threshold type.
- CloudWatch will automatically determine the "normal" range based on the last two weeks of data.
- You can adjust the sensitivity (the width of the band) to make the alarm more or less strict.
This is a powerful tool for complex, dynamic environments where static thresholds are simply too brittle to be useful.
Key Takeaways
As we conclude this lesson, let's summarize the core principles that will ensure your success in monitoring and logging:
- Logs are for investigation, Metrics are for alerting: Never use logs to trigger real-time alerts directly. Use Metric Filters to convert log events into metrics, then alert on those metrics.
- Standardize for scale: Use consistent log formats (like JSON) and hierarchical naming conventions (Namespaces/Dimensions) to keep your monitoring environment clean and manageable.
- Prioritize actionable data: Avoid the temptation to log everything. Focus on metrics that represent business value or system health, and use anomaly detection to reduce noise.
- Monitor the monitoring: Always ensure your logging and metric pipelines are healthy. A silent monitoring system is more dangerous than no monitoring at all.
- Practice "Monitoring as Code": Don't configure your filters and alarms manually through the console for production environments. Use CloudFormation, Terraform, or CDK to define your monitoring infrastructure. This ensures that your monitoring is version-controlled, repeatable, and consistent across all environments.
- Beware of High Cardinality: When defining dimensions, avoid using values that change per request (like IDs or timestamps). Stick to low-cardinality values to keep your metrics within CloudWatch limits and maintain performance.
- Balance cost and granularity: Custom metrics and high-resolution data come with a price. Evaluate whether you truly need 1-second resolution versus 1-minute resolution before finalizing your implementation.
By following these principles, you will be able to build a monitoring system that is not only effective but also sustainable. You will be able to detect problems before they manifest as customer-facing outages and provide your team with the data they need to troubleshoot issues with confidence and speed. Monitoring is the eyes and ears of your cloud infrastructure; treat it with the same care and rigor you apply to your application code.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons