CloudWatch et X-Ray
1 - Amazon CloudWatch
1.1 Composants CloudWatch
2 - CloudWatch Metrics
2.1 Métriques personnalisées
# Publier une métrique custom
aws cloudwatch put-metric-data \
--namespace "MonApplication" \
--metric-name "OrdersProcessed" \
--value 25 \
--unit Count \
--dimensions Environment=Production,Service=OrderService
2.2 Via SDK (Python)
import boto3
cloudwatch = boto3.client('cloudwatch')
# Publier des métriques
cloudwatch.put_metric_data(
Namespace='MonApplication',
MetricData=[
{
'MetricName': 'RequestLatency',
'Dimensions': [
{'Name': 'Service', 'Value': 'API'},
{'Name': 'Environment', 'Value': 'Production'}
],
'Value': 125.5,
'Unit': 'Milliseconds'
},
{
'MetricName': 'ErrorCount',
'Value': 3,
'Unit': 'Count'
}
]
)
3 - CloudWatch Alarms
3.1 Créer une alarme
# CloudFormation
HighCPUAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: HighCPU-Production
AlarmDescription: CPU above 80% for 5 minutes
MetricName: CPUUtilization
Namespace: AWS/EC2
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: AutoScalingGroupName
Value: !Ref ASG
AlarmActions:
- !Ref SNSTopic
- !Ref ScaleUpPolicy
OKActions:
- !Ref SNSTopic
3.2 Alarme composite
CompositeAlarm:
Type: AWS::CloudWatch::CompositeAlarm
Properties:
AlarmName: CriticalServiceHealth
AlarmRule: |
ALARM(HighCPUAlarm) AND
(ALARM(HighMemoryAlarm) OR ALARM(HighErrorRateAlarm))
AlarmActions:
- !Ref PagerDutyTopic
4 - CloudWatch Logs
4.1 Configuration
# CloudFormation - Log Group
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /ecs/mon-application
RetentionInDays: 30
Tags:
- Key: Environment
Value: Production
# Metric Filter
ErrorMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref LogGroup
FilterPattern: "[timestamp, requestId, level=ERROR, ...]"
MetricTransformations:
- MetricName: ErrorCount
MetricNamespace: MonApplication
MetricValue: "1"
DefaultValue: 0
4.2 CloudWatch Agent
// amazon-cloudwatch-agent.json
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "cwagent"
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/app/*.log",
"log_group_name": "/app/logs",
"log_stream_name": "{instance_id}",
"retention_in_days": 30
}
]
}
}
},
"metrics": {
"namespace": "CustomMetrics",
"metrics_collected": {
"cpu": {
"measurement": ["cpu_usage_idle", "cpu_usage_user"],
"metrics_collection_interval": 60
},
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
},
"disk": {
"measurement": ["disk_used_percent"],
"resources": ["/"],
"metrics_collection_interval": 60
}
}
}
}
4.3 Logs Insights
-- Erreurs par minute
fields @timestamp, @message
| filter @message like /ERROR/
| stats count() as errorCount by bin(1m)
| sort @timestamp desc
-- Latence P99
fields @timestamp, latency
| filter latency > 0
| stats percentile(latency, 99) as p99,
percentile(latency, 95) as p95,
avg(latency) as avg_latency
by bin(5m)
-- Top 10 des erreurs
fields @timestamp, @message, errorType
| filter level = "ERROR"
| stats count() as count by errorType
| sort count desc
| limit 10
5 - AWS X-Ray
5.1 Concepts
5.2 Instrumentation Node.js
// app.js
const AWSXRay = require('aws-xray-sdk');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const express = require('express');
const app = express();
// Middleware X-Ray
app.use(AWSXRay.express.openSegment('MonApplication'));
// Route instrumentée
app.get('/api/users', async (req, res) => {
const segment = AWSXRay.getSegment();
const subsegment = segment.addNewSubsegment('fetchUsers');
try {
const dynamodb = new AWS.DynamoDB.DocumentClient();
const result = await dynamodb.scan({
TableName: 'Users'
}).promise();
subsegment.addAnnotation('userCount', result.Items.length);
subsegment.close();
res.json(result.Items);
} catch (error) {
subsegment.addError(error);
subsegment.close();
res.status(500).json({ error: error.message });
}
});
app.use(AWSXRay.express.closeSegment());
5.3 Instrumentation Python
# app.py
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware
# Patch automatique des libs AWS
patch_all()
from flask import Flask
app = Flask(__name__)
# Middleware X-Ray
xray_recorder.configure(service='MonApplication')
XRayMiddleware(app, xray_recorder)
@app.route('/api/data')
@xray_recorder.capture('get_data')
def get_data():
# Créer un subsegment
subsegment = xray_recorder.begin_subsegment('process_data')
try:
# Logique métier
result = process()
subsegment.put_annotation('result_count', len(result))
return jsonify(result)
finally:
xray_recorder.end_subsegment()
5.4 X-Ray pour Lambda
# SAM template
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: app.handler
Runtime: python3.11
Tracing: Active # Active X-Ray
Environment:
Variables:
AWS_XRAY_TRACING_NAME: MonApplication
6 - Dashboards
6.1 Dashboard CloudFormation
Dashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: Application-Overview
DashboardBody: !Sub |
{
"widgets": [
{
"type": "metric",
"x": 0, "y": 0, "width": 12, "height": 6,
"properties": {
"title": "CPU Utilization",
"metrics": [
["AWS/ECS", "CPUUtilization", "ServiceName", "${ECSService}"]
],
"period": 300,
"stat": "Average",
"region": "${AWS::Region}"
}
},
{
"type": "log",
"x": 12, "y": 0, "width": 12, "height": 6,
"properties": {
"title": "Error Logs",
"query": "SOURCE '/ecs/app' | filter @message like /ERROR/ | stats count() by bin(5m)",
"region": "${AWS::Region}"
}
}
]
}
7 - Intégration avec CodePipeline
# buildspec.yml - Métriques de build
phases:
post_build:
commands:
- |
aws cloudwatch put-metric-data \
--namespace "CI/CD" \
--metric-name "BuildDuration" \
--value $CODEBUILD_BUILD_DURATION \
--unit Seconds \
--dimensions Project=$CODEBUILD_PROJECT
- |
if [ "$CODEBUILD_BUILD_SUCCEEDING" = "1" ]; then
STATUS=1
else
STATUS=0
fi
aws cloudwatch put-metric-data \
--namespace "CI/CD" \
--metric-name "BuildSuccess" \
--value $STATUS \
--unit Count
Résumé
Dans ce chapitre, nous avons appris :
- Les métriques CloudWatch et custom metrics
- Les alarmes simples et composites
- Les logs et Logs Insights
- Le tracing distribué avec X-Ray
- La création de dashboards
Prochaine étape
Dans le prochain chapitre, nous verrons IAM et Sécurité pour les pipelines.
→ Chapitre suivant : IAM et Sécurité