Przejdź do głównej zawartości

Wzorce Monitorowania i Logowania

Opanuj obserwowalność z Cursor i Claude Code. Ten przewodnik obejmuje konfigurację Prometheus i Grafana, konfigurację stosu ELK, rozproszone śledzenie, strategie alarmowania oraz wzorce monitorowania produkcyjnego z pomocą AI.

  1. Inicjalizacja Stosu Monitorowania

    Okno terminala
    # Generowanie konfiguracji monitorowania
    Agent: "Utwórz stos monitorowania z:
    - Prometheus dla metryk
    - Panele Grafana
    - Reguły AlertManager
    - Wykrywanie usług
    - Agregacja logów"
  2. Instalacja Serwerów MCP do Monitorowania (opcjonalnie)

    Okno terminala
    # Grafana
    claude mcp add grafana -- npx -y @leval/mcp-grafana
    # Sentry
    claude mcp add sentry -- npx -y sentry-mcp
    # Elasticsearch
    claude mcp add es -- npx -y elasticsearch-mcp
  3. Konfiguracja Reguł AI

    # .cursorrules lub CLAUDE.md
    Najlepsze praktyki monitorowania:
    - Używaj strukturalnego logowania
    - Definiuj SLI i SLO
    - Implementuj odpowiednią kontrolę kardynalności
    - Używaj sensownych nazw metryk
    - Konfiguruj polityki retencji
    - Przestrzegaj najlepszych praktyk bezpieczeństwa
    - Implementuj optymalizację kosztów
# Prompt AI
Agent: "Utwórz konfigurację Prometheus z:
- Wykrywanie usług dla Kubernetes
- Reguły nagrywania dla wydajności
- Reguły alarmowania dla SLO
- Konfiguracja zdalnego zapisu
- Konfiguracja federacji"
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: 'production'
region: 'us-east-1'
# Konfiguracja Alertmanager
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
# Wczytywanie reguł
rule_files:
- "rules/*.yml"
- "alerts/*.yml"
# Zdalny zapis dla długoterminowego przechowywania
remote_write:
- url: "http://cortex:9009/api/v1/push"
queue_config:
max_samples_per_send: 10000
batch_send_deadline: 5s
min_backoff: 30ms
max_backoff: 100ms
write_relabel_configs:
- source_labels: [__name__]
regex: '(go_|process_).*'
action: drop
# Konfiguracje wykrywania usług
scrape_configs:
# Wykrywanie usług Kubernetes
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
# Metryki węzłów
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# Metryki podów
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
# Endpointy usług
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
# Blackbox exporter dla monitorowania endpointów
- job_name: 'blackbox'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://api.example.com
- https://app.example.com
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
rules/recording.yml
# Prompt AI: "Utwórz reguły nagrywania Prometheus dla wydajności"
groups:
- name: api_performance
interval: 30s
rules:
# Wskaźnik żądań
- record: instance:api_http_requests:rate5m
expr: |
sum by (instance, job, method, status) (
rate(http_requests_total[5m])
)
# Wskaźnik błędów
- record: job:api_http_errors:rate5m
expr: |
sum by (job) (
rate(http_requests_total{status=~"5.."}[5m])
)
# Opóźnienie P95
- record: job:api_http_latency_seconds:p95_5m
expr: |
histogram_quantile(0.95,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# Opóźnienie P99
- record: job:api_http_latency_seconds:p99_5m
expr: |
histogram_quantile(0.99,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
- name: resource_utilization
interval: 30s
rules:
# Wykorzystanie CPU
- record: instance:node_cpu:rate5m
expr: |
100 - (avg by (instance) (
irate(node_cpu_seconds_total{mode="idle"}[5m])
) * 100)
# Wykorzystanie pamięci
- record: instance:node_memory_utilization:ratio
expr: |
1 - (
node_memory_MemAvailable_bytes /
node_memory_MemTotal_bytes
)
# Wykorzystanie dysku
- record: instance:node_filesystem_utilization:ratio
expr: |
1 - (
node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.lxcfs"} /
node_filesystem_size_bytes{fstype!~"tmpfs|fuse.lxcfs"}
)
- name: business_metrics
interval: 1m
rules:
# Przychód na minutę
- record: business:revenue_usd:rate1m
expr: |
sum(increase(order_total_usd[1m]))
# Aktywni użytkownicy
- record: business:active_users:gauge
expr: |
count(
sum by (user_id) (
rate(api_requests_by_user[5m])
) > 0
)
alerts/slo.yml
# Prompt AI: "Utwórz kompleksowe reguły alarmowania z alarmami opartymi na SLO"
groups:
- name: slo_alerts
interval: 30s
rules:
# SLO dostępności API
- alert: APIAvailabilitySLO
expr: |
(
sum(rate(http_requests_total{status!~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
) < 0.995
for: 5m
labels:
severity: critical
team: platform
slo: availability
annotations:
summary: "Dostępność API poniżej SLO ({{ $value | humanizePercentage }})"
description: "Dostępność API wynosi {{ $value | humanizePercentage }}, co jest poniżej SLO wynoszącego 99.5%"
runbook: "https://runbooks.example.com/api-availability"
# SLO opóźnienia
- alert: APILatencySLO
expr: |
job:api_http_latency_seconds:p95_5m > 0.5
for: 5m
labels:
severity: warning
team: platform
slo: latency
annotations:
summary: "Opóźnienie p95 API przekracza SLO"
description: "Opóźnienie 95. percentyla wynosi {{ $value }}s (SLO: 500ms)"
# Wskaźnik zużycia budżetu błędów
- alert: ErrorBudgetBurnRate
expr: |
(
sum(rate(http_requests_total{status=~"5.."}[1h]))
/
sum(rate(http_requests_total[1h]))
) > 0.01
for: 5m
labels:
severity: warning
team: platform
annotations:
summary: "Wysoki wskaźnik zużycia budżetu błędów"
description: "Wskaźnik błędów w ciągu ostatniej godziny wynosi {{ $value | humanizePercentage }}"
- name: infrastructure_alerts
rules:
# Węzeł niedostępny
- alert: NodeDown
expr: up{job="kubernetes-nodes"} == 0
for: 2m
labels:
severity: critical
team: infrastructure
annotations:
summary: "Węzeł {{ $labels.instance }} jest niedostępny"
description: "Węzeł jest nieosiągalny od ponad 2 minut"
# Wysokie użycie CPU
- alert: HighCPUUsage
expr: instance:node_cpu:rate5m > 80
for: 10m
labels:
severity: warning
team: infrastructure
annotations:
summary: "Wysokie użycie CPU na {{ $labels.instance }}"
description: "Użycie CPU wynosi {{ $value }}%"
# Ostrzeżenie o miejscu na dysku
- alert: DiskSpaceWarning
expr: instance:node_filesystem_utilization:ratio > 0.8
for: 5m
labels:
severity: warning
team: infrastructure
annotations:
summary: "Mało miejsca na dysku na {{ $labels.instance }}"
description: "Wykorzystanie dysku wynosi {{ $value | humanizePercentage }}"
# Pod w pętli awarii
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: warning
team: platform
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} jest w pętli awarii"
description: "Pod został ponownie uruchomiony {{ $value }} razy w ciągu ostatnich 15 minut"
// Prompt AI
Agent: "Utwórz panel Grafana dla:
- Przegląd usług z SLI
- Szczegółowe metryki wydajności
- Monitorowanie infrastruktury
- Metryki biznesowe
- Status alarmów"
// dashboard.json
{
"dashboard": {
"title": "Przegląd Usług",
"uid": "service-overview",
"tags": ["production", "sli"],
"timezone": "browser",
"schemaVersion": 27,
"version": 1,
"refresh": "30s",
"time": {
"from": "now-6h",
"to": "now"
},
"templating": {
"list": [
{
"name": "datasource",
"type": "datasource",
"query": "prometheus",
"current": {
"text": "Prometheus",
"value": "prometheus"
}
},
{
"name": "namespace",
"type": "query",
"datasource": "$datasource",
"query": "label_values(kube_namespace_created, namespace)",
"refresh": 1,
"multi": true,
"includeAll": true
},
{
"name": "service",
"type": "query",
"datasource": "$datasource",
"query": "label_values(up{namespace=~\"$namespace\"}, job)",
"refresh": 1,
"multi": true,
"includeAll": true
}
]
},
"panels": [
{
"title": "Wskaźniki Poziomu Usługi",
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 0},
"type": "row",
"collapsed": false,
"panels": [
{
"title": "Dostępność",
"gridPos": {"h": 8, "w": 6, "x": 0, "y": 1},
"type": "stat",
"targets": [
{
"expr": "sum(rate(http_requests_total{status!~\"5..\",namespace=~\"$namespace\",job=~\"$service\"}[5m])) / sum(rate(http_requests_total{namespace=~\"$namespace\",job=~\"$service\"}[5m]))",
"format": "time_series",
"legendFormat": "Dostępność"
}
],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "red", "value": null},
{"color": "yellow", "value": 0.99},
{"color": "green", "value": 0.995}
]
}
}
}
},
{
"title": "Wskaźnik Żądań",
"gridPos": {"h": 8, "w": 6, "x": 6, "y": 1},
"type": "graph",
"targets": [
{
"expr": "sum(rate(http_requests_total{namespace=~\"$namespace\",job=~\"$service\"}[5m])) by (status)",
"legendFormat": "{{status}}"
}
],
"yaxes": [
{"format": "reqps", "label": "Żądań/sek"}
]
},
{
"title": "Opóźnienie P95",
"gridPos": {"h": 8, "w": 6, "x": 12, "y": 1},
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{namespace=~\"$namespace\",job=~\"$service\"}[5m])) by (le))",
"legendFormat": "p95"
}
],
"yaxes": [
{"format": "s", "label": "Opóźnienie"}
],
"alert": {
"conditions": [
{
"evaluator": {
"params": [0.5],
"type": "gt"
},
"query": {
"params": ["A", "5m", "now"]
},
"reducer": {
"params": [],
"type": "avg"
},
"type": "query"
}
],
"name": "Wysokie Opóźnienie P95",
"noDataState": "no_data",
"notifications": []
}
},
{
"title": "Wskaźnik Błędów",
"gridPos": {"h": 8, "w": 6, "x": 18, "y": 1},
"type": "stat",
"targets": [
{
"expr": "sum(rate(http_requests_total{status=~\"5..\",namespace=~\"$namespace\",job=~\"$service\"}[5m])) / sum(rate(http_requests_total{namespace=~\"$namespace\",job=~\"$service\"}[5m]))",
"legendFormat": "Wskaźnik Błędów"
}
],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 0.01},
{"color": "red", "value": 0.05}
]
}
}
}
}
]
},
{
"title": "Metryki Infrastruktury",
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 9},
"type": "row",
"panels": [
{
"title": "Użycie CPU",
"gridPos": {"h": 8, "w": 8, "x": 0, "y": 10},
"type": "graph",
"targets": [
{
"expr": "sum(rate(container_cpu_usage_seconds_total{namespace=~\"$namespace\",pod=~\".*$service.*\"}[5m])) by (pod)",
"legendFormat": "{{pod}}"
}
]
},
{
"title": "Użycie Pamięci",
"gridPos": {"h": 8, "w": 8, "x": 8, "y": 10},
"type": "graph",
"targets": [
{
"expr": "sum(container_memory_working_set_bytes{namespace=~\"$namespace\",pod=~\".*$service.*\"}) by (pod)",
"legendFormat": "{{pod}}"
}
],
"yaxes": [
{"format": "bytes"}
]
},
{
"title": "I/O Sieciowe",
"gridPos": {"h": 8, "w": 8, "x": 16, "y": 10},
"type": "graph",
"targets": [
{
"expr": "sum(rate(container_network_receive_bytes_total{namespace=~\"$namespace\",pod=~\".*$service.*\"}[5m])) by (pod)",
"legendFormat": "RX {{pod}}"
},
{
"expr": "-sum(rate(container_network_transmit_bytes_total{namespace=~\"$namespace\",pod=~\".*$service.*\"}[5m])) by (pod)",
"legendFormat": "TX {{pod}}"
}
],
"yaxes": [
{"format": "Bps"}
]
}
]
}
]
}
}

Najlepsze Praktyki Monitorowania i Logowania

  1. Definiuj SLI/SLO - Ustal jasne wskaźniki i cele poziomu usług
  2. Używaj Strukturalnego Logowania - Format JSON z konsekwentnymi polami
  3. Implementuj Próbkowanie - Równoważ widoczność z kosztami
  4. Koreluj Sygnały - Łącz metryki, logi i ślady
  5. Automatyzuj Reakcje - Twórz runbooki i auto-remediację
  6. Monitoruj Monitory - Zapewniaj zdrowie stosu obserwowalności
Okno terminala
# Prompt AI: "Wygeneruj polecenia debugowania monitorowania"
# Zapytania Prometheus
# Sprawdzanie celów scrapowania
curl http://prometheus:9090/api/v1/targets | jq '.data.activeTargets[] | select(.health != "up")'
# Zapytanie o kardynalność metryk
curl -G http://prometheus:9090/api/v1/query \
--data-urlencode 'query=prometheus_tsdb_symbol_table_size_bytes'
# Zdrowie klastra Elasticsearch
curl -X GET "elasticsearch:9200/_cluster/health?pretty"
curl -X GET "elasticsearch:9200/_cat/indices?v&s=store.size:desc"
# Zależności usług Jaeger
curl http://jaeger-query:16686/api/dependencies?endTs=$(date +%s)000&lookback=3600000
# Metryki OpenTelemetry Collector
curl http://otel-collector:8888/metrics