Extract CloudWatch metrics from log events using configurable patterns and metric definitions, enabling automated monitoring and alerting based on log content.
Extract CloudWatch metrics from log events by matching patterns and extracting values, enabling automated monitoring and alerting based on log content.
/**
* Extract metrics from log events using pattern matching
*/
class MetricFilter extends Construct {
/**
* Create a metric filter
* @param scope - Construct scope
* @param id - Construct ID
* @param props - MetricFilter configuration properties
*/
constructor(scope: Construct, id: string, props: MetricFilterProps);
/**
* Return the CloudWatch metric associated with this filter
* @param props - Additional metric configuration options
* @returns CloudWatch Metric object
*/
metric(props?: cloudwatch.MetricOptions): cloudwatch.Metric;
}
/**
* Properties for MetricFilter
*/
interface MetricFilterProps {
/** Log group to monitor for metrics */
readonly logGroup: ILogGroup;
/** Pattern to match in log events */
readonly filterPattern: IFilterPattern;
/** CloudWatch metric namespace */
readonly metricNamespace: string;
/** CloudWatch metric name */
readonly metricName: string;
/** Expression to extract metric value from matched logs */
readonly metricValue?: string;
/** Default value to emit when no logs match in a period */
readonly defaultValue?: number;
}Usage Examples:
import * as logs from '@aws-cdk/aws-logs';
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
const logGroup = new logs.LogGroup(this, 'MyLogGroup');
// Count ERROR occurrences
const errorMetricFilter = new logs.MetricFilter(this, 'ErrorMetricFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.literal('ERROR'),
metricNamespace: 'MyApp',
metricName: 'ErrorCount',
metricValue: '1', // Increment by 1 for each match
defaultValue: 0,
});
// Extract response time from JSON logs
const responseTimeFilter = new logs.MetricFilter(this, 'ResponseTimeFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.exists('$.responseTime'),
metricNamespace: 'MyApp',
metricName: 'ResponseTime',
metricValue: '$.responseTime', // Use the actual response time value
});
// Create CloudWatch alarm from metric
const errorAlarm = new cloudwatch.Alarm(this, 'ErrorAlarm', {
metric: errorMetricFilter.metric({
statistic: 'Sum',
period: cdk.Duration.minutes(5),
}),
threshold: 10,
evaluationPeriods: 2,
});Convenient method to extract metrics directly from log groups with simplified JSON field extraction.
/**
* Extract metric from JSON logs in the log group (from LogGroup class)
* @param jsonField - JSON field path to extract (e.g., "$.responseTime")
* @param metricNamespace - CloudWatch metric namespace
* @param metricName - CloudWatch metric name
* @returns Created MetricFilter instance
*/
extractMetric(jsonField: string, metricNamespace: string, metricName: string): MetricFilter;Usage Examples:
import * as logs from '@aws-cdk/aws-logs';
const logGroup = new logs.LogGroup(this, 'ApiLogGroup');
// Extract response time metric from JSON logs
const responseTimeMetric = logGroup.extractMetric(
'$.responseTime',
'API',
'ResponseTime'
);
// Extract error count metric
const errorCountMetric = logGroup.extractMetric(
'$.errorCount',
'API',
'ErrorCount'
);
// Use metrics in alarms
const responseTimeAlarm = new cloudwatch.Alarm(this, 'ResponseTimeAlarm', {
metric: responseTimeMetric.metric({
statistic: 'Average',
period: cdk.Duration.minutes(5),
}),
threshold: 1000,
evaluationPeriods: 2,
});// Count different types of errors
const authErrorFilter = new logs.MetricFilter(this, 'AuthErrorFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.stringValue('$.level', '=', 'ERROR'),
logs.FilterPattern.stringValue('$.type', '=', 'authentication')
),
metricNamespace: 'Security',
metricName: 'AuthenticationErrors',
metricValue: '1',
defaultValue: 0,
});
// Monitor database connection failures
const dbErrorFilter = new logs.MetricFilter(this, 'DatabaseErrorFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.literal('ERROR'),
logs.FilterPattern.anyTerm('database', 'connection', 'timeout')
),
metricNamespace: 'Database',
metricName: 'ConnectionErrors',
metricValue: '1',
});// Track API response times by endpoint
const apiResponseTimeFilter = new logs.MetricFilter(this, 'ApiResponseTimeFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.exists('$.endpoint'),
logs.FilterPattern.exists('$.responseTime')
),
metricNamespace: 'API/Performance',
metricName: 'ResponseTime',
metricValue: '$.responseTime',
});
// Monitor memory usage from application logs
const memoryUsageFilter = new logs.MetricFilter(this, 'MemoryUsageFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.stringValue('$.metric', '=', 'memory'),
logs.FilterPattern.exists('$.value')
),
metricNamespace: 'System',
metricName: 'MemoryUsage',
metricValue: '$.value',
});// Track successful user registrations
const registrationFilter = new logs.MetricFilter(this, 'RegistrationFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.stringValue('$.event', '=', 'user_registration'),
logs.FilterPattern.stringValue('$.status', '=', 'success')
),
metricNamespace: 'Business',
metricName: 'UserRegistrations',
metricValue: '1',
});
// Monitor revenue events
const revenueFilter = new logs.MetricFilter(this, 'RevenueFilter', {
logGroup: logGroup,
filterPattern: logs.FilterPattern.all(
logs.FilterPattern.stringValue('$.event', '=', 'purchase'),
logs.FilterPattern.exists('$.amount')
),
metricNamespace: 'Business',
metricName: 'Revenue',
metricValue: '$.amount',
});// Track HTTP status codes from space-delimited logs
const http4xxFilter = new logs.MetricFilter(this, 'Http4xxFilter', {
logGroup: webServerLogGroup,
filterPattern: logs.FilterPattern
.spaceDelimited('ip', 'user', 'time', 'method', 'path', 'status', 'size')
.whereNumber('status', '>=', 400)
.whereNumber('status', '<', 500),
metricNamespace: 'WebServer',
metricName: 'Http4xxErrors',
metricValue: '1',
});
// Monitor request sizes
const requestSizeFilter = new logs.MetricFilter(this, 'RequestSizeFilter', {
logGroup: webServerLogGroup,
filterPattern: logs.FilterPattern
.spaceDelimited('ip', 'user', 'time', 'method', 'path', 'status', 'size')
.whereNumber('size', '>', 0),
metricNamespace: 'WebServer',
metricName: 'RequestSize',
metricValue: '$size', // Extract the size field
});// Create metrics with custom dimensions using CloudWatch Metric
const customMetric = errorMetricFilter.metric({
statistic: 'Sum',
period: cdk.Duration.minutes(1),
dimensionsMap: {
'Service': 'MyApiService',
'Environment': 'Production',
},
});
// Use in dashboard
const dashboard = new cloudwatch.Dashboard(this, 'MyDashboard', {
widgets: [
[
new cloudwatch.GraphWidget({
title: 'Error Rate',
left: [customMetric],
width: 12,
height: 6,
}),
],
],
});const applicationLogGroup = new logs.LogGroup(this, 'ApplicationLogs');
// Create multiple metric filters for different aspects
const metrics = {
errors: new logs.MetricFilter(this, 'ErrorCount', {
logGroup: applicationLogGroup,
filterPattern: logs.FilterPattern.literal('ERROR'),
metricNamespace: 'Application',
metricName: 'ErrorCount',
}),
warnings: new logs.MetricFilter(this, 'WarningCount', {
logGroup: applicationLogGroup,
filterPattern: logs.FilterPattern.literal('WARN'),
metricNamespace: 'Application',
metricName: 'WarningCount',
}),
responseTime: new logs.MetricFilter(this, 'ResponseTime', {
logGroup: applicationLogGroup,
filterPattern: logs.FilterPattern.exists('$.responseTime'),
metricNamespace: 'Application',
metricName: 'ResponseTime',
metricValue: '$.responseTime',
}),
};
// Create composite alarms
const healthAlarm = new cloudwatch.CompositeAlarm(this, 'ApplicationHealth', {
alarmRule: cloudwatch.AlarmRule.anyOf(
cloudwatch.AlarmRule.fromAlarm(
new cloudwatch.Alarm(this, 'HighErrorRate', {
metric: metrics.errors.metric(),
threshold: 10,
evaluationPeriods: 2,
}),
cloudwatch.AlarmState.ALARM
),
cloudwatch.AlarmRule.fromAlarm(
new cloudwatch.Alarm(this, 'HighResponseTime', {
metric: metrics.responseTime.metric({ statistic: 'Average' }),
threshold: 2000,
evaluationPeriods: 3,
}),
cloudwatch.AlarmState.ALARM
),
),
});