Instrumentation personnalisée Go
Rapport de recherche Datadog : Bilan sur l'adoption de l'informatique sans serveur Rapport : Bilan sur l'adoption de l'informatique sans serveur

Instrumentation personnalisée Go

Si vous n'avez pas encore lu les instructions d'instrumentation automatique et de configuration, commencez par les Instructions de configuration Go.

Cette page décrit des méthodes courantes pour configurer et personnaliser la visibilité sur votre application avec l’APM Datadog.

Ajout de tags

Ajoutez des tags de span personnalisés à vos spans pour personnaliser votre visibilité dans Datadog. Les tags de span sont appliqués à vos traces entrantes, ce qui vous permet de corréler le comportement observé avec des informations au niveau du code, comme le niveau du commerçant, le montant du paiement ou l’ID de l’utilisateur.

Ajouter des tags de span personnalisés

Ajoutez directement des tags à une interface Span en appelant SetTag :

package main

import (
    "log"
    "net/http"

    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Créer une span pour une requête Web au niveau de l'URL /posts.
    span := tracer.StartSpan("web.request", tracer.ResourceName("/posts"))
    defer span.Finish()

    // Set tag
    span.SetTag("http.url", r.URL.Path)
    span.SetTag("<CLÉ_VALUE>", "<VALEUR_TAG>")
}

func main() {
    tracer.Start(tracer.WithServiceName("<NOM_SERVICE>"))
    defer tracer.Stop()
    http.HandleFunc("/posts", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Les intégrations de Datadog utilisent le type Context pour propager la span active. Si vous souhaitez ajouter des tags à une span associée à un Context, appelez la fonction SpanFromContext :

package main

import (
    "net/http"

    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Récupérer une span pour une requête Web associée à un contexte Go.
    if span, ok := tracer.SpanFromContext(r.Context()); ok {
        // Définir un tag
        span.SetTag("http.url", r.URL.Path)
    }
}

Ajouter des tags à l’ensemble des spans

Ajoutez des tags à l’ensemble des spans en configurant l’option WithGlobalTag du traceur :

package main

import "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"

func main() {
    tracer.Start(
        tracer.WithGlobalTag("datacenter", "us-1"),
        tracer.WithGlobalTag("env", "dev"),
    )
    defer tracer.Stop()
}

Définir des erreurs sur une span

Pour définir une erreur sur une de vos spans, utilisez tracer.WithError comme ci-dessous :

err := someOperation()
span.Finish(tracer.WithError(err))

Ajout de spans

Si vous n’utilisez pas une instrumentation de bibliothèque compatible (voir la compatibilité des bibliothèques), vous pouvez choisir d’instrumenter manuellement votre code.

Créer manuellement une nouvelle span

Afin de bénéficier d’une instrumentation manuelle, utilisez le package tracer, dont l’utilisation est documentée sur la page GoDoc de Datadog :

Deux fonctions permettent de créer des spans. Les détails de l’API sont disponibles pour StartSpan ici et pour StartSpanFromContext ici.

//Créer une span
span := tracer.StartSpan(mainOp, tracer.ResourceName("/user"), tracer.ChildOf(parentSpan))

//Créer une span avec un nom de ressource, qui est l'enfant de parentSpan.
span := tracer.StartSpan(mainOp, tracer.ResourceName("/user"), tracer.ChildOf(parentSpan))

// Créer une span qui sera l'enfant de la span dans le contexte ctx, si une span figure dans le contexte.
// Renvoie la nouvelle span, et un nouveau contexte contenant la nouvelle span.
span, ctx := tracer.StartSpanFromContext(ctx, mainOp, tracer.ResourceName("/user"))

Traces asynchrones

func main() {
    span, ctx := tracer.StartSpanFromContext(context.Background(), mainOp)
    defer span.Finish()

    go func() {
        asyncSpan := tracer.StartSpanFromContext(ctx, asyncOp)
        defer asyncSpan.Finish()
        performOp()
    }()
}

Tracing distribué

Créez une trace distribuée en propageant manuellement le contexte de tracing :

package main

import (
    "net/http"

    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    span, ctx := tracer.StartSpanFromContext(r.Context(), "post.process")
    defer span.Finish()

    req, err := http.NewRequest("GET", "http://example.com", nil)
    req = req.WithContext(ctx)
    // Injecter le contexte de la span dans les en-têtes de requête
    err = tracer.Inject(span.Context(), tracer.HTTPHeadersCarrier(req.Header))
    if err != nil {
        // Erreur de traitement ou d'injection de log
    }
    http.DefaultClient.Do(req)
}

Pour continuer la trace, initialisez une nouvelle span côté serveur à partir du Context extrait :

package main

import (
    "net/http"

    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Extraire le contexte de la span et continuer la trace dans ce service
    sctx, err := tracer.Extract(tracer.HTTPHeadersCarrier(r.Header))
    if err != nil {
        // Erreur de traitement ou d'extraction de log
    }

    span := tracer.StartSpan("post.filter", tracer.ChildOf(sctx))
    defer span.Finish()
}

Configuration de l’Agent et du client de tracing

D’autres paramètres peuvent être configurés au niveau du client de tracing et de l’Agent Datadog pour la propagation en contexte avec les en-têtes B3, ainsi que pour empêcher des ressources spécifiques d’envoyer des traces à Datadog (si vous ne souhaitez pas que ces ces traces soient prises en compte pour le calcul des métriques, comme pour les checks de santé).

Extraction et injection d’en-têtes B3

Le traceur de l’APM Datadog prend en charge l’extraction et l’injection d’en-têtes B3 pour le tracing distribué.

L’injection et l’extraction distribuées d’en-têtes sont contrôlées en configurant des styles d’injection/extraction. Deux styles sont actuellement pris en charge : Datadog et B3.

Configurez les styles d’injection via la variable d’environnement : DD_PROPAGATION_STYLE_INJECT=Datadog,B3

Configurez les styles d’extraction via la variable d’environnement : DD_PROPAGATION_STYLE_EXTRACT=Datadog,B3

Ces variables d’environnement prennent comme valeur une liste des styles d’en-tête autorisés pour l’injection ou l’extraction, séparés par des virgules. Par défaut, le style d’extraction Datadog est activé.

Si plusieurs styles d’extraction sont activés, les tentative d’extraction sont effectuées dans l’ordre selon lequel ces styles ont été configurés, et la première valeur extraite avec succès est utilisée.

Filtrage de ressources

Vous pouvez configurer l’Agent de façon à exclure une ressource spécifique des traces envoyées par l’Agent à l’application Datadog. Pour empêcher l’envoi de ressources spécifiques, utilisez le paramètre ignore_resources dans le fichier datadog.yaml. Ce paramètre permet la création d’une liste contenant une ou plusieurs expressions régulières, qui indique à l’Agent de filtrer les traces en fonction de leur nom de ressource.

En cas d’exécution dans un environnement conteneurisé, définissez plutôt DD_APM_IGNORE_RESOURCES sur le conteneur avec l’Agent Datadog. Pour en savoir plus, consultez la documentation ici.

Cela peut être utile pour exclure un check de santé ou tout autre trafic simulé du calcul des métriques de vos services.

## @param ignore_resources - liste de chaînes, facultatif
## Une liste d'expressions régulières peut être spécifiée pour exclure certaines traces en fonction de leur nom de ressource.
## Toutes les entrées doivent être entourées de guillemets doubles et séparées par des virgules.
# ignore_resources: ["(GET|POST) /healthcheck"]

OpenTracing

Datadog prend également en charge la norme OpenTracing. Pour en savoir plus, consultez l’API OpenTracing ou les informations de configuration ci-dessous.

Configuration

Importez le package opentracer pour exposer le traceur Datadog en tant que traceur compatible avec OpenTracing.

Un exemple d’utilisation courante :

package main

import (
    "github.com/opentracing/opentracing-go"

    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
    "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func main() {
    // Lancer le traceur normal et le renvoyer sous la forme d'une interface opentracing.Tracer. Vous
    // pouvez utiliser le même ensemble d'options que celui que vous utilisez habituellement avec le traceur Datadog.
    t := opentracer.New(tracer.WithServiceName("<NOM_SERVICE>"))

    // Arrêter le traceur à l'aide de l'appel Stop habituel pour le paquet du traceur.
    defer tracer.Stop()

    // Définir le traceur OpenTracing global.
    opentracing.SetGlobalTracer(t)

    // Utiliser comme d'habitude l'API OpenTracing.
}

Remarque : vous pouvez utiliser l’API OpenTracing conjointement avec l’API normale ou les intégrations Datadog. Elles se basent toutes sur le même traceur. Consultez la documentation relative à l’API pour obtenir davantage d’exemples et de détails.

Pour aller plus loin