OpenTelemetry est une norme ouverte permettant de collecter des traces et des métriques à partir d'applications distribuées. ClickHouse prend en charge OpenTelemetry dans une certaine mesure.
Fournir le contexte de trace à ClickHouse
ClickHouse accepte les en-têtes HTTP de contexte de trace, comme décrit dans la recommandation du W3C. Il accepte également le contexte de trace via un protocole natif utilisé pour la communication entre les serveurs ClickHouse, ou entre le client et le serveur. Pour les tests manuels, vous pouvez fournir à clickhouse-client des en-têtes de contexte de trace conformes à la recommandation Trace Context à l'aide des options --opentelemetry-traceparent et --opentelemetry-tracestate.
Si aucun contexte de trace parent n'est fourni, ou si le contexte de trace fourni n'est pas conforme à la norme W3C ci-dessus, ClickHouse peut démarrer une nouvelle trace, avec une probabilité contrôlée par le paramètre opentelemetry_start_trace_probability.
Propagation du contexte de trace
Le contexte de trace est propagé aux services en aval dans les cas suivants :
-
Requêtes adressées à des serveurs ClickHouse distants, par exemple lors de l’utilisation du moteur de table Distributed.
-
La fonction de table url. Les informations de contexte de trace sont envoyées dans les en-têtes HTTP.
Traçage des requêtes ClickHouse Keeper
ClickHouse prend en charge le traçage OpenTelemetry des requêtes ClickHouse Keeper (service de coordination compatible avec ZooKeeper). Cette fonctionnalité offre une visibilité détaillée sur le cycle de vie des opérations Keeper, depuis la soumission de la requête par le client jusqu’au traitement côté serveur.
Activation du traçage de Keeper
Pour activer le traçage des requêtes Keeper, configurez les paramètres suivants dans la configuration de votre client ZooKeeper/Keeper :
<clickhouse>
<zookeeper>
<node>
<host>keeper1</host>
<port>9181</port>
</node>
<!-- Enable OpenTelemetry tracing context propagation -->
<pass_opentelemetry_tracing_context>true</pass_opentelemetry_tracing_context>
</zookeeper>
</clickhouse>Types de spans de Keeper
Lorsque le traçage est activé, ClickHouse crée des spans pour les opérations Keeper côté client et côté serveur :
Spans côté client :
zookeeper.create— Créer un nouveau nœudzookeeper.get— Récupérer les données du nœudzookeeper.set— Définir les données du nœudzookeeper.remove— Supprimer un nœudzookeeper.list— Lister les nœuds enfantszookeeper.exists— Vérifier si un nœud existezookeeper.multi— Exécuter plusieurs opérations de manière atomiquezookeeper.client.requests_queue— Temps passé en file d’attente avant l’envoi des requêtes
Spans côté serveur (Keeper) :
keeper.receive_request— Réception et analyse de la requête du clientkeeper.dispatcher.requests_queue— Mise en file d’attente des requêtes dans le dispatcherkeeper.write.pre_commit— Prétraitement des requêtes d’écriture avant le Raft commitkeeper.write.commit— Traitement des requêtes d’écriture après le Raft commitkeeper.read.wait_for_write— Requêtes de lecture en attente des écritures dont elles dépendentkeeper.read.process— Traitement des requêtes de lecturekeeper.dispatcher.responses_queue— Mise en file d’attente des réponses dans le dispatcherkeeper.send_response— Envoi de la réponse au client
Échantillonnage et performances
Pour gérer la surcharge liée au traçage, Keeper met en œuvre un échantillonnage dynamique. Le taux d’échantillonnage s’ajuste automatiquement entre 1/10 000 et 1/10 en fonction de la taille des requêtes. La durée de toutes les requêtes (échantillonnées ou non) est enregistrée dans des métriques de type histogramme afin de surveiller les performances.
Traçage de ClickHouse lui-même
ClickHouse crée des trace spans pour chaque requête et pour certaines étapes de l’exécution des requêtes, comme la planification des requêtes ou les requêtes distribuées.
Pour être utiles, les informations de traçage doivent être exportées vers un système de supervision compatible avec OpenTelemetry, comme Jaeger ou Prometheus. ClickHouse évite de dépendre d’un système de supervision particulier et fournit uniquement les données de traçage via une table système. Les informations sur les trace spans OpenTelemetry requises par la norme sont stockées dans la table system.opentelemetry_span_log.
La table doit être activée dans la configuration du serveur ; voir l’élément opentelemetry_span_log dans le fichier de configuration par défaut config.xml. Elle est activée par défaut.
Les tags ou attributs sont enregistrés sous forme de deux tableaux parallèles contenant les clés et les valeurs. Utilisez ARRAY JOIN pour les exploiter.
Paramètres de journalisation des requêtes
Le paramètre log_query_settings permet de consigner les modifications des paramètres de requête pendant l’exécution d’une requête. Lorsqu’il est activé, toute modification apportée aux paramètres de requête est enregistrée dans le journal du span OpenTelemetry. Cette fonctionnalité est particulièrement utile dans les environnements de production pour suivre les changements de configuration susceptibles d’affecter les performances des requêtes.
Intégration avec les systèmes de supervision
À l’heure actuelle, il n’existe aucun outil prêt à l’emploi permettant d’exporter les données de traçage de ClickHouse vers un système de supervision.
Pour les tests, il est possible de configurer l’export à l’aide d’une vue matérialisée avec le moteur URL sur la table system.opentelemetry_span_log, afin d’envoyer les logs entrants vers l’endpoint HTTP d’un collecteur de traces. Par exemple, pour envoyer les données minimales du span vers une instance Zipkin exécutée sur http://localhost:9411, au format JSON Zipkin v2 :
CREATE MATERIALIZED VIEW default.zipkin_spans
ENGINE = URL('http://127.0.0.1:9411/api/v2/spans', 'JSONEachRow')
SETTINGS output_format_json_named_tuples_as_objects = 1,
output_format_json_array_of_rows = 1 AS
SELECT
lower(hex(trace_id)) AS traceId,
CASE WHEN parent_span_id = 0 THEN '' ELSE lower(hex(parent_span_id)) END AS parentId,
lower(hex(span_id)) AS id,
operation_name AS name,
start_time_us AS timestamp,
finish_time_us - start_time_us AS duration,
cast(tuple('clickhouse'), 'Tuple(serviceName text)') AS localEndpoint,
cast(tuple(
attribute.values[indexOf(attribute.names, 'db.statement')]),
'Tuple("db.statement" text)') AS tags
FROM system.opentelemetry_span_logEn cas d’erreur, la partie des données de logs concernée sera perdue sans avertissement. Consultez le journal du serveur pour voir les messages d’erreur si les données n’arrivent pas.