RousselTMLEARNING

TP · Opentelemetry : de la découverte à l'expertise

TP : Profiler une application et relier profils et traces avec correction

La correction est intégrée au TP (Voir les encadrés de couleur vert)

Ce que vous allez apprendre dans ce TP
  • Envoyer des profils continus
  • Lire un flame graph
  • Relier spans et profils

Introduction #

Ce que vous allez apprendre dans cette section
  • Envoyer des profils continus
  • Lire un flame graph
  • Relier spans et profils

Contexte. Un service de calcul de remises est lent et coûteux en CPU, mais ses traces montrent seulement un span long. Vous ajoutez le quatrième signal pour trouver la ligne responsable.

Prérequis : Docker et Python 3.10 ou plus ; la pile grafana/otel-lgtm (Collector, Tempo, Loki, Prometheus, Pyroscope et Grafana dans un seul conteneur)  ·  Durée estimée : 45 min

Un goulet d'étranglement identifié dans le code grâce au lien span-profil, puis corrigé et mesuré.

Mise en place #

Étapes guidées, avec leur correction.

  1. 1. Démarrer la pile d'observabilité

    Pourquoi ? Une seule image fournit un Collector OTLP et tous les backends : on se concentre sur le signal.

    Lancez grafana/otel-lgtm, créez un environnement Python et pointez les exportateurs vers le port OTLP/HTTP 4318.
    Voir la correction
    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. Un service lent

    Pourquoi ? Le code contient un défaut classique : une expression régulière recompilée et une concaténation coûteuse à chaque appel.

    Installez le SDK Pyroscope et son intégration OpenTelemetry, puis écrivez remises.py : traces vers Tempo, profils vers Pyroscope avec le même nom de service, et le PyroscopeSpanProcessor.
    Voir la correction
    pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http pyroscope-io pyroscope-otel
    cat > remises.py <<'EOF'
    import random, re, time
    import pyroscope
    from pyroscope.otel import PyroscopeSpanProcessor
    from opentelemetry import trace
    from opentelemetry.sdk.resources import Resource
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
    
    pyroscope.configure(application_name="remises", server_address="http://localhost:4040", tags={"env": "tp"})
    provider = TracerProvider(resource=Resource.create({"service.name": "remises"}))
    provider.add_span_processor(PyroscopeSpanProcessor())
    provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
    trace.set_tracer_provider(provider)
    tracer = trace.get_tracer("tp.remises")
    
    def code_valide(code):
        motif = re.compile(r"^(PROMO|VIP)-[0-9]{4}" + "(-X)?" * random.randint(20, 40) + "$")   # recompilé à chaque appel
        return bool(motif.match(code))
    
    def calculer_remise(panier):
        texte = ""
        for article in panier:
            texte += f"{article};"                       # concaténation quadratique
        return sum(1 for a in panier if code_valide(a)) * 5
    
    while True:
        with tracer.start_as_current_span("calculer remise") as span:
            panier = [f"PROMO-{random.randint(1000, 9999)}" for _ in range(random.randint(200, 800))]
            span.set_attribute("shop.cart.items", len(panier))
            calculer_remise(panier)
        time.sleep(0.05)
    EOF
    python remises.py &
  3. 3. Lire le flame graph

    Pourquoi ? Le flame graph montre où le CPU est réellement consommé, sans ajouter un seul span.

    Dans Explore > Pyroscope (ou Drilldown > Profiles), sélectionnez l'application remises et le type CPU. Identifiez les plateaux les plus larges et la part de code_valide et de re.compile.
    Voir la correction
    # requête Pyroscope
    process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name="remises"}
    # attendu : calculer_remise > code_valide > re.compile / sre_compile très larges
  4. 4. Du span au profil

    Pourquoi ? Le span processor étiquette les échantillons avec le span_id : on obtient le profil d'une requête précise.

    Dans Tempo, ouvrez une trace calculer remise longue et utilisez Profiles for this span. Si le lien n'apparaît pas, configurez Trace to profiles dans la source de données Tempo (source Pyroscope, type CPU).
    Voir la correction
    { resource.service.name = "remises" && duration > 300ms }
    # span sélectionné > Profiles for this span : flame graph limité à ce span
    # vérifier l'attribut pyroscope.profile.id ajouté au span par le PyroscopeSpanProcessor
  5. 5. Corriger et comparer

    Pourquoi ? Le profil prouve l'effet d'une optimisation, au lieu de le supposer.

    Compilez l'expression une seule fois au niveau du module et remplacez la concaténation par ';'.join(). Relancez, puis comparez les deux périodes avec la vue Diff de Pyroscope et la durée des spans dans Tempo.
    Voir la correction
    kill %1
    python - <<'EOF'
    s = open("remises.py").read()
    s = s.replace('def code_valide(code):\n    motif = re.compile(r"^(PROMO|VIP)-[0-9]{4}" + "(-X)?" * random.randint(20, 40) + "$")   # recompilé à chaque appel\n    return bool(motif.match(code))',
                  'MOTIF = re.compile(r"^(PROMO|VIP)-[0-9]{4}(-X)*$")\n\ndef code_valide(code):\n    return bool(MOTIF.match(code))')
    s = s.replace('    texte = ""\n    for article in panier:\n        texte += f"{article};"                       # concaténation quadratique\n', '    texte = ";".join(panier)\n')
    open("remises.py", "w").write(s)
    EOF
    python remises.py &
    # Tempo : avg_over_time des durées { name = "calculer remise" } ; Pyroscope : Diff avant / après
  6. 6. Situer les profils OpenTelemetry

    Pourquoi ? Le SDK Pyroscope est une solution éprouvée ; le signal OTLP Profiles vise à unifier la collecte, mais n'est pas encore stable.

    Consultez la page de statut du signal profiles sur opentelemetry.io et la documentation du profileur eBPF OpenTelemetry. Rédigez en trois lignes ce qu'il faudrait pour remplacer le SDK par le profileur eBPF et un Collector, puis arrêtez la pile.
    Voir la correction
    kill %1 ; docker rm -f lgtm
    # Pistes : profileur eBPF en DaemonSet (privilégié, noyau récent), Collector avec feature gate profiles,
    # exportateur OTLP vers Pyroscope, mêmes attributs de ressource que les traces

Niveau de difficulté : ●●●○○ (3/5)

Mon suivi

  • ⏱ Durée estimée : ≈ 45 min

Connectez-vous pour suivre votre progression et prendre des notes. Se connecter

✉️ Poser une question

Articles recommandés

Les profils, le quatrième signal d'OpenTelemetry : profilage continu et corrélation avec les traces

Comprendre le nouveau signal profile d'OpenTelemetry : profilage continu, flame graphs, modèle de...

Comprendre la notion de score

Le concept de score va permettre à Elasticsearch de classer vos documents par pertinence lors d u...

Elastic Common Schema (ECS) : le format standard des données Elastic et son rôle dans Elastic SIEM

Comprendre l'Elastic Common Schema (ECS) : format standard des champs dans Elasticsearch, convent...

Grail : Dynatrace Data Lakehouse

Désormais vous disposez dans Dynatrace (SaaS) d'un Data Lakehouse nommé Grail dont vous pouvez co...

C'est quoi l'observabilité

La capacité à connaître l'état interne d'un système à partir des données que cette dernière émet...

Les types de transactions dans les base de données

Cet article détaille les différences entre trois concepts essentiels dans l'exécution des instruc...

Différences entre Technologies et Services dans Dynatrace

Dans Dynatrace, les concepts de 'Technologie' et de 'Services' aident à organiser et surveiller l...

Dynatrace : Différences entre SQL Modifications, SQL Queries or Procedures, et SQL Transactions

Cet article détaille les différences entre trois concepts essentiels dans l'exécution des instruc...

Licences Dynatrace : modèle par unités et consumption-based licensing (DPS)

Comprendre la facturation Dynatrace : l'ancien modèle de licences segmentées par unités (Host Uni...