Dans les pipelines de streaming distribués, il peut être difficile d'identifier l'étape spécifique, l'appel de service externe ou le shuffle de worker qui provoque des pics de latence en utilisant uniquement des métriques agrégées. En utilisant le traçage distribué OpenTelemetry dans Dataflow, vous pouvez suivre des éléments individuels de bout en bout dans les transformations de pipeline, les limites de réseau et les services intégrés sous un seul ID de trace. Cette visibilité vous aide à identifier les goulots d'étranglement des performances, à optimiser les coûts d'exécution des pipelines et à résoudre les problèmes liés aux charges de travail de streaming complexes.
Utilisez les informations suivantes pour activer, configurer et utiliser le traçage distribué OpenTelemetry dans vos pipelines Apache Beam.
Cas d'utilisation
Le traçage distribué dans Dataflow est particulièrement utile dans les scénarios suivants :
- Charges de travail de streaming : suivez le temps de traitement par élément et identifiez les étapes qui introduisent des pics de décalage ou de latence.
- Suivi des appels de service externes dans le code utilisateur : mesurez les durées d'exécution lorsque votre pipeline appelle des bases de données externes, des microservices ou des API d'IA générative dans le code utilisateur (par exemple, dans un
DoFn). Par exemple, vous pouvez mesurer le temps nécessaire aux appels vers des bases de données externes (telles que Spanner ou Bigtable), des microservices (à l'aide de HTTP ou gRPC) ou des API d'IA générative (telles que Gemini). Pour en savoir plus, consultez Écrire des traces personnalisées dans DoFns et Intégrer aux bibliothèques clientes. - Optimisation des coûts et des performances : exposez les durées d'opérations spécifiques dans les instances
PTransformsous charge réelle pour identifier la sérialisation inefficace, les requêtes lentes ou la contention des threads de worker. - Pipelines de workflows et agentiques complexes : obtenez de la visibilité sur les pipelines avec plusieurs branches, les boucles d'agents itératives et les jointures pour déterminer quelle transformation ou branche prend le plus de temps.
Limites
Le traçage distribué dans Dataflow présente les limites suivantes :
- Cette fonctionnalité est conçue et vérifiée uniquement pour les pipelines de streaming.
- Pour utiliser cette fonctionnalité, vous devez utiliser le SDK Beam pour Java (version 2.76.0 ou ultérieure).
- La propagation du contexte inter-étapes nécessite le Streaming Java Runner (anciennement appelé Runner v1). L'exécuteur portable (anciennement appelé Runner v2) réinitialise le contexte de trace aux limites du shuffle.
- Le traçage OpenTelemetry intégré aux connecteurs d'E/S Beam n'est compatible qu'avec les connecteurs suivants : Pub/Sub, Apache Kafka et flux de modifications Spanner. Pour Apache Kafka, le traçage n'est compatible que lorsque vous utilisez directement le connecteur
KafkaIO. Il n'est pas compatible avec Managed I/O pour Kafka. D'autres connecteurs d'E/S (tels queBigtableIO) ne disposent pas de traçage de connecteur intégré. Pour tracer les opérations avec ces services, instrumentez vos appels dans le code utilisateur (par exemple, dans unDoFn). - Les opérations qui combinent plusieurs éléments en un seul ne propagent pas un seul contexte de trace. Cela inclut des opérations telles que
GroupByKey,CoGroupByKeyetCombine. - Le contexte n'est pas propagé entre la définition d'un minuteur (
Timer.set()) et l'exécution de la méthode de rappel@OnTimer.
Prérequis
Pour utiliser le traçage distribué dans Dataflow, assurez-vous que votre environnement répond aux exigences suivantes :
- Votre tâche doit répondre aux exigences suivantes :
- Est un pipeline de flux de données
- Utilise l'exécuteur Java Streaming (anciennement appelé Runner v1)
- Utilise le SDK Java Apache Beam version 2.76.0 ou ultérieure
Si vous exportez des traces vers Cloud Trace, activez l'API Telemetry (
telemetry.googleapis.com) dans votre projet Google Cloud .Rôles requis pour activer les API
Pour activer les API, vous devez disposer de l'autorisation
serviceusage.services.enable. Si vous avez créé le projet, vous disposez probablement déjà de cette autorisation grâce au rôle Propriétaire (roles/owner). Sinon, vous pouvez obtenir cette autorisation grâce au rôle Administrateur Service Usage (roles/serviceusage.serviceUsageAdmin). Découvrez comment attribuer des rôles.Le compte de service du nœud de calcul doit disposer du rôle Agent Cloud Trace (
roles/cloudtrace.agent), qui inclut l'autorisationcloudtrace.traces.patch.
Concepts fondamentaux
Le traçage distribué repose sur les concepts OpenTelemetry suivants :
- Trace
- Représentation d'une transaction ou d'un workflow complet dans un système distribué. Une trace se compose d'un ou de plusieurs spans.
- Segment
- Composant de base d'une trace, représentant une seule unité de travail. Par exemple, une exécution de transformation, un appel de méthode ou une requête RPC.
- Contexte
- : état propagé entre les threads et les limites de l'API. Cela inclut l'ID de trace et l'ID de span.
- Propagateur
- Mécanisme utilisé pour injecter et extraire la représentation du contexte au-delà des limites du réseau. Par exemple, le contexte de trace W3C.
- Exportateur
- Composant qui envoie les données span collectées à un backend de traçage, tel que Cloud Trace ou un collecteur OpenTelemetry auto-hébergé.
- Échantillonneur
- Mécanisme qui contrôle le volume des traces en déterminant quelles traces sont enregistrées et exportées. Par exemple, un taux d'échantillonnage de 1 %.
Activer le traçage OpenTelemetry
Pour activer le traçage OpenTelemetry avec les paramètres par défaut, configurez les options de pipeline et les expériences requises lorsque vous envoyez votre job. Le paramètre par défaut exporte vers Cloud Trace avec un échantillonnage de 1 %.
Pour modifier les valeurs par défaut, consultez Définir et modifier les propriétés de traçage.
Configurez les options et les tests de pipeline lorsque vous exécutez votre job.
Job de modèle non Flex
Transmettez les indicateurs d'expérience suivants lorsque vous soumettez un job :
--experiments=enable_otel_defaults,element_metadata_supported,disable_portable_worker
Job de modèle Flex
Transmettez les expériences à l'aide de l'option
--additional-experimentsdans la commandegcloud:gcloud dataflow flex-template run JOB_NAME \ --template-file-gcs-location=gs://BUCKET_NAME/templates/TEMPLATE_NAME.json \ --additional-experiments="enable_otel_defaults,element_metadata_supported,disable_portable_worker" \ --region=REGIONRemplacez les éléments suivants :
- JOB_NAME : nom de votre job Dataflow.
- BUCKET_NAME : bucket Cloud Storage contenant votre modèle.
- TEMPLATE_NAME : nom de votre fichier de modèle Flex.
- REGION : Google Cloud région dans laquelle vous souhaitez exécuter le job.
Ces tests configurent les comportements suivants :
enable_otel_defaults: configure les paramètres OpenTelemetry standards par défaut, y compris l'exportateur Cloud Trace et l'échantillonnage à 1 %.element_metadata_supported: permet la sérialisation et la propagation des métadonnées (telles que le contexte de trace) dans les étapes du pipeline.disable_portable_worker: force l'utilisation de l'exécuteur Java de streaming Dataflow (anciennement appelé Runner v1).
Si vous utilisez le SDK Beam pour Java version 2.76.0 ou 2.77.0, ajoutez les dépendances OpenTelemetry requises à votre configuration de compilation.
En raison d'un problème dans les versions 2.76.0 et 2.77.0, vous devez ajouter les dépendances suivantes à votre fichier
pom.xmlpour que les traces soient exportées. Pour en savoir plus, consultez Gérer les dépendances de pipeline.<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> <version>1.62.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.beam</groupId> <artifactId>beam-sdks-java-extensions-opentelemetry-gcp-auth-extension</artifactId> <scope>compile</scope> </dependency>Activez explicitement le traçage OpenTelemetry sur les connecteurs d'E/S compatibles dans le code de votre pipeline :
Pub/Sub
Pour activer le traçage lors de la lecture ou de l'écriture dans Pub/Sub :
// Reading from Pub/Sub pipeline.apply("ReadFromPubSub", PubsubIO.readMessages() .withEnableOpenTelemetryTracing() .fromSubscription("projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID")); // Writing to Pub/Sub pipeline.apply("WriteToPubSub", PubsubIO.writeStrings() .withEnableOpenTelemetryTracing() .to("projects/PROJECT_ID/topics/TOPIC_ID"));
Remplacez les éléments suivants :
- PROJECT_ID : ID de votre projet Google Cloud .
- SUBSCRIPTION_ID : nom de votre abonnement Pub/Sub.
- TOPIC_ID : nom de votre sujet Pub/Sub.
Détails de la propagation du contexte :
- Éditeur en amont : lorsque vous publiez des messages à partir d'une application externe, injectez le contexte de trace W3C dans les attributs de message Pub/Sub. Pour en savoir plus, consultez la section Traçage OpenTelemetry Pub/Sub.
- Attributs : Beam s'attend aux attributs suivants et les renseigne :
googclient_traceparent: contient l'en-têtetraceparentdu W3C.googclient_tracestate: contient l'en-têtetracestatedu W3C.
- Pour en savoir plus sur le format des en-têtes, consultez la spécification du contexte de trace W3C.
Apache Kafka
Pour activer le traçage lors de la lecture ou de l'écriture dans Apache Kafka :
// Reading from Kafka pipeline.apply("ReadFromKafka", KafkaIO.<String, String>read() .withEnableOpenTelemetryTracing() // ... additional configuration ); // Writing to Kafka pipeline.apply("WriteToKafka", KafkaIO.<String, String>write() .withEnableOpenTelemetryTracing() // ... additional configuration );
Détails de la propagation du contexte :
KafkaIOutilise des en-têtes d'enregistrement Kafka standards pour propager le contexte.- Il attend et injecte des en-têtes conformes à la spécification du contexte de trace W3C :
traceparent: identifie le contexte de trace entrant.tracestate: fournit des métadonnées de filtrage et de routage supplémentaires spécifiques au fournisseur.
Spanner
Pour activer le traçage lors de la lecture des flux de modifications Spanner :
pipeline.apply("ReadChangeStream", SpannerIO.readChangeStream() .withSpannerConfig(spannerConfig) .withEnableOpenTelemetryTracing(true) .withChangeStreamName("CHANGE_STREAM_NAME"));
Remplacez les éléments suivants :
- CHANGE_STREAM_NAME : nom du flux de modifications Spanner.
Détails de la création de la portée :
- L'activation du traçage démarre une nouvelle trace et une nouvelle étendue pour chaque enregistrement de mutation de base de données lu par le lecteur de capture des données modifiées (CDC).
- Les cycles d'interrogation du lecteur Spanner qui ne renvoient aucun nouvel enregistrement peuvent également générer des segments de trace qui peuvent être filtrés dans l'interface utilisateur Cloud Trace.
Définir et modifier les propriétés de traçage
Lorsque vous spécifiez enable_otel_defaults, Dataflow applique les propriétés par défaut suivantes :
| Propriété | Valeur par défaut | Description |
|---|---|---|
otel.traces.exporter |
otlp |
Exporte les traces à l'aide du protocole OpenTelemetry (OTLP). |
otel.exporter.otlp.endpoint |
https://telemetry.googleapis.com |
Cible le récepteur OTLP Cloud Trace. |
google.cloud.project |
ID de votre projet | Le projet Google Cloud dans lequel les traces sont stockées. |
otel.traces.sampler.arg |
0.01 (1%) |
Enregistre une trace sur 100. |
otel.service.name |
options.getAppName() |
Nom du service associé aux spans, dérivé de l'option de pipeline appName. |
Pour personnaliser la configuration OpenTelemetry, transmettez une liste de propriétés séparées par des points-virgules à l'option de pipeline --openTelemetryProperties.
L'exemple suivant configure explicitement toutes les propriétés par défaut :
--openTelemetryProperties="otel.traces.exporter=otlp;otel.exporter.otlp.endpoint=https://telemetry.googleapis.com;google.cloud.project=PROJECT_ID;otel.traces.sampler.arg=0.01;otel.service.name=CUSTOM_SERVICE_NAME;otel.java.global-autoconfigure.enabled=true"
Définir un nom de service personnalisé
Par défaut, le nom du service de trace est dérivé de l'option appName du pipeline (--appName=YourPipelineName). Vous pouvez remplacer cette valeur en définissant la propriété otel.service.name :
--openTelemetryProperties="otel.service.name=CUSTOM_SERVICE_NAME"
Modifier le taux d'échantillonnage et les propriétés
Si vous définissez un taux d'échantillonnage plus élevé, vous obtiendrez des informations de traçage plus fiables.
Toutefois, des taux d'échantillonnage élevés (tels que 1.0 ou always_on) augmentent considérablement le volume de données de trace envoyées à Cloud Trace, ce qui peut augmenter vos coûts Google Cloud . N'utilisez des taux d'échantillonnage élevés que pour le débogage à court terme et réduisez-les pour les charges de travail de production.
L'exemple suivant configure explicitement le taux d'échantillonnage. Dans ce cas, vous devez fournir une liste complète d'arguments :
--openTelemetryProperties="otel.traces.exporter=otlp;otel.exporter.otlp.endpoint=https://telemetry.googleapis.com;google.cloud.project=PROJECT_ID;otel.traces.sampler.arg=0.02;otel.service.name=CUSTOM_SERVICE_NAME;otel.java.global-autoconfigure.enabled=true"
Exporter vers des backends tiers
Pour envoyer des traces à un backend de traçage géré externe ou à un collecteur OpenTelemetry auto-hébergé au lieu de Cloud Trace :
- Omettez le test suivant :
--experiments=enable_otel_defaults. Configurez manuellement les propriétés de l'exportateur à l'aide de
--openTelemetryProperties:--openTelemetryProperties="otel.traces.exporter=otlp;otel.exporter.otlp.endpoint=http://COLLECTOR_HOST:4317;otel.traces.sampler=parentbased_always_on"
Extension d'authentificationGoogle Cloud
L'exécution Beam inclut une extension d'authentification Google Cloud qui authentifie automatiquement les requêtes OpenTelemetry Protocol (OTLP) envoyées aux API Google telles que telemetry.googleapis.com.
- Lorsque vous utilisez les valeurs par défaut Google Cloud , l'authentification est activée automatiquement.
- Lors de l'exportation vers des points de terminaison non Google : si
enable_otel_defaultsest omis, Beam désactive l'extension d'authentification Google Cloud en définissant la propriété systèmegoogle.otel.auth.target.signals=none. - Configuration manuelle : vous pouvez définir la propriété système
google.otel.auth.target.signalssurnone(désactivé) outrace(activé pour les traces uniquement).
Écrire des traces personnalisées dans les DoFn
Vous pouvez créer des spans personnalisés dans le code utilisateur, par exemple dans un DoFn, pour mesurer des opérations spécifiques. Cela inclut les appels à des API externes ou une logique nécessitant beaucoup de ressources de calcul.
Exemple d'implémentation DoFn
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.SdkHarnessOptions;
import org.apache.beam.sdk.transforms.DoFn;
public class InvestigateTransactionDoFn extends DoFn<Transaction, RiskAssessment> {
private transient Tracer tracer;
@Setup
public void setup(PipelineOptions options) {
// Obtain the Tracer instance from SdkHarnessOptions
this.tracer = options
.as(SdkHarnessOptions.class)
.getOpenTelemetry()
.getTracer("org.apache.beam.examples.adk.aml");
}
@ProcessElement
public void processElement(@Element Transaction tx, OutputReceiver<RiskAssessment> out) {
// Create and start a custom span as a child of the active context
Span span = tracer.spanBuilder("InvestigateTransactionDoFn:Analyze")
.setAttribute("transaction.id", tx.getId())
.setAttribute("transaction.amount", tx.getAmount())
.startSpan();
// Make the span current in the execution thread
try (Scope scope = span.makeCurrent()) {
// Perform your logic (such as calling an external service)
RiskAssessment assessment = analyzeTransactionWithLLM(tx);
out.output(assessment);
} catch (Exception e) {
// Record exception details and set error status on the span
span.recordException(e);
span.setStatus(StatusCode.ERROR, e.getMessage());
throw e;
} finally {
// Always end the span
span.end();
}
}
private RiskAssessment analyzeTransactionWithLLM(Transaction tx) {
// Application analysis logic
return new RiskAssessment();
}
}
Intégrer des bibliothèques clientes
Lorsqu'un DoFn appelle des bibliothèques externes compatibles avec OpenTelemetry, telles que les bibliothèques clientes Google Cloud , configurez le client pour qu'il utilise l'instance OpenTelemetry du pipeline. Les spans enfants seront ainsi directement associés à la trace du pipeline.
Exemple de client Java Spanner
Pour exécuter des requêtes Spanner manuelles dans un DoFn et associer ces spans à la trace de pipeline active, initialisez SpannerOptions avec l'instance OpenTelemetry du pipeline :
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.Statement;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.SdkHarnessOptions;
import org.apache.beam.sdk.transforms.DoFn;
public class SpannerEnrichmentDoFn extends DoFn<String, String> {
private transient Spanner spanner;
private transient DatabaseClient dbClient;
private final String instanceId;
private final String databaseId;
public SpannerEnrichmentDoFn(String instanceId, String databaseId) {
this.instanceId = instanceId;
this.databaseId = databaseId;
}
@Setup
public void setup(PipelineOptions pipelineOptions) {
// Build SpannerOptions leveraging the pipeline's active OpenTelemetry instance
SpannerOptions options =
SpannerOptions.newBuilder()
.setOpenTelemetry(pipelineOptions
.as(SdkHarnessOptions.class)
.getOpenTelemetry())
.setEnableEndToEndTracing(true)
.setEnableExtendedTracing(true)
.build();
this.spanner = options.getService();
DatabaseId db = DatabaseId.of(options.getProjectId(), instanceId, databaseId);
this.dbClient = spanner.getDatabaseClient(db);
}
@ProcessElement
public void processElement(@Element String inputId, OutputReceiver<String> out) {
Statement statement = Statement.newBuilder(
"SELECT Details FROM AccountTable WHERE AccountId = @id")
.bind("id").to(inputId)
.build();
// Spanner queries automatically generate child spans linked to the active trace
try (ResultSet rs = dbClient.singleUse().executeQuery(statement)) {
while (rs.next()) {
out.output(rs.getString("Details"));
}
}
}
@Teardown
public void tearDown() {
if (spanner != null) {
spanner.close();
}
}
}
Propagation du contexte entre les étapes
Dans les pipelines de données distribués, il est essentiel de transmettre le contexte de trace au-delà des limites des nœuds de calcul et des opérations de brassage pour assurer une visibilité de bout en bout.
Lorsque vous insérez Redistribute.arbitrarily() dans votre pipeline, le contexte de trace active est sérialisé dans les métadonnées de l'élément, transmis sur le réseau et désérialisé sur la VM de nœud de calcul destinataire. Cela garantit la continuité des traces entre les étapes.
L'exemple suivant montre comment le contexte de trace se propage dans les étapes du pipeline :
- Extraire le contexte :
KafkaIO.read()lit un enregistrement entrant et extrait le contexte de trace des en-têtes de message. - Traiter et créer des spans :
DoFn Atraite l'élément dans un span de trace actif. - Propager entre les nœuds de calcul :
Redistribute.arbitrarily()sérialise le contexte de trace actif dans les métadonnées de l'élément et le mélange sur le réseau. - Poursuivre la trace :
DoFn Breçoit l'élément sur une VM de nœud de calcul, désérialise le contexte de trace et poursuit le traitement sous le même ID de trace.
Afficher les traces dans Cloud Trace
Une fois le traçage activé, affichez les traces de pipeline dans la console Google Cloud :
Dans la console Google Cloud , accédez à la page Explorateur Trace.
Dans la zone de filtre, filtrez par
Service: SERVICE_NAME. Ce SERVICE_NAME correspond à votreappNamede pipeline ou à votreotel.service.nameconfiguré.Vous pouvez également rechercher un ID de trace spécifique.
Sélectionnez une trace dans la liste des résultats pour afficher sa chronologie détaillée.
Le graphique de la chronologie affiche les éléments suivants :
- Spans de l'exécuteur : spans générés par l'environnement d'exécution Beam.
Par exemple,
PubSubIO.ReadetProcessElement. - Portées personnalisées : portées créées dans vos implémentations
DoFn. Exemple :InvestigateTransactionDoFn:Analyze. Portées de la bibliothèque cliente : portées enfants générées par les bibliothèques clientes intégrées. Par exemple, les requêtes RPC Spanner.

- Spans de l'exécuteur : spans générés par l'environnement d'exécution Beam.
Par exemple,
Étapes suivantes
- Pour en savoir plus sur l'exploration et l'analyse des traces distribuées, consultez la documentation Cloud Trace.
- Suivez les messages de l'ingestion au traitement à l'aide du traçage OpenTelemetry Pub/Sub.
- Surveillez le débit, l'utilisation du processeur et les détails d'exécution de votre pipeline à l'aide de l'interface de surveillance Dataflow.
- Affichez les journaux opérationnels et diagnostiquez les erreurs à l'aide des journaux de pipeline Dataflow.
- Enquêter sur les problèmes de performances et les résoudre à l'aide des pages Résoudre les problèmes liés aux jobs lents ou bloqués et Détecter et résoudre les goulots d'étranglement des pipelines.