Tutoriel : Instrumenter un framework Java HTTP personnalisé avec le SDK de traçage Instana

L'agent Instana prend en charge de nombreux frameworks Java HTTP et, dans la plupart des cas, le traçage est pris en charge dès que vous exécutez l'agent Java.

Toutefois, si vous disposez d'un serveur HTTP interne personnalisé qui n'est pas pris en charge, vous pouvez utiliser le SDK Java Trace pour ajouter le traçage pour votre cadre.

Ce tutoriel explique comment procéder.

Exemple de code

L'exemple de code du tutoriel custom-http-sample est disponible sur le site github.com. Il implémente le scénario suivant :

tutoriel sur le serveur HTTP personnalisé

Si vous exécutez l'exemple et ouvrez http://localhost:8080, vous obtiendrez la réponse Hello, Stan!. Cependant, si vous analysez les appels dans Instana, vous voyez que la trace est rompue.

Trace 1 : traçage de la capture d'écran 01

Trace 2 : traçage de la capture d'écran 02

Les demandes sortantes sont implémentées à l'aide du client HTTP Apache qui est pris en charge par le traçage automatique d'Instana. Le lien manquant est le span d'entrée (appel entrant) GET /greeting sur le serveur HTTP personnalisé.

Activation du traçage pour le serveur HTTP personnalisé

Pour les frameworks pris en charge, l'agent Instana instrumente automatiquement les applications Java. Pour le serveur HTTP personnalisé, il est nécessaire d'ajouter des annotations pour indiquer à l'agent Instana les appels de méthode qui doivent démarrer un nouveau span.

Tout d'abord, ajoutez la dépendance mvn

<dependency>
  <groupId>com.instana</groupId>
  <artifactId>instana-java-sdk</artifactId>
  <version>1.2.0</version>
</dependency>

Ensuite, ajoutez une annotation @Span à la méthode de traitement de la demande HTTP dans le serveur HTTP personnalisé.

@Span(type = Span.Type.ENTRY, value = "my-custom-http-server")
public String apply(Map<String, String> headers) {
  // ...
}

Cette annotation indique à l'agent Java de générer un span ENTRY (c'est à dire, un span serveur) chaque fois que cette méthode est appelée.

Troisièmement, ajoutez ce qui suit au fichier configuration.yaml de l'agent Instana pour lui indiquer que les classes Java dans le package com.instana.sample.* doivent être analysées pour l'annotation @Span :

com.instana.plugin.javatrace:
  instrumentation:
    sdk:
      packages:
        - 'com.instana.sample'

Maintenant, le serveur personnalisé est instrumenté, et vous voyez que l'appel sortant vers /name est déclenché depuis l'appel entrant /greeting.

traçage de la capture d'écran 03

Cependant, la trace est toujours rompue, car l'ID de trace n'est pas transmis entre l'appel entrant et l'appel sortant.

Traitement des en-être de traçage entrants

Instana utilise les en-têtes HTTP suivants pour transmettre les informations de trace d'un service à l'autre :

  • X-INSTANA-T: ID de trace
  • X-INSTANA-S : ID du span parent
  • X-INSTANA-L : le niveau 0 signifie que la trace doit être supprimée, ce qui peut être utile pour les contrôles d'intégrité

Pour corréler le contexte de trace dans le serveur HTTP client, vous devez ajouter la méthode suivante à GreetingHandler :

private void correlateTracing(Map<String, String> request) {
  String level = request.remove(SpanSupport.LEVEL);
  String traceId = request.remove(SpanSupport.TRACE_ID);
  String parentSpanId = request.remove(SpanSupport.SPAN_ID);

  if (SpanSupport.SUPPRESS.equals(level)) {
    SpanSupport.suppressNext();
  } else if (traceId != null && parentSpanId != null) {
    SpanSupport.inheritNext(traceId, parentSpanId);
  }
}

Notez que nous supprimons les en-têtes après les avoir évalués, en ne laissant que les en-têtes d'origine tels qu'ils seraient envoyés sans le traçage Instana.

Toutefois, vous ne pouvez simplement pas appeler correlateTracing() dans apply(), car les en-têtes doivent être évalués avant que la méthode avec l'annotation @Span soit appelée. Comme solution palliative, vous pouvez renommer la méthode apply() en doApply() et ajouter une étape comme suit:

@Override
public String apply(Map<String, String> headers) {
  correlateTracing(headers);
  return doApply(headers);
}


@Span(type = Span.Type.ENTRY, value = "my-custom-http-server")
private String doApply(Map<String, String> headers) {
  // ...
}

Lorsque vous exécutez curl http://localhost:8080, vous voyez la trace complète dans Instana.

traçage de la capture d'écran 04

Ajout de balises

Jusqu'à présent, le span my-custom-http-server n'est qu'un span ENTRY générique sans annotations supplémentaires. Si vous regardez les détails, ils ont l'air plutôt vides.

étendue sans annotations

Vous pouvez appeler la méthode SpanSupport.annotate() du kit SDK dans un contexte @Span actif pour ajouter des annotations au span actuel. Instana prend en charge une partie des conventions sémantiques OpenTracing's décrites dans la documentation Java Trace SDK. Pour ajouter des annotations HTTP, ajoutez les lignes suivantes en haut de la méthode doApply() :

@Span(type = Span.Type.ENTRY, value = SPAN_NAME)
private String doApply(Map<String, String> headers) {
  SpanSupport.annotate(Span.Type.ENTRY, SPAN_NAME,"tags.http.url", "http://localhost:8080/greeting");
  SpanSupport.annotate(Span.Type.ENTRY, SPAN_NAME,"tags.http.method", "GET");
  SpanSupport.annotate(Span.Type.ENTRY, SPAN_NAME,"tags.http.status_code", "200");
  // ...
}

Maintenant, les détails du span ENTRY du serveur HTTP personnalisé affichent les métadonnées HTTP spécifiées.

étendue avec annotations

Notez que le span iEXIT correspondant de Jetty au serveur HTTP personnalisé avait déjà des métadonnées HTTP, car le client utilise le client Apache HTTP qui est pris en charge par le traçage automatique d'Instana.

Marquage d'un span comme étant erroné

À un moment ou à un autre, vous serez amené à marquer un appel comme étant erroné. Cela peut se faire facilement en ajoutant la balise " error, comme spécifié dans les conventions sémantiquesOpenTracing's.

SpanSupport.annotate(Span.Type.ENTRY, SPAN_NAME,"tags.error", "true");

Cet ajout fait apparaître l'appel comme erroné dans Instana.

étendue erronée

Récapitulatif et perspective

Ce tutoriel a montré l'API la plus importante API nécessaire pour instrumenter un framework HTTP personnalisé avec le traçage distribué d'Instana.

Pour une référence complète sur notre SDK, consultez le JavaDocdu SDK. Par exemple, les annotations @SpanParam et @SpanReturn facilitent grandement la capture des paramètres ou des valeurs de retour sous forme d'informations supplémentaires des spans, ce qui peut être plus pratique que d'appeler explicitement SpanSupport.annotate() dans certains scénarios.