Lorsque des threads ou des processus communiquent via des intermédiaires tels que des files d'attente de messages ou des bases de données, l'agent ARMS ne peut pas propager automatiquement le contexte de trace. Le consommateur démarre alors une nouvelle trace déconnectée au lieu de poursuivre celle du producteur. Utilisez le SDK OpenTelemetry pour Java afin de capturer et de restaurer manuellement le contexte de trace à travers ces limites asynchrones, garantissant ainsi la corrélation de toutes les spans au sein d'une seule trace.
Quand une propagation manuelle est nécessaire
L'agent ARMS propage automatiquement le contexte de trace pour les modèles asynchrones suivants, sans modification du code :
Pools de threads créés avec JDK, Spring ou Netty
Programmation réactive avec Reactor ou RxJava
Annotations Spring
@AsyncFrameworks réactifs tels que Spring Webflux et Spring Gateway
Pour la liste complète des frameworks pris en charge, consultez la rubrique Composants et frameworks Java pris en charge par ARMS.
Une propagation manuelle s'impose lorsque des threads ou des processus communiquent via des intermédiaires non instrumentés par l'agent ARMS. Voici deux exemples courants :
| Scénario | Description |
|---|---|
| File d'attente producteur-consommateur | Le thread T1 place un message dans une file d'attente et le thread T2 le récupère pour traitement. Sans propagation manuelle, T2 démarre une nouvelle trace au lieu de poursuivre celle de T1. |
| Transfert médiatisé par une base de données | Le processus P1 écrit un lot d'enregistrements dans une base de données et le processus P2 les lit et les traite. Sans propagation manuelle, la trace de traitement est déconnectée de la trace d'écriture. |
Prérequis
Avant de commencer, assurez-vous d'avoir :
Intégré Application Monitoring d'ARMS. Pour plus d'informations, consultez la rubrique Présentation d'Application Monitoring
Installé l'agent ARMS version 4.x ou ultérieure. Pour vérifier ou mettre à jour votre version, consultez la rubrique Mettre à jour l'agent ARMS
Ajouter des dépendances
Ajoutez les dépendances Maven suivantes à votre projet. Pour plus d'informations, consultez la documentation officielle d'OpenTelemetry.
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-trace</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.23.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Propager le contexte au-delà des limites asynchrones
Ce modèle repose sur deux étapes :
Capture : Côté émetteur, appelez
Context.current()pour capturer le contexte de trace actif et stockez-le conjointement avec les données transmises.Restauration : Côté récepteur, appelez
context.makeCurrent()pour restaurer le contexte capturé avant le traitement.
Exemple : Producteur-consommateur avec une file d'attente bloquante
Le code suivant transmet le contexte de trace via une LinkedBlockingQueue. Le producteur capture le contexte actuel lors de l'ajout d'un message à la file, et le consommateur le restaure avant le traitement.
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import java.util.concurrent.LinkedBlockingQueue;
// Wrap both the message and its trace context
class Event {
private final Context context;
private final String msg;
public Event(Context context, String msg) {
this.context = context;
this.msg = msg;
}
public Context getContext() {
return context;
}
public String getMsg() {
return msg;
}
}
// Shared queue between producer and consumer threads
private final LinkedBlockingQueue<Event> queue = new LinkedBlockingQueue<>();
// Producer: capture the current trace context
public void produce(String msg) {
queue.add(new Event(Context.current(), msg));
}
// Consumer: restore the trace context before processing
public void consume() throws InterruptedException {
Event event = queue.take();
// makeCurrent() sets the captured context as the active context.
// The try-with-resources block ensures the context is cleaned up after processing.
try (Scope scope = event.getContext().makeCurrent()) {
processEvent(event);
}
}
public void processEvent(Event event) {
// Any spans created here automatically become children
// of the producer's trace.
}
Points clés
| Concept | Description |
|---|---|
Context.current() |
Capture le contexte de trace actif au moment de l'appel. Stockez-le conjointement avec les données échangées entre les threads. |
context.makeCurrent() |
Restaure le contexte capturé sur le thread consommateur. Les spans, journaux et métriques créés dans le bloc try (Scope scope = ...) sont corrélés avec la trace d'origine. |
Scope |
Implémente AutoCloseable. Utilisez toujours un bloc try-with-resources pour garantir le nettoyage correct du contexte. |
Étapes suivantes
Associez les ID de trace aux journaux d'application pour simplifier l'analyse des erreurs. Consultez la rubrique Associer les ID de trace aux journaux d'une application Java.