Aller au contenu principal

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é


← Retour à la table des matières