Application Performance Monitoring (APM)
1 - Qu'est-ce que l'APM ?
1.1 Définition
APM = Surveillance des performances applicatives en temps réel.
1.2 Métriques clés
| Métrique | Description | Cible |
|---|---|---|
| Apdex | Score de satisfaction | > 0.9 |
| Response Time | Temps de réponse | < 200ms |
| Throughput | Requêtes/sec | Variable |
| Error Rate | % d'erreurs | < 1% |
| CPU/Memory | Ressources | < 80% |
2 - Solutions APM
2.1 Comparatif
| Solution | Type | Prix | Points forts |
|---|---|---|---|
| Datadog | SaaS | $$$ | All-in-one |
| New Relic | SaaS | $$$ | APM natif |
| Dynatrace | SaaS | $$$$ | AI-powered |
| Elastic APM | OSS/SaaS | $-$$ | ELK intégration |
| Grafana | OSS | $ | LGTM stack |
| SigNoz | OSS | Free | OpenTelemetry |
2.2 Architecture open source
3 - Elastic APM
3.1 Installation Agent
// Node.js - apm.js
const apm = require('elastic-apm-node').start({
serviceName: 'my-service',
serverUrl: 'http://apm-server:8200',
environment: 'production',
captureBody: 'all',
transactionSampleRate: 1.0,
});
module.exports = apm;
# Python
import elasticapm
app = Flask(__name__)
apm = ElasticAPM(app,
service_name='my-service',
server_url='http://apm-server:8200'
)
3.2 Configuration APM Server
# docker-compose.yml
apm-server:
image: docker.elastic.co/apm/apm-server:8.11.0
ports:
- "8200:8200"
environment:
- output.elasticsearch.hosts=["elasticsearch:9200"]
- apm-server.kibana.enabled=true
- apm-server.kibana.host=kibana:5601
3.3 Custom Transactions
const apm = require('./apm');
// Transaction manuelle
const transaction = apm.startTransaction('process-order', 'custom');
// Span
const span = apm.startSpan('database-query');
await db.query('SELECT * FROM orders');
span.end();
// Labels
apm.setLabel('order_id', orderId);
apm.setLabel('customer_tier', 'premium');
// User context
apm.setUserContext({
id: user.id,
username: user.name,
email: user.email,
});
transaction.end();
4 - SigNoz (Open Source)
4.1 Installation
# Docker
git clone https://github.com/SigNoz/signoz.git
cd signoz/deploy
./install.sh
# Kubernetes
helm repo add signoz https://charts.signoz.io
helm install signoz signoz/signoz \
--namespace monitoring \
--create-namespace
4.2 Configuration Application
// OpenTelemetry standard - compatible SigNoz
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://signoz-otel-collector:4318/v1/traces',
}),
// ...
});
5 - Profiling
5.1 Continuous Profiling
5.2 Pyroscope
# docker-compose.yml
pyroscope:
image: pyroscope/pyroscope:latest
ports:
- "4040:4040"
command: ["server"]
// Node.js agent
const Pyroscope = require('@pyroscope/nodejs');
Pyroscope.init({
serverAddress: 'http://pyroscope:4040',
appName: 'my-service',
});
Pyroscope.start();
5.3 Flame Graphs
[main]
┌─────────────────────┴──────────────────────┐
[processRequest] [handleResponse]
┌───────────┴───────────┐ │
[validateInput] [queryDatabase] [serialize]
│ │
[checkAuth] [executeSQL]
6 - Real User Monitoring (RUM)
6.1 Concept
6.2 Implementation
<!-- Elastic RUM -->
<script src="https://unpkg.com/@elastic/apm-rum"></script>
<script>
elasticApm.init({
serviceName: 'my-frontend',
serverUrl: 'https://apm.example.com',
environment: 'production',
});
</script>
// React
import { init as initApm } from '@elastic/apm-rum';
const apm = initApm({
serviceName: 'my-react-app',
serverUrl: 'https://apm.example.com',
});
// Transaction manuelle
const transaction = apm.startTransaction('user-checkout', 'user-interaction');
// ... checkout logic
transaction.end();
6.3 Métriques RUM
| Métrique | Description |
|---|---|
| LCP | Largest Contentful Paint |
| FID | First Input Delay |
| CLS | Cumulative Layout Shift |
| TTFB | Time to First Byte |
| FCP | First Contentful Paint |
7 - Dashboards APM
7.1 Service Overview
panels:
- title: "Request Rate"
type: timeseries
query: sum(rate(http_requests_total[5m])) by (service)
- title: "Error Rate"
type: stat
query: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) * 100
thresholds:
- color: green
value: 0
- color: red
value: 1
- title: "P99 Latency"
type: gauge
query: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))
- title: "Top Endpoints"
type: table
query: topk(10, sum(rate(http_requests_total[5m])) by (endpoint))
7.2 Dependency Map
8 - Alerting APM
# alerts.yml
groups:
- name: apm-alerts
rules:
- alert: HighLatencyP99
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (service, le)
) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "High P99 latency on {{ $labels.service }}"
- alert: ApdexLow
expr: |
(
sum(rate(http_request_duration_seconds_bucket{le="0.5"}[5m])) by (service)
+ sum(rate(http_request_duration_seconds_bucket{le="2.0"}[5m])) by (service) / 2
)
/ sum(rate(http_request_duration_seconds_count[5m])) by (service)
< 0.8
for: 10m
labels:
severity: critical
Résumé
Dans ce chapitre, nous avons appris :
- Les concepts APM
- Les solutions disponibles
- Elastic APM et agents
- SigNoz open source
- Le Profiling continu
- Le RUM (Real User Monitoring)
- Les Dashboards et alertes APM
Prochaine étape
Dans le prochain chapitre, nous verrons les Bonnes pratiques.
→ Chapitre suivant : Bonnes pratiques