RousselTMLEARNING

TP · OpenTelemetry: del descubrimiento a la experiencia

Práctica: Correlacionar las cuatro señales de dos servicios auto-instrumentados con corrección

La corrección está integrada en el TP (Ver los recuadros verdes)

Lo que vas a aprender en este TP
  • Auto-instrumentar todas las señales
  • Garantizar un recurso común
  • Navegar entre las señales

Introducción #

Lo que vas a aprender en esta sección
  • Auto-instrumentar todas las señales
  • Garantizar un recurso común
  • Navegar entre las señales

Contexto. Una tienda de dos servicios devuelve errores de forma intermitente. Instrumentas sin tocar el código e investigas navegando de una señal a otra.

Requisitos previos: Docker y Python 3.10 o superior; la pila grafana/otel-lgtm (Collector, Tempo, Loki, Prometheus, Pyroscope y Grafana en un solo contenedor)  ·  Duración estimada: 50 min

Una causa encontrada en unos clics gracias a un recurso común y a los identificadores compartidos.

Puesta en práctica #

Pasos guiados, con su corrección.

  1. 1. Arrancar la pila de observabilidad

    ¿Por qué? Una sola imagen proporciona un Collector OTLP y todos los backends: nos centramos en la señal.

    Lanza grafana/otel-lgtm, crea un entorno Python y apunta los exportadores al puerto OTLP/HTTP 4318.
    Ver la corrección
    docker run -d --name lgtm -p 3000:3000 -p 4317:4317 -p 4318:4318 -p 4040:4040 grafana/otel-lgtm
    python3 -m venv .venv && . .venv/bin/activate
    export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
    # Grafana : http://localhost:3000 (admin / admin)
  2. 2. Escribir los dos servicios

    ¿Por qué? El código no contiene ninguna línea de OpenTelemetry: todo vendrá de la auto-instrumentación.

    Crea front.py (puerto 8001) que llame a stock.py (puerto 8002); el servicio de stock falla en el 15 % de las peticiones con un log de error.
    Ver la corrección
    pip install flask requests opentelemetry-distro opentelemetry-exporter-otlp
    opentelemetry-bootstrap -a install          # installe les instrumentations Flask, requests, logging…
    cat > stock.py <<'EOF'
    import logging, random, time
    from flask import Flask
    app = Flask(__name__)
    log = logging.getLogger("stock")
    @app.get("/stock/<sku>")
    def stock(sku):
        time.sleep(random.uniform(0.01, 0.08))
        if random.random() < 0.15:
            log.error("pool de connexions épuisé pour %s", sku)
            return {"error": "indisponible"}, 503
        return {"sku": sku, "qty": random.randint(0, 40)}
    app.run(port=8002)
    EOF
    cat > front.py <<'EOF'
    import logging, random, requests
    from flask import Flask
    app = Flask(__name__)
    log = logging.getLogger("front")
    @app.get("/produit")
    def produit():
        sku = f"SKU-{random.randint(1, 50)}"
        r = requests.get(f"http://localhost:8002/stock/{sku}", timeout=2)
        if r.status_code != 200:
            log.warning("stock indisponible pour %s", sku)
            return {"error": "réessayez"}, 502
        return r.json()
    app.run(port=8001)
    EOF
  3. 3. Arrancar con un recurso común

    ¿Por qué? Las mismas variables para las tres señales garantizan el mismo recurso: es la clave de la correlación.

    Lanza cada servicio con opentelemetry-instrument, los tres exportadores OTLP, la captura de logs y atributos de recurso comunes, y genera tráfico.
    Ver la corrección
    export OTEL_TRACES_EXPORTER=otlp OTEL_METRICS_EXPORTER=otlp OTEL_LOGS_EXPORTER=otlp
    export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true OTEL_METRIC_EXPORT_INTERVAL=5000
    export OTEL_RESOURCE_ATTRIBUTES=service.namespace=boutique,service.version=1.3.0,deployment.environment.name=tp
    OTEL_SERVICE_NAME=stock opentelemetry-instrument python stock.py &
    OTEL_SERVICE_NAME=front opentelemetry-instrument python front.py &
    sleep 3 ; for i in $(seq 1 400); do curl -s -o /dev/null localhost:8001/produit; done
  4. 4. Partir de la métrica

    ¿Por qué? La investigación empieza como una alerta: una métrica de errores procedente de las convenciones HTTP, idéntica para todos los servicios.

    En Prometheus, calcula la tasa de errores 5xx por servicio a partir del histograma http.server.request.duration (o su equivalente según la versión de instrumentación). Activa los exemplars y abre una traza desde un punto.
    Ver la corrección
    sum by (job) (rate(http_server_request_duration_seconds_count{http_response_status_code=~"5.."}[1m]))
      / sum by (job) (rate(http_server_request_duration_seconds_count[1m]))
    # anciennes conventions : http_server_duration_milliseconds_count{http_status_code=~"5.."}
  5. 5. De la traza a los logs

    ¿Por qué? La traza muestra qué servicio ha fallado; sus logs dicen por qué.

    En Tempo, busca las trazas con error, abre una, comprueba que el span servidor de stock está en 503 y usa Logs for this span para encontrar el mensaje «pool de conexiones agotado». Haz el camino inverso desde Loki.
    Ver la corrección
    { resource.service.namespace = "boutique" && status = error }
    { resource.service.name = "front" } >> { resource.service.name = "stock" && span.http.response.status_code = 503 }
    # Loki : {service_name="stock"} | severity_text="ERROR"  -> champ trace_id -> lien Tempo
  6. 6. Mapa de servicios y métricas de spans

    ¿Por qué? Las métricas calculadas a partir de los spans dan ritmo, errores y duración por servicio y un mapa de dependencias.

    Abre la pestaña Service Graph de Tempo en Explore: comprueba la arista de front hacia stock y su tasa de error. Anota la línea de configuración (conector servicegraph o generador de métricas de Tempo) que lo hace posible.
    Ver la corrección
    traces_service_graph_request_failed_total{client="front", server="stock"}
    traces_spanmetrics_calls_total{service="stock", status_code="STATUS_CODE_ERROR"}
    # selon la version de l'image, ces métriques viennent du generator de Tempo ou des connecteurs du Collector
  7. 7. Romper y reparar la correlación

    ¿Por qué? Un recurso diferente basta para romper todos los enlaces: se comprueba para recordarlo.

    Reinicia stock con OTEL_LOGS_EXPORTER=none, genera tráfico de nuevo y comprueba que Logs for this span ya no devuelve nada. Restablece la configuración y detén todo.
    Ver la corrección
    pkill -f "python stock.py"
    OTEL_LOGS_EXPORTER=none OTEL_SERVICE_NAME=stock opentelemetry-instrument python stock.py &
    for i in $(seq 1 100); do curl -s -o /dev/null localhost:8001/produit; done
    pkill -f "opentelemetry-instrument python" ; pkill -f "python front.py" ; pkill -f "python stock.py"

Nivel de dificultad : ●●●○○ (3/5)

Mi seguimiento

  • ⏱ Duración estimada : ≈ 50 min

Inicia sesión para seguir tu progreso y tomar notas. Iniciar sesión

✉️ Hacer una pregunta

Artículos recomendados

Corréler traces, métriques, logs et profils avec OpenTelemetry

Relier les quatre signaux pour diagnostiquer vite : ressource commune, trace_id dans les logs, ex...

Les métriques OpenTelemetry : instruments, temporalité, histogrammes et exemplars

Maîtriser le signal métrique : MeterProvider, instruments synchrones et asynchrones (Counter, UpD...

Les logs avec OpenTelemetry : modèle de données, appenders, corrélation et collecte

Maîtriser le signal log : modèle de données LogRecord, Logs Bridge API et appenders (Logback, Log...

Grafana Alloy: Perfilado Continuo con Pyroscope

Descubra cómo configurar el perfilado continuo (Continuous Profiling) en sus entornos utilizando ...