> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Intégration d’OpenTelemetry pour la collecte de données

> Intégration d’OpenTelemetry et de ClickHouse pour l’observabilité

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

Toute solution d’observability nécessite un moyen de collecter et d’exporter les logs et les traces. À cette fin, ClickHouse recommande [le projet OpenTelemetry (OTel)](https://opentelemetry.io/).

"OpenTelemetry est un framework et une boîte à outils d’observability conçus pour créer et gérer des données de télémétrie telles que les traces, les metrics et les logs."

Contrairement à ClickHouse ou à Prometheus, OpenTelemetry n'est pas un backend d’observability ; il se concentre plutôt sur la génération, la collecte, la gestion et l’export de données de télémétrie. Si l’objectif initial d’OpenTelemetry était de vous permettre d’instrumenter facilement vos applications ou vos systèmes à l’aide de SDKs propres à chaque langage, il s’est depuis étendu à la collecte de logs via l’OpenTelemetry collector, un agent ou proxy qui reçoit, traite et exporte des données de télémétrie.

<div id="clickhouse-relevant-components">
  ## Composants pertinents pour ClickHouse
</div>

OpenTelemetry comprend un certain nombre de composants. En plus de fournir une spécification des données et des API, un protocole normalisé et des conventions de nommage pour les champs/colonnes, OTel offre deux capacités essentielles à la création d'une solution d'observabilité avec ClickHouse :

* L'[OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) est un proxy qui reçoit, traite et exporte les données de télémétrie. Une solution reposant sur ClickHouse utilise ce composant à la fois pour collecter les logs et traiter les événements avant leur mise en lot et leur insertion.
* Les [SDKs de langage](https://opentelemetry.io/docs/languages/) qui implémentent la spécification, les API et l'export des données de télémétrie. Ces SDKs garantissent concrètement que les traces sont correctement enregistrées dans le code d'une application, en générant les spans qui les composent et en veillant à ce que le contexte soit propagé entre les services via les métadonnées, ce qui permet de constituer des traces distribuées et de corréler les spans. Ces SDKs sont complétés par un écosystème qui instrumente automatiquement les bibliothèques et frameworks courants, ce qui signifie que l'utilisateur n'a pas besoin de modifier son code et bénéficie d'une instrumentation prête à l'emploi.

Une solution d'observabilité reposant sur ClickHouse tire parti de ces deux outils.

<div id="distributions">
  ## Distributions
</div>

Le collecteur OpenTelemetry existe en [plusieurs distributions](https://github.com/open-telemetry/opentelemetry-collector-releases?tab=readme-ov-file). Le receiver filelog ainsi que l’exporter ClickHouse, nécessaires pour une solution ClickHouse, ne sont disponibles que dans la [distribution OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib).

Cette distribution contient de nombreux composants et permet d’expérimenter diverses configurations. Cependant, pour une exécution en production, il est recommandé de limiter le collecteur aux seuls composants nécessaires à l’environnement. Voici quelques raisons de le faire :

* Réduire la taille du collecteur, et donc le temps de déploiement du collecteur
* Améliorer la sécurité du collecteur en réduisant la surface d’attaque disponible

Il est possible de créer un [collecteur personnalisé](https://opentelemetry.io/docs/collector/custom-collector/) à l’aide d’[OpenTelemetry Collector Builder](https://github.com/open-telemetry/opentelemetry-collector/tree/main/cmd/builder).

<div id="ingesting-data-with-otel">
  ## Ingestion de données avec OTel
</div>

<div id="collector-deployment-roles">
  ### Rôles de déploiement du collecteur
</div>

Pour collecter les logs et les insérer dans ClickHouse, nous recommandons d'utiliser l'OpenTelemetry Collector. L'OpenTelemetry Collector peut être déployé selon deux rôles principaux :

* **Agent** - Les instances d'agent collectent les données en périphérie, par exemple sur des serveurs ou des nœuds Kubernetes, ou reçoivent directement des événements d'applications instrumentées avec un SDK OpenTelemetry. Dans ce dernier cas, l'instance d'agent s'exécute avec l'application ou sur le même hôte que celle-ci (par exemple en sidecar ou sous forme de DaemonSet). Les agents peuvent envoyer leurs données directement à ClickHouse ou à une instance de passerelle. Dans le premier cas, on parle du [modèle de déploiement Agent](https://opentelemetry.io/docs/collector/deployment/agent/).
* **Gateway**  - Les instances de passerelle fournissent un service autonome (par exemple, un déploiement dans Kubernetes), généralement par cluster, par centre de données ou par région. Elles reçoivent les événements des applications (ou d'autres collecteurs agissant comme agents) via un point de terminaison OTLP unique. En règle générale, plusieurs instances de passerelle sont déployées, avec un équilibreur de charge prêt à l'emploi pour répartir la charge entre elles. Lorsque tous les agents et toutes les applications envoient leurs signaux vers ce point de terminaison unique, on parle souvent du [modèle de déploiement Gateway](https://opentelemetry.io/docs/collector/deployment/gateway/).

Dans la suite, nous partons du principe qu'un collecteur agent simple envoie directement ses événements à ClickHouse. Voir [Scaling with Gateways](#scaling-with-gateways) pour plus de détails sur l'utilisation des passerelles et les cas où elles sont pertinentes.

<div id="collecting-logs">
  ### Collecte des logs
</div>

Le principal avantage de l’utilisation d’un collecteur est qu’il permet à vos services d’évacuer rapidement les données, en laissant au Collector le soin de gérer les traitements supplémentaires tels que les nouvelles tentatives, le regroupement par lots, le chiffrement ou encore le filtrage des données sensibles.

Le Collector utilise les termes [receiver](https://opentelemetry.io/docs/collector/configuration/#receivers), [processor](https://opentelemetry.io/docs/collector/configuration/#processors) et [exporter](https://opentelemetry.io/docs/collector/configuration/#exporters) pour ses trois principales étapes de traitement. Les receivers servent à collecter les données et peuvent fonctionner en mode pull ou push. Les processors permettent d’effectuer des transformations et d’enrichir les messages. Les exporters se chargent d’envoyer les données vers un service en aval. Bien que ce service puisse, en théorie, être un autre collecteur, nous partons ici du principe que toutes les données sont envoyées directement à ClickHouse.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-3.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=51a4df47eaaa58fae6330c7a9e915db7" alt="Collecte des logs" size="md" width="1000" height="620" data-path="images/use-cases/observability/observability-3.webp" />

Nous recommandons aux utilisateurs de se familiariser avec l’ensemble des receivers, processors et exporters.

Le collecteur fournit deux receivers principaux pour la collecte des logs :

**Via OTLP** - Dans ce cas, les logs sont envoyés (push) directement au collecteur depuis les OpenTelemetry SDKs via le protocole OTLP. La [OpenTelemetry demo](https://opentelemetry.io/docs/demo/) utilise cette approche, les exporters OTLP de chaque langage supposant un endpoint local du collecteur. Le collecteur doit alors être configuré avec l’OTLP receiver — voir la [démo ci-dessus pour un exemple de configuration](https://github.com/ClickHouse/opentelemetry-demo/blob/main/src/otelcollector/otelcol-config.yml#L5-L12). L’avantage de cette approche est que les données de logs contiennent automatiquement des trace IDs, ce qui permet ensuite d’identifier les traces associées à un log donné, et inversement.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-4.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=5384df19aba995909c89b1fc1a591e8d" alt="Collecte des logs via otlp" size="md" width="1000" height="300" data-path="images/use-cases/observability/observability-4.webp" />

Cette approche exige que les utilisateurs instrumentent leur code avec le [SDK adapté à leur langage](https://opentelemetry.io/docs/languages/).

* **Scraping via le receiver filelog** - Ce receiver lit les fichiers sur disque en continu, génère des messages de log, puis les envoie à ClickHouse. Il prend en charge des tâches complexes telles que la détection des messages multilignes, la gestion de la rotation des logs, les checkpoints pour une meilleure robustesse au redémarrage, ainsi que l’extraction de structure. Il peut également suivre les logs des conteneurs Docker et Kubernetes, et être déployé via un chart Helm, [en extrayant leur structure](https://opentelemetry.io/blog/2024/otel-collector-container-log-parser/) et en les enrichissant avec les détails du pod.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-5.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=3a9a36156316a135be41c857b7b402fd" alt="Receiver filelog" size="md" width="1000" height="300" data-path="images/use-cases/observability/observability-5.webp" />

**La plupart des déploiements utiliseront une combinaison des receivers ci-dessus. Nous recommandons aux utilisateurs de lire la [documentation du collecteur](https://opentelemetry.io/docs/collector/) et de se familiariser avec les concepts de base, ainsi qu’avec [la structure de configuration](https://opentelemetry.io/docs/collector/configuration/) et les [méthodes d’installation](https://opentelemetry.io/docs/collector/installation/).**

<Info>
  **Astuce : `otelbin.io`**

  [`otelbin.io`](https://www.otelbin.io/) est utile pour valider et visualiser les configurations.
</Info>

<div id="structured-vs-unstructured">
  ## Structuré ou non structuré
</div>

Les logs peuvent être structurés ou non structurés.

Un log structuré utilise un format de données tel que JSON, avec des champs de métadonnées comme le code HTTP et l’adresse IP source.

```json theme={null}
{
    "remote_addr":"54.36.149.41",
    "remote_user":"-","run_time":"0","time_local":"2019-01-22 00:26:14.000","request_type":"GET",
    "request_path":"\/filter\/27|13 ,27|  5 ,p53","request_protocol":"HTTP\/1.1",
    "status":"200",
    "size":"30577",
    "referer":"-",
    "user_agent":"Mozilla\/5.0 (compatible; AhrefsBot\/6.1; +http:\/\/ahrefs.com\/robot\/)"
}
```

Les logs non structurés, bien qu’ils présentent eux aussi généralement une certaine structure inhérente pouvant être extraite à l’aide d’un motif regex, représentent le log uniquement sous forme de chaîne de caractères.

```response theme={null}
54.36.149.41 - - [22/Jan/2019:03:56:14 +0330] "GET
/filter/27|13%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,27|%DA%A9%D9%85%D8%AA%D8%B1%20%D8%A7%D8%B2%205%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,p53 HTTP/1.1" 200 30577 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" "-"
```

Nous recommandons aux utilisateurs d’adopter une journalisation structurée et, dans la mesure du possible, d’émettre les logs au format JSON (c.-à-d. ndjson). Cela simplifiera le traitement des logs par la suite, soit avant leur envoi vers ClickHouse avec les [processors du collector](https://opentelemetry.io/docs/collector/configuration/#processors), soit au moment de l’insert à l’aide de vues matérialisées. À terme, les logs structurés permettent d’économiser des ressources de traitement et de réduire le CPU nécessaire à votre solution ClickHouse.

<div id="example">
  ### Exemple
</div>

À titre d’exemple, nous fournissons un jeu de données de logs structuré (JSON) et un jeu de données de logs non structuré, contenant chacun environ 10 M de lignes, disponibles aux liens suivants :

* [Non structuré](https://datasets-documentation.s3.eu-west-3.amazonaws.com/http_logs/access-unstructured.log.gz)
* [Structuré](https://datasets-documentation.s3.eu-west-3.amazonaws.com/http_logs/access-structured.log.gz)

Nous utilisons le jeu de données structuré pour l’exemple ci-dessous. Assurez-vous d’avoir téléchargé et extrait ce fichier pour reproduire les exemples suivants.

Ce qui suit présente une configuration simple pour l’OTel Collector, qui lit ces fichiers sur le disque à l’aide du receiver filelog et écrit les messages obtenus dans stdout. Nous utilisons l’opérateur [`json_parser`](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/stanza/docs/operators/json_parser.md), puisque nos logs sont structurés. Modifiez le chemin vers le fichier access-structured.log.

<Info>
  **Envisagez ClickHouse pour le parsing**

  L’exemple ci-dessous extrait le timestamp du log. Cela nécessite l’utilisation de l’opérateur `json_parser`, qui convertit toute la ligne de log en chaîne JSON et place le résultat dans `LogAttributes`. Cette opération peut être coûteuse en calcul et [peut être effectuée plus efficacement dans ClickHouse](https://clickhouse.com/blog/worlds-fastest-json-querying-tool-clickhouse-local) - [Extraction de la structure avec SQL](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#extracting-structure-with-sql). Un exemple non structuré équivalent, qui utilise le [`regex_parser`](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/stanza/docs/operators/regex_parser.md) pour obtenir le même résultat, est disponible [ici](https://pastila.nl/?01da7ee2/2ffd3ba8124a7d6e4ddf39422ad5b863#swBkiAXvGP7mRPgbuzzHFA==).
</Info>

**[config-structured-logs.yaml](https://www.otelbin.io/#config=receivers%3A*N_filelog%3A*N___include%3A*N_____-_%2Fopt%2Fdata%2Flogs%2Faccess-structured.log*N___start*_at%3A_beginning*N___operators%3A*N_____-_type%3A_json*_parser*N_______timestamp%3A*N_________parse*_from%3A_attributes.time*_local*N_________layout%3A_*%22*.Y-*.m-*.d_*.H%3A*.M%3A*.S*%22*N*N*Nprocessors%3A*N__batch%3A*N____timeout%3A_5s*N____send*_batch*_size%3A_1*N*N*Nexporters%3A*N_logging%3A*N___loglevel%3A_debug*N*N*Nservice%3A*N_pipelines%3A*N___logs%3A*N_____receivers%3A_%5Bfilelog%5D*N_____processors%3A_%5Bbatch%5D*N_____exporters%3A_%5Blogging%5D%7E)**

```yaml theme={null}
receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
processors:
  batch:
    timeout: 5s
    send_batch_size: 1
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [logging]
```

Vous pouvez suivre les [instructions officielles](https://opentelemetry.io/docs/collector/installation/) pour installer le collector localement. Veillez toutefois à adapter ces instructions afin d’utiliser la [distribution contrib](https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib) (qui contient le receiver `filelog`) ; par exemple, au lieu de `otelcol_0.102.1_darwin_arm64.tar.gz`, les utilisateurs devront télécharger `otelcol-contrib_0.102.1_darwin_arm64.tar.gz`. Les releases sont disponibles [ici](https://github.com/open-telemetry/opentelemetry-collector-releases/releases).

Une fois installé, l’OTel Collector peut être exécuté à l’aide des commandes suivantes :

```bash theme={null}
./otelcol-contrib --config config-logs.yaml
```

En utilisant des logs structurés, les messages prendront la forme suivante en sortie :

```response theme={null}
LogRecord #98
ObservedTimestamp: 2024-06-19 13:21:16.414259 +0000 UTC
Timestamp: 2019-01-22 01:12:53 +0000 UTC
SeverityText:
SeverityNumber: Unspecified(0)
Body: Str({"remote_addr":"66.249.66.195","remote_user":"-","run_time":"0","time_local":"2019-01-22 01:12:53.000","request_type":"GET","request_path":"\/product\/7564","request_protocol":"HTTP\/1.1","status":"301","size":"178","referer":"-","user_agent":"Mozilla\/5.0 (Linux; Android 6.0.1; Nexus 5X Build\/MMB29P) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/41.0.2272.96 Mobile Safari\/537.36 (compatible; Googlebot\/2.1; +http:\/\/www.google.com\/bot.html)"})
Attributes:
        -> remote_user: Str(-)
        -> request_protocol: Str(HTTP/1.1)
        -> time_local: Str(2019-01-22 01:12:53.000)
        -> user_agent: Str(Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html))
        -> log.file.name: Str(access.log)
        -> status: Str(301)
        -> size: Str(178)
        -> referer: Str(-)
        -> remote_addr: Str(66.249.66.195)
        -> request_type: Str(GET)
        -> request_path: Str(/product/7564)
        -> run_time: Str(0)
Trace ID:
Span ID:
Flags: 0
```

Le contenu ci-dessus représente un seul message de log tel que produit par l’OTel collector. Nous ingérons ces mêmes messages dans ClickHouse dans les sections suivantes.

Le schéma complet des messages de log, ainsi que les colonnes supplémentaires qui peuvent être présentes si vous utilisez d’autres receivers, est maintenu [ici](https://opentelemetry.io/docs/specs/otel/logs/data-model/). **Nous recommandons vivement aux utilisateurs de se familiariser avec ce schéma.**

L’élément essentiel ici est que la ligne de log elle-même est stockée sous forme de chaîne dans le champ `Body`, tandis que le JSON a été extrait automatiquement dans le champ Attributes grâce à `json_parser`. Ce même [operator](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/stanza/docs/operators/README.md#what-operators-are-available) a également été utilisé pour extraire le timestamp vers la colonne `Timestamp` appropriée. Pour des recommandations sur le traitement des logs avec OTel, voir [Processing](#processing---filtering-transforming-and-enriching).

<Info>
  **Opérateurs**

  Les opérateurs constituent l’unité la plus élémentaire du traitement des logs. Chaque opérateur remplit une fonction unique, comme lire des lignes depuis un fichier ou analyser du JSON à partir d’un champ. Les opérateurs sont ensuite chaînés dans un pipeline afin d’obtenir le résultat souhaité.
</Info>

Les messages ci-dessus n’ont pas de champ `TraceID` ni `SpanID`. S’ils étaient présents, par exemple dans les cas où des utilisateurs mettent en œuvre le [traçage distribué](https://opentelemetry.io/docs/concepts/observability-primer/#distributed-traces), ils pourraient être extraits du JSON en utilisant les mêmes techniques que celles présentées ci-dessus.

Pour les utilisateurs qui doivent collecter des fichiers de log locaux ou des fichiers de log Kubernetes, nous recommandons de se familiariser avec les options de configuration disponibles pour le [filelog receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/filelogreceiver/README.md#configuration), ainsi qu’avec la façon dont le suivi des [offsets](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/filelogreceiver#offset-tracking) et [l’analyse multiligne des logs sont gérés](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/filelogreceiver#example---multiline-logs-parsing).

<div id="collecting-kubernetes-logs">
  ## Collecte des logs Kubernetes
</div>

Pour la collecte des logs Kubernetes, nous recommandons le [guide de la documentation OpenTelemetry](https://opentelemetry.io/docs/kubernetes/). Le [Kubernetes Attributes Processor](https://opentelemetry.io/docs/kubernetes/collector/components/#kubernetes-attributes-processor) est recommandé pour enrichir les logs et les métriques avec les métadonnées des pods. Cela peut générer des métadonnées dynamiques, par exemple des labels, qui sont stockées dans la colonne `ResourceAttributes`. ClickHouse utilise actuellement le type `Map(String, String)` pour cette colonne. Voir [Using Maps](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#using-maps) et [Extracting from maps](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#extracting-from-maps) pour plus de détails sur la gestion et l’optimisation de ce type.

<div id="collecting-traces">
  ## Collecte de traces
</div>

Pour les utilisateurs qui souhaitent instrumenter leur code et collecter des traces, nous recommandons de suivre la [documentation officielle d’OTel](https://opentelemetry.io/docs/languages/).

Pour transmettre des événements à ClickHouse, vous devrez déployer un OTel collector afin de recevoir les événements de trace via le protocole OTLP à l’aide du receiver approprié. OpenTelemetry demo fournit un [exemple d’instrumentation pour chaque langage pris en charge](https://opentelemetry.io/docs/demo/) et d’envoi des événements à un collector. Un exemple de configuration de collector appropriée, qui envoie les événements vers stdout, est présenté ci-dessous :

<div id="example">
  ### Exemple
</div>

Comme les traces doivent être reçues via OTLP, nous utilisons l’outil [`telemetrygen`](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen) pour générer des données de trace. Suivez les instructions d’installation [ici](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen).

La configuration suivante reçoit des événements de trace via un receiver OTLP avant de les envoyer vers stdout.

[config-traces.xml](https://www.otelbin.io/#config=receivers%3A*N_otlp%3A*N___protocols%3A*N_____grpc%3A*N_______endpoint%3A_0.0.0.0%3A4317*N*Nprocessors%3A*N_batch%3A*N__timeout%3A_1s*N*Nexporters%3A*N_logging%3A*N___loglevel%3A_debug*N*Nservice%3A*N_pipelines%3A*N__traces%3A*N____receivers%3A_%5Botlp%5D*N____processors%3A_%5Bbatch%5D*N____exporters%3A_%5Blogging%5D%7E)

```yaml theme={null}
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 1s
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [logging]
```

Exécutez cette configuration comme suit :

```bash theme={null}
./otelcol-contrib --config config-traces.yaml
```

Envoyez des événements de trace au collector avec `telemetrygen` :

```bash theme={null}
$GOBIN/telemetrygen traces --otlp-insecure --traces 300
```

Cela produira des messages de trace similaires à l’exemple ci-dessous, envoyés vers stdout :

```response theme={null}
Span #86
        Trace ID        : 1bb5cdd2c9df5f0da320ca22045c60d9
        Parent ID       : ce129e5c2dd51378
        ID              : fbb14077b5e149a0
        Name            : okey-dokey-0
        Kind            : Server
        Start time      : 2024-06-19 18:03:41.603868 +0000 UTC
        End time        : 2024-06-19 18:03:41.603991 +0000 UTC
        Status code     : Unset
        Status message :
Attributes:
        -> net.peer.ip: Str(1.2.3.4)
        -> peer.service: Str(telemetrygen-client)
```

Ce qui précède représente un seul message de trace tel que produit par l’OTel collector. Nous ingérons ces mêmes messages dans ClickHouse dans les sections suivantes.

Le schéma complet des messages de trace est documenté [ici](https://opentelemetry.io/docs/concepts/signals/traces/). Nous recommandons vivement aux utilisateurs de se familiariser avec ce schéma.

<div id="processing---filtering-transforming-and-enriching">
  ## Traitement - filtrage, transformation et enrichissement
</div>

Comme l’a montré l’exemple précédent de définition du timestamp d’un événement de log, vous aurez presque toujours besoin de filtrer, transformer et enrichir les messages d’événement. Pour cela, OpenTelemetry offre plusieurs mécanismes :

* **Processors** - Les processors prennent les données collectées par les [receivers et les modifient ou les transforment](https://opentelemetry.io/docs/collector/transforming-telemetry/) avant de les envoyer aux exporters. Les processors sont appliqués dans l’ordre défini dans la section `processors` de la collector configuration. Ils sont facultatifs, mais l’ensemble minimal est [généralement recommandé](https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor#recommended-processors). Lors de l’utilisation d’un OTel collector avec ClickHouse, nous recommandons de limiter les processors à :

  * Un [memory\_limiter](https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/memorylimiterprocessor/README.md) sert à éviter les situations de saturation mémoire sur le collector. Consultez [Estimating Resources](#estimating-resources) pour les recommandations.
  * Tout processor qui effectue un enrichissement basé sur le contexte. Par exemple, le [Kubernetes Attributes Processor](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor) permet de définir automatiquement les resource attributes des spans, metrics et logs à partir des métadonnées k8s, par ex. en enrichissant les événements avec l’identifiant de leur pod source.
  * Le [tail sampling ou head sampling](https://opentelemetry.io/docs/concepts/sampling/), si nécessaire pour les traces.
  * Le [filtrage de base](https://opentelemetry.io/docs/collector/transforming-telemetry/) - suppression des événements inutiles si cela ne peut pas être fait via un opérateur (voir ci-dessous).
  * Le [batching](https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor/batchprocessor) - indispensable avec ClickHouse pour garantir l’envoi des données par lots. Voir [« Exporting to ClickHouse »](#exporting-to-clickhouse).

* **Opérateurs** - Les [opérateurs](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/stanza/docs/operators/README.md) constituent l’unité de traitement la plus élémentaire disponible au niveau du receiver. Ils prennent en charge le parsing de base, ce qui permet de définir des champs tels que Severity et Timestamp. Le parsing JSON et regex est pris en charge ici, ainsi que le filtrage d’événements et les transformations de base. Nous recommandons d’effectuer le filtrage des événements à ce niveau.

Nous recommandons aux utilisateurs d’éviter un traitement excessif des événements à l’aide d’opérateurs ou de [transform processors](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/transformprocessor/README.md). Ceux-ci peuvent entraîner une surcharge importante en mémoire et en CPU, en particulier le parsing JSON. Il est possible d’effectuer tout le traitement dans ClickHouse au moment de l’insert à l’aide de materialized views et de colonnes, à quelques exceptions près — notamment l’enrichissement dépendant du contexte, par ex. l’ajout de métadonnées k8s. Pour plus de détails, voir [Extracting structure with SQL](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#extracting-structure-with-sql).

Si le traitement est effectué à l’aide de l’OTel collector, nous recommandons d’exécuter les transformations sur les instances passerelle et de réduire au minimum le travail effectué sur les instances agent. Cela permet de limiter autant que possible les ressources requises par les agents en périphérie, exécutés sur les servers. En pratique, nous constatons que les utilisateurs n’effectuent généralement dans les agents que le filtrage (pour limiter l’utilisation réseau inutile), la définition des timestamps (via des opérateurs) et l’enrichissement lorsqu’il nécessite du contexte. Par exemple, si les instances passerelle se trouvent dans un Kubernetes cluster différent, l’enrichissement k8s devra être effectué dans l’agent.

<div id="example">
  ### Exemple
</div>

La configuration suivante montre la collecte d’un fichier de logs non structuré. Notez l’utilisation d’opérateurs pour extraire une structure des lignes de log (`regex_parser`) et filtrer les événements, ainsi que d’un processeur pour traiter les événements par lot et limiter la consommation mémoire.

[config-unstructured-logs-with-processor.yaml](https://www.otelbin.io/#config=receivers%3A*N_filelog%3A*N___include%3A*N_____-_%2Fopt%2Fdata%2Flogs%2Faccess-unstructured.log*N___start*_at%3A_beginning*N___operators%3A*N_____-_type%3A_regex*_parser*N_______regex%3A_*%22%5E*C*QP*Lip*G%5B*Bd.%5D*P*D*Bs*P-*Bs*P-*Bs*P*B%5B*C*QP*Ltimestamp*G%5B%5E*B%5D%5D*P*D*B%5D*Bs*P%22*C*QP*Lmethod*G%5BA-Z%5D*P*D*Bs*P*C*QP*Lurl*G%5B%5E*Bs%5D*P*D*Bs*PHTTP%2F%5B%5E*Bs%5D*P%22*Bs*P*C*QP*Lstatus*G*Bd*P*D*Bs*P*C*QP*Lsize*G*Bd*P*D*Bs*P%22*C*QP*Lreferrer*G%5B%5E%22%5D***D%22*Bs*P%22*C*QP*Luser*_agent*G%5B%5E%22%5D***D%22*%22*N_______timestamp%3A*N_________parse*_from%3A_attributes.timestamp*N_________layout%3A_*%22*.d%2F*.b%2F*.Y%3A*.H%3A*.M%3A*.S_*.z*%22*N_________*H22%2FJan%2F2019%3A03%3A56%3A14_*P0330*N*N*Nprocessors%3A*N_batch%3A*N___timeout%3A_1s*N___send*_batch*_size%3A_100*N_memory*_limiter%3A*N___check*_interval%3A_1s*N___limit*_mib%3A_2048*N___spike*_limit*_mib%3A_256*N*N*Nexporters%3A*N_logging%3A*N___loglevel%3A_debug*N*N*Nservice%3A*N_pipelines%3A*N___logs%3A*N_____receivers%3A_%5Bfilelog%5D*N_____processors%3A_%5Bbatch%2C_memory*_limiter%5D*N_____exporters%3A_%5Blogging%5D%7E)

```yaml theme={null}
receivers:
  filelog:
    include:
      - /opt/data/logs/access-unstructured.log
    start_at: beginning
    operators:
      - type: regex_parser
        regex: '^(?P<ip>[\d.]+)\s+-\s+-\s+\[(?P<timestamp>[^\]]+)\]\s+"(?P<method>[A-Z]+)\s+(?P<url>[^\s]+)\s+HTTP/[^\s]+"\s+(?P<status>\d+)\s+(?P<size>\d+)\s+"(?P<referrer>[^"]*)"\s+"(?P<user_agent>[^"]*)"'
        timestamp:
          parse_from: attributes.timestamp
          layout: '%d/%b/%Y:%H:%M:%S %z'
          #22/Jan/2019:03:56:14 +0330
processors:
  batch:
    timeout: 1s
    send_batch_size: 100
  memory_limiter:
    check_interval: 1s
    limit_mib: 2048
    spike_limit_mib: 256
exporters:
  logging:
    loglevel: debug
service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch, memory_limiter]
      exporters: [logging]
```

```bash theme={null}
./otelcol-contrib --config config-unstructured-logs-with-processor.yaml
```

<div id="exporting-to-clickhouse">
  ## Exportation vers ClickHouse
</div>

Les exporters envoient des données vers un ou plusieurs backends ou destinations. Les exporters peuvent être de type pull ou push. Pour envoyer des événements à ClickHouse, vous devez utiliser le [ClickHouse exporter](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/clickhouseexporter/README.md), qui fonctionne en mode push.

<Info>
  **Utilisez OpenTelemetry Collector Contrib**

  Le ClickHouse exporter fait partie d’[OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main), et non de la distribution principale. Vous pouvez soit utiliser la distribution contrib, soit [compiler votre propre collector](https://opentelemetry.io/docs/collector/custom-collector/).
</Info>

Un fichier de configuration complet est présenté ci-dessous.

[clickhouse-config.yaml](https://www.otelbin.io/#config=receivers%3A*N_filelog%3A*N___include%3A*N_____-_%2Fopt%2Fdata%2Flogs%2Faccess-structured.log*N___start*_at%3A_beginning*N___operators%3A*N_____-_type%3A_json*_parser*N_______timestamp%3A*N_________parse*_from%3A_attributes.time*_local*N_________layout%3A_*%22*.Y-*.m-*.d_*.H%3A*.M%3A*.S*%22*N_otlp%3A*N____protocols%3A*N______grpc%3A*N________endpoint%3A_0.0.0.0%3A4317*N*Nprocessors%3A*N_batch%3A*N___timeout%3A_5s*N___send*_batch*_size%3A_10000*N*Nexporters%3A*N_clickhouse%3A*N___endpoint%3A_tcp%3A%2F%2Flocalhost%3A9000*Qdial*_timeout*E10s*Acompress*Elz4*Aasync*_insert*E1*N___*H_ttl%3A_72h*N___traces*_table*_name%3A_otel*_traces*N___logs*_table*_name%3A_otel*_logs*N___create*_schema%3A_true*N___timeout%3A_5s*N___database%3A_default*N___sending*_queue%3A*N_____queue*_size%3A_1000*N___retry*_on*_failure%3A*N_____enabled%3A_true*N_____initial*_interval%3A_5s*N_____max*_interval%3A_30s*N_____max*_elapsed*_time%3A_300s*N*Nservice%3A*N_pipelines%3A*N___logs%3A*N_____receivers%3A_%5Bfilelog%5D*N_____processors%3A_%5Bbatch%5D*N_____exporters%3A_%5Bclickhouse%5D*N___traces%3A*N____receivers%3A_%5Botlp%5D*N____processors%3A_%5Bbatch%5D*N____exporters%3A_%5Bclickhouse%5D%7E\&distro=otelcol-contrib%7E\&distroVersion=v0.103.1%7E)

```yaml theme={null}
receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 5s
    send_batch_size: 10000
exporters:
  clickhouse:
    endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
    # ttl: 72h
    traces_table_name: otel_traces
    logs_table_name: otel_logs
    create_schema: true
    timeout: 5s
    database: default
    sending_queue:
      queue_size: 1000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s

service:
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [clickhouse]
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [clickhouse]
```

Notez les principaux paramètres suivants :

* **pipelines** - La configuration ci-dessus met en évidence l’utilisation des [pipelines](https://opentelemetry.io/docs/collector/configuration/#pipelines), composés d’un ensemble de receivers, de processeurs et d’exporters, avec un pipeline pour les logs et un pour les traces.
* **endpoint** - La communication avec ClickHouse est configurée via le paramètre `endpoint`. La chaîne de connexion `tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1` fait en sorte que la communication s’effectue sur TCP. Si vous préférez HTTP pour des raisons de basculement de trafic, modifiez cette chaîne de connexion comme décrit [ici](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/clickhouseexporter/README.md#configuration-options). Les détails complets de la connexion, y compris la possibilité de spécifier un nom d’utilisateur et un mot de passe dans cette chaîne de connexion, sont décrits [ici](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/clickhouseexporter/README.md#configuration-options).

**Important :** Notez que la chaîne de connexion ci-dessus active à la fois la compression (lz4) et les insertions asynchrones. Nous recommandons que les deux soient toujours activées. Consultez [regroupement par lots](#batching) pour plus de détails sur les insertions asynchrones. La compression doit toujours être spécifiée et ne sera pas activée par défaut sur les anciennes versions de l’exportateur.

* **ttl** - la valeur indiquée ici détermine la durée de conservation des données. Pour plus de détails, voir "Gestion des données". Cette valeur doit être spécifiée sous forme d’une unité de temps en heures, par exemple 72h. Nous désactivons le TTL dans l’exemple ci-dessous, car nos données datent de 2019 et seront immédiatement supprimées par ClickHouse si elles sont insérées.
* **traces\_table\_name** et **logs\_table\_name** - détermine le nom des tables de logs et de traces.
* **create\_schema** - détermine si les tables sont créées avec les schémas par défaut au démarrage. La valeur par défaut est true pour démarrer. Vous devriez le définir sur false et définir votre propre schéma.
* **database** - base de données cible.
* **retry\_on\_failure** - paramètres qui déterminent si les batches en échec doivent être retentés.
* **batch** - un batch processor garantit que les événements sont envoyés par batches. Nous recommandons une valeur d’au moins 10 000 avec un timeout de 5s (des valeurs allant jusqu’à 100 000 peuvent être utilisées si la mémoire le permet). Le premier de ces seuils atteint déclenchera l’envoi d’un batch à l’exportateur. Réduire ces valeurs permet d’obtenir un pipeline à plus faible latence, avec des données disponibles plus tôt pour les requêtes, au prix d’un plus grand nombre de connections et de batches envoyés à ClickHouse. Cela n’est pas recommandé si vous n’utilisez pas les [insertions asynchrones](https://clickhouse.com/blog/asynchronous-data-inserts-in-clickhouse), car cela peut provoquer des problèmes de [Too many parts](https://clickhouse.com/blog/common-getting-started-issues-with-clickhouse#1-too-many-parts) dans ClickHouse. À l’inverse, si vous utilisez les insertions asynchrones, la disponibilité de ces données pour les requêtes dépendra également des paramètres d’insertion asynchrone, même si les données seront tout de même transmises plus tôt par le connecteur. Consultez [regroupement par lots](#batching) pour plus de détails.
* **sending\_queue** - contrôle la taille de la file d’envoi. Chaque élément de la file contient un batch. Si cette file est saturée, par exemple parce que ClickHouse est inaccessible alors que les événements continuent d’arriver, les batches seront abandonnés.

En supposant que les utilisateurs aient extrait le fichier de logs structuré et disposent d’une [instance locale de ClickHouse](/docs/fr/get-started/setup/install) en cours d’exécution (avec l’authentification par défaut), vous pouvez exécuter cette configuration à l’aide de la commande :

```bash theme={null}
./otelcol-contrib --config clickhouse-config.yaml
```

Pour envoyer des données de traçage à ce collecteur, exécutez la commande suivante à l’aide de l’outil `telemetrygen` :

```bash theme={null}
$GOBIN/telemetrygen traces --otlp-insecure --traces 300
```

Une fois en fonctionnement, vérifiez la présence d’événements de log à l’aide d’une requête simple :

```sql theme={null}
SELECT *
FROM otel_logs
LIMIT 1
FORMAT Vertical
```

```response theme={null}
Row 1:
──────
Timestamp:              2019-01-22 06:46:14.000000000
TraceId:
SpanId:
TraceFlags:             0
SeverityText:
SeverityNumber:         0
ServiceName:
Body:                   {"remote_addr":"109.230.70.66","remote_user":"-","run_time":"0","time_local":"2019-01-22 06:46:14.000","request_type":"GET","request_path":"\/image\/61884\/productModel\/150x150","request_protocol":"HTTP\/1.1","status":"200","size":"1684","referer":"https:\/\/www.zanbil.ir\/filter\/p3%2Cb2","user_agent":"Mozilla\/5.0 (Windows NT 6.1; Win64; x64; rv:64.0) Gecko\/20100101 Firefox\/64.0"}
ResourceSchemaUrl:
ResourceAttributes: {}
ScopeSchemaUrl:
ScopeName:
ScopeVersion:
ScopeAttributes:        {}
LogAttributes:          {'referer':'https://www.zanbil.ir/filter/p3%2Cb2','log.file.name':'access-structured.log','run_time':'0','remote_user':'-','request_protocol':'HTTP/1.1','size':'1684','user_agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0','remote_addr':'109.230.70.66','request_path':'/image/61884/productModel/150x150','status':'200','time_local':'2019-01-22 06:46:14.000','request_type':'GET'}

1 row in set. Elapsed: 0.012 sec. Processed 5.04 thousand rows, 4.62 MB (414.14 thousand rows/s., 379.48 MB/s.)
Peak memory usage: 5.41 MiB.

Likewise, for trace events, you can check the `otel_traces` table:

SELECT *
FROM otel_traces
LIMIT 1
FORMAT Vertical

Row 1:
──────
Timestamp:              2024-06-20 11:36:41.181398000
TraceId:                00bba81fbd38a242ebb0c81a8ab85d8f
SpanId:                 beef91a2c8685ace
ParentSpanId:
TraceState:
SpanName:               lets-go
SpanKind:               SPAN_KIND_CLIENT
ServiceName:            telemetrygen
ResourceAttributes: {'service.name':'telemetrygen'}
ScopeName:              telemetrygen
ScopeVersion:
SpanAttributes:         {'peer.service':'telemetrygen-server','net.peer.ip':'1.2.3.4'}
Duration:               123000
StatusCode:             STATUS_CODE_UNSET
StatusMessage:
Events.Timestamp:   []
Events.Name:            []
Events.Attributes:  []
Links.TraceId:          []
Links.SpanId:           []
Links.TraceState:   []
Links.Attributes:   []
```

<div id="out-of-the-box-schema">
  ## Schéma prêt à l’emploi
</div>

<Tip>
  **ClickStack est livré avec un schéma par défaut optimisé**

  **ClickStack fournit des schémas prêts à l’emploi pour les logs, les traces et les métriques** qui intègrent les dernières fonctionnalités de ClickHouse (index textuels pour la recherche en texte intégral et par clé de Map, colonnes matérialisées et arrays ALIAS pour le filtrage en lecture directe, recherche de lignes par numéro de bloc) et ont été benchmarkés pour offrir de solides performances prêtes à l’emploi pour les charges de travail de logging et de traces. Utilisez-les comme point de départ pour votre propre conception.

  * DDL canonique : [Tables et schémas utilisés par ClickStack](/docs/fr/clickstack/ingesting-data/schemas).
  * Recettes d’optimisation : [Optimisation des performances de ClickStack](/docs/fr/clickstack/managing/performance-tuning). Bon nombre des recommandations de cette page (colonnes matérialisées, skip indexes, choix de la clé primaire, projections, vues matérialisées) s’appliquent directement à une configuration personnalisée.
</Tip>

Par défaut, le ClickHouse exporter crée les tables cibles pour les logs et les traces. Cela peut être désactivé avec le paramètre `create_schema`. En outre, les noms des tables de logs et de traces peuvent être modifiés par rapport à leurs valeurs par défaut, `otel_logs` et `otel_traces`, via les paramètres mentionnés ci-dessus.

<Note>
  Dans les schémas ci-dessous, nous supposons que TTL est configuré à 72 h.
</Note>

Le schéma par défaut pour les logs est présenté ci-dessous (`otelcol-contrib v0.102.1`) :

```sql theme={null}
CREATE TABLE default.otel_logs
(
    `Timestamp` DateTime64(9) CODEC(Delta(8), ZSTD(1)),
    `TraceId` String CODEC(ZSTD(1)),
    `SpanId` String CODEC(ZSTD(1)),
    `TraceFlags` UInt32 CODEC(ZSTD(1)),
    `SeverityText` LowCardinality(String) CODEC(ZSTD(1)),
    `SeverityNumber` Int32 CODEC(ZSTD(1)),
    `ServiceName` LowCardinality(String) CODEC(ZSTD(1)),
    `Body` String CODEC(ZSTD(1)),
    `ResourceSchemaUrl` String CODEC(ZSTD(1)),
    `ResourceAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    `ScopeSchemaUrl` String CODEC(ZSTD(1)),
    `ScopeName` String CODEC(ZSTD(1)),
    `ScopeVersion` String CODEC(ZSTD(1)),
    `ScopeAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    `LogAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
    INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1,
    INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
    INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 1
)
ENGINE = MergeTree
PARTITION BY toDate(Timestamp)
ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId)
TTL toDateTime(Timestamp) + toIntervalDay(3)
SETTINGS ttl_only_drop_parts = 1
```

Les colonnes présentées ici correspondent à la spécification officielle d’OTel pour les logs, décrite [ici](https://opentelemetry.io/docs/specs/otel/logs/data-model/).

Quelques remarques importantes concernant ce schéma :

* Par défaut, la table est partitionnée par date via `PARTITION BY toDate(Timestamp)`. Cela permet de supprimer efficacement les données expirées.
* Le TTL est défini via `TTL toDateTime(Timestamp) + toIntervalDay(3)` et correspond à la valeur définie dans la configuration du collector. [`ttl_only_drop_parts=1`](/docs/fr/reference/settings/merge-tree-settings#ttl_only_drop_parts) signifie que seules des parts entières sont supprimées lorsque toutes les lignes qu'elles contiennent ont expiré. C'est plus efficace que de supprimer des lignes à l'intérieur des parts, ce qui implique un `delete` coûteux. Nous recommandons de toujours définir ce paramètre. Consultez [Gestion des données avec TTL](/docs/fr/guides/use-cases/observability/build-your-own/managing-data#data-management-with-ttl-time-to-live) pour plus de détails.
* La table utilise le moteur classique [`MergeTree`](/docs/fr/reference/engines/table-engines/mergetree-family/mergetree). C'est la recommandation pour les logs et les traces, et il ne devrait pas être nécessaire de le modifier.
* La table est ordonnée par `ORDER BY (ServiceName, SeverityText, toUnixTimestamp(Timestamp), TraceId)`. Cela signifie que les requêtes seront optimisées pour les filtres sur `ServiceName`, `SeverityText`, `Timestamp` et `TraceId` : les colonnes placées plus tôt dans la liste seront filtrées plus rapidement que les suivantes ; par exemple, un filtrage sur `ServiceName` sera nettement plus rapide qu'un filtrage sur `TraceId`. Vous devez modifier cet ordre en fonction des schémas d’accès attendus ; voir [Choisir une clé primaire](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#choosing-a-primary-ordering-key).
* Le schéma ci-dessus applique `ZSTD(1)` aux colonnes. Cela offre la meilleure compression pour les logs. Vous pouvez augmenter le niveau de compression ZSTD (au-dessus de la valeur par défaut de 1) pour obtenir une meilleure compression, bien que cela soit rarement avantageux. Augmenter cette valeur entraînera une surcharge CPU plus importante au moment de l'insert (pendant la compression), même si la décompression (et donc les requêtes) devrait rester comparable. Consultez [ce lien](https://clickhouse.com/blog/optimize-clickhouse-codecs-compression-schema) pour plus de détails. Un [encodage delta](/docs/fr/reference/statements/create/table#delta) supplémentaire est appliqué à `Timestamp` afin de réduire sa taille sur disque.
* Notez que [`ResourceAttributes`](https://opentelemetry.io/docs/specs/otel/resource/sdk/), [`LogAttributes`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-attributes) et [`ScopeAttributes`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-instrumentationscope) sont des maps. Il est important de bien comprendre les différences entre ces éléments. Consultez ["Utiliser les maps"](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#using-maps) pour savoir comment accéder à ces maps et optimiser l'accès aux clés qu'elles contiennent.
* La plupart des autres types ici, par exemple `ServiceName` en `LowCardinality`, sont optimisés. Notez que `Body`, qui est du JSON dans nos logs d'exemple, est stocké sous forme de `String`.
* Des bloom filters sont appliqués aux clés et valeurs des maps, ainsi qu'à la colonne `Body`. Ils visent à améliorer le temps d'exécution des requêtes qui accèdent à ces colonnes, mais ne sont généralement pas nécessaires. Consultez [Indices secondaires / data skipping indices](/docs/fr/guides/use-cases/observability/build-your-own/schema-design#secondarydata-skipping-indices).

```sql theme={null}
CREATE TABLE default.otel_traces
(
        `Timestamp` DateTime64(9) CODEC(Delta(8), ZSTD(1)),
        `TraceId` String CODEC(ZSTD(1)),
        `SpanId` String CODEC(ZSTD(1)),
        `ParentSpanId` String CODEC(ZSTD(1)),
        `TraceState` String CODEC(ZSTD(1)),
        `SpanName` LowCardinality(String) CODEC(ZSTD(1)),
        `SpanKind` LowCardinality(String) CODEC(ZSTD(1)),
        `ServiceName` LowCardinality(String) CODEC(ZSTD(1)),
        `ResourceAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
        `ScopeName` String CODEC(ZSTD(1)),
        `ScopeVersion` String CODEC(ZSTD(1)),
        `SpanAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
        `Duration` Int64 CODEC(ZSTD(1)),
        `StatusCode` LowCardinality(String) CODEC(ZSTD(1)),
        `StatusMessage` String CODEC(ZSTD(1)),
        `Events.Timestamp` Array(DateTime64(9)) CODEC(ZSTD(1)),
        `Events.Name` Array(LowCardinality(String)) CODEC(ZSTD(1)),
        `Events.Attributes` Array(Map(LowCardinality(String), String)) CODEC(ZSTD(1)),
        `Links.TraceId` Array(String) CODEC(ZSTD(1)),
        `Links.SpanId` Array(String) CODEC(ZSTD(1)),
        `Links.TraceState` Array(String) CODEC(ZSTD(1)),
        `Links.Attributes` Array(Map(LowCardinality(String), String)) CODEC(ZSTD(1)),
        INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1,
        INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_span_attr_key mapKeys(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_span_attr_value mapValues(SpanAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
        INDEX idx_duration Duration TYPE minmax GRANULARITY 1
)
ENGINE = MergeTree
PARTITION BY toDate(Timestamp)
ORDER BY (ServiceName, SpanName, toUnixTimestamp(Timestamp), TraceId)
TTL toDateTime(Timestamp) + toIntervalDay(3)
SETTINGS ttl_only_drop_parts = 1
```

Là encore, cela s’alignera sur les colonnes correspondant à la spécification officielle d’OTel pour les traces, documentée [ici](https://opentelemetry.io/docs/specs/otel/trace/api/). Le schéma utilise ici bon nombre des mêmes paramètres que le schéma de logs ci-dessus, avec des colonnes Link supplémentaires propres aux spans.

Nous recommandons aux utilisateurs de désactiver la création automatique du schéma et de créer leurs tables manuellement. Cela permet de modifier les clés primaire et secondaire, ainsi que d’ajouter des colonnes supplémentaires pour optimiser les performances des requêtes. Pour plus de détails, consultez [Schema design](/docs/fr/guides/use-cases/observability/build-your-own/schema-design).

<div id="optimizing-inserts">
  ## Optimisation des insertions
</div>

Pour obtenir de bonnes performances d’insertion tout en bénéficiant de fortes garanties de cohérence, respectez quelques règles simples lorsque vous insérez des données d’observabilité dans ClickHouse via le collector. Avec une configuration correcte de l’OTel collector, les règles suivantes sont faciles à appliquer. Cela permet également d’éviter les [problèmes courants](https://clickhouse.com/blog/common-getting-started-issues-with-clickhouse) que rencontrent les utilisateurs qui découvrent ClickHouse.

<div id="batching">
  ### Regroupement par lots
</div>

Par défaut, chaque insertion envoyée à ClickHouse amène ClickHouse à créer immédiatement une part de stockage contenant les données de l’insertion ainsi que les autres métadonnées à stocker. Par conséquent, envoyer moins d’insertions contenant chacune davantage de données, plutôt qu’un plus grand nombre d’insertions contenant chacune moins de données, réduit le nombre d’écritures nécessaires. Nous recommandons d’insérer les données par lots assez volumineux, d’au moins 1 000 lignes à la fois. Plus de détails [ici](https://clickhouse.com/blog/asynchronous-data-inserts-in-clickhouse#data-needs-to-be-batched-for-optimal-performance).

Par défaut, les insertions dans ClickHouse sont synchrones et idempotentes lorsqu’elles sont identiques. Pour les tables de la famille de moteurs MergeTree, ClickHouse [déduplique automatiquement les insertions](https://clickhouse.com/blog/common-getting-started-issues-with-clickhouse#5-deduplication-at-insert-time) par défaut. Cela signifie que les insertions tolèrent des situations comme les suivantes :

* (1) Si le nœud qui reçoit les données rencontre un problème, la requête d’insertion expire (ou renvoie une erreur plus spécifique) et ne reçoit pas d’accusé de réception.
* (2) Si les données ont bien été écrites par le nœud, mais que l’accusé de réception ne peut pas être renvoyé à l’émetteur de la requête en raison d’interruptions réseau, l’émetteur recevra soit un délai d’expiration, soit une erreur réseau.

Du point de vue du collector, il peut être difficile de distinguer (1) de (2). Cependant, dans les deux cas, l’insertion non acquittée peut simplement être retentée immédiatement. Tant que la requête d’insertion retentée contient les mêmes données dans le même ordre, ClickHouse ignorera automatiquement cette nouvelle tentative si l’insertion d’origine (non acquittée) a réussi.

Nous recommandons aux utilisateurs d’utiliser le [batch processor](https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/README.md) présenté dans les configurations précédentes pour répondre à ces exigences. Cela garantit que les insertions sont envoyées sous forme de lots cohérents de lignes respectant les conditions ci-dessus. Si un collector doit traiter un débit élevé (événements par seconde) et qu’au moins 10 000 événements peuvent être envoyés à chaque insertion, c’est généralement le seul regroupement par lots nécessaire dans le pipeline. Des valeurs allant jusqu’à 100 000 peuvent être utilisées si la mémoire le permet. Dans ce cas, le collector flush les lots avant que le `timeout` du batch processor ne soit atteint, ce qui garantit une faible latence de bout en bout du pipeline ainsi qu’une taille de lot cohérente.

<div id="use-asynchronous-inserts">
  ### Utiliser les insertions asynchrones
</div>

En règle générale, les utilisateurs sont contraints d’envoyer des lots plus petits lorsque le débit d’un collector est faible, tout en s’attendant à ce que les données parviennent à ClickHouse avec une latence de bout en bout minimale. Dans ce cas, de petits lots sont envoyés à l’expiration du `timeout` du batch processor. Cela peut poser problème, et c’est précisément dans ce type de situation que les insertions asynchrones deviennent nécessaires. Ce cas se présente généralement lorsque **des collectors dans le rôle d’agent sont configurés pour envoyer directement vers ClickHouse**. Les passerelles, en jouant un rôle d’agrégation, peuvent atténuer ce problème ; voir [Scaling with Gateways](#scaling-with-gateways).

S’il n’est pas possible de garantir de gros lots, vous pouvez déléguer le regroupement par lots à ClickHouse en utilisant les [insertions asynchrones](/docs/fr/concepts/best-practices/selecting-an-insert-strategy#asynchronous-inserts). Avec les insertions asynchrones, les données sont d’abord insérées dans un buffer, puis écrites ultérieurement dans le stockage de la base de données, donc de manière asynchrone.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-6.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=40e17f316483f64085ad3b5580b578ca" alt="Insertions asynchrones" size="md" width="1600" height="1130" data-path="images/use-cases/observability/observability-6.webp" />

Lorsque les [insertions asynchrones sont activées](/docs/fr/concepts/features/operations/insert/asyncinserts#enabling-asynchronous-inserts), quand ClickHouse ① reçoit une insert query, les données de la requête sont ② immédiatement écrites dans un buffer en mémoire. Lors du ③ prochain flush du buffer, les données du buffer sont [triées](/docs/fr/guides/clickhouse/data-modelling/sparse-primary-indexes#data-is-stored-on-disk-ordered-by-primary-key-columns) et écrites sous forme de part dans le stockage de la base de données. Notez que les données ne peuvent pas être interrogées avant d’avoir été flushées vers le stockage de la base de données ; le flush du buffer est [configurable](/docs/fr/concepts/features/operations/insert/asyncinserts).

Pour activer les insertions asynchrones pour le collector, ajoutez `async_insert=1` à la chaîne de connexion. Nous recommandons d’utiliser `wait_for_async_insert=1` (valeur par défaut) afin d’obtenir des garanties de livraison ; voir [ici](https://clickhouse.com/blog/asynchronous-data-inserts-in-clickhouse) pour plus de détails.

Les données d’une async insert sont insérées une fois le buffer ClickHouse flushé. Cela se produit soit lorsque [`async_insert_max_data_size`](/docs/fr/reference/settings/session-settings#async_insert_max_data_size) est dépassé, soit après [`async_insert_busy_timeout_ms`](/docs/fr/reference/settings/session-settings#async_insert_max_data_size) millisecondes à partir de la première INSERT query. Si `async_insert_stale_timeout_ms` est défini sur une valeur non nulle, les données sont insérées après `async_insert_stale_timeout_ms milliseconds` depuis la dernière query. Vous pouvez ajuster ces settings pour contrôler la latence de bout en bout de votre pipeline. D’autres settings permettant d’ajuster le flush du buffer sont documentés [ici](/docs/fr/reference/settings/session-settings#async_insert). En règle générale, les valeurs par défaut conviennent.

<Info>
  **Envisagez les insertions asynchrones adaptatives**

  Dans les cas où un petit nombre d’agents est utilisé, avec un débit faible mais des exigences strictes en matière de latence de bout en bout, les [insertions asynchrones adaptatives](https://clickhouse.com/blog/clickhouse-release-24-02#adaptive-asynchronous-inserts) peuvent être utiles. En règle générale, elles ne s’appliquent pas aux cas d’usage d’observability à haut débit, comme ceux observés avec ClickHouse.
</Info>

Enfin, le comportement précédent de déduplication associé aux insertions synchrones dans ClickHouse n’est pas activé par défaut lors de l’utilisation d’insertions asynchrones. Si nécessaire, consultez le paramètre [`async_insert_deduplicate`](/docs/fr/reference/settings/session-settings#async_insert_deduplicate).

Tous les détails sur la configuration de cette fonctionnalité sont disponibles [ici](/docs/fr/concepts/features/operations/insert/asyncinserts#enabling-asynchronous-inserts), avec une analyse approfondie [ici](https://clickhouse.com/blog/asynchronous-data-inserts-in-clickhouse).

<div id="deployment-architectures">
  ## Architectures de déploiement
</div>

Plusieurs architectures de déploiement sont possibles lors de l’utilisation de l’OTel collector avec ClickHouse. Nous décrivons ci-dessous chacune d’elles et indiquons dans quels cas elle est la plus adaptée.

<div id="agents-only">
  ### Agents uniquement
</div>

Dans une architecture composée uniquement d’agents, les utilisateurs déploient l’OTel collector à la périphérie sous forme d’agents. Ceux-ci reçoivent les traces des applications locales (par ex. via un conteneur sidecar) et collectent les logs des serveurs et des nœuds Kubernetes. Dans ce mode, les agents envoient leurs données directement à ClickHouse.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-7.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=59877047c8f3b5ea5129339728da6a4b" alt="Agents uniquement" size="md" width="1000" height="1000" data-path="images/use-cases/observability/observability-7.webp" />

Cette architecture convient aux déploiements de petite à moyenne taille. Son principal avantage est qu’elle ne nécessite pas de matériel supplémentaire et qu’elle réduit au minimum l’empreinte globale en ressources de la solution d’observabilité ClickHouse, avec une correspondance simple entre applications et collecteurs.

Vous devriez envisager de migrer vers une architecture basée sur des passerelles lorsque le nombre d’agents dépasse plusieurs centaines. Cette architecture présente plusieurs inconvénients qui compliquent sa mise à l’échelle :

* **Mise à l’échelle des connexions** - Chaque agent établit une connexion à ClickHouse. Bien que ClickHouse puisse maintenir des centaines, voire des milliers, de connexions d’insertion concurrentes, cela finit par devenir un facteur limitant et par rendre les insertions moins efficaces : ClickHouse consacre alors davantage de ressources au maintien de ces connexions. L’utilisation de passerelles réduit le nombre de connexions et améliore l’efficacité des insertions.
* **Traitement à la périphérie** - Dans cette architecture, toute transformation ou tout traitement des événements doit être effectué à la périphérie ou dans ClickHouse. En plus d’être contraignant, cela peut impliquer soit des vues matérialisées ClickHouse complexes, soit le déplacement d’une part importante du calcul vers la périphérie, où les ressources sont limitées et les services critiques peuvent être affectés.
* **Petits lots et latences** - Les collectors agents peuvent, individuellement, collecter très peu d’événements. Cela signifie généralement qu’ils doivent être configurés pour envoyer leurs données à intervalle défini afin de respecter les SLA de livraison. Le collector peut alors envoyer de petits lots à ClickHouse. Bien que ce soit un inconvénient, il peut être atténué avec les insertions asynchrones - voir [Optimiser les insertions](#optimizing-inserts).

<div id="scaling-with-gateways">
  ### Mise à l’échelle avec des passerelles
</div>

Les OTel collectors peuvent être déployés en tant qu’instances passerelle pour pallier les limitations décrites ci-dessus. Ils fournissent un service autonome, généralement par centre de données ou par région. Ils reçoivent les événements des applications (ou d’autres collectors jouant le rôle d’agent) via un unique point de terminaison OTLP. En général, un ensemble d’instances passerelle est déployé, avec un load balancer prêt à l’emploi pour répartir la charge entre elles.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-8.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=967971cf6843028dba83f621191be822" alt="Mise à l’échelle avec des passerelles" size="md" width="1400" height="1000" data-path="images/use-cases/observability/observability-8.webp" />

L’objectif de cette architecture est de décharger les agents des traitements intensifs en calcul, afin de réduire au minimum leur consommation de ressources. Ces passerelles peuvent effectuer des tâches de transformation qui, autrement, devraient être réalisées par les agents. En outre, en agrégeant les événements provenant de nombreux agents, les passerelles peuvent garantir l’envoi de batches volumineux vers ClickHouse, ce qui permet une insertion efficace. Ces passerelle collectors peuvent facilement passer à l’échelle à mesure que davantage d’agents sont ajoutés et que le débit des événements augmente. Un exemple de configuration passerelle, accompagné d’une configuration d’agent associée consommant le fichier journal structuré d’exemple, est présenté ci-dessous. Notez l’utilisation d’OTLP pour la communication entre l’agent et la passerelle.

[clickhouse-agent-config.yaml](https://www.otelbin.io/#config=receivers%3A*N_filelog%3A*N___include%3A*N_____-_%2Fopt%2Fdata%2Flogs%2Faccess-structured.log*N___start*_at%3A_beginning*N___operators%3A*N_____-_type%3A_json*_parser*N_______timestamp%3A*N_________parse*_from%3A_attributes.time*_local*N_________layout%3A_*%22*.Y-*.m-*.d_*.H%3A*.M%3A*.S*%22*N*Nprocessors%3A*N_batch%3A*N___timeout%3A_5s*N___send*_batch*_size%3A_10000*N*Nexporters%3A*N_otlp%3A*N___endpoint%3A_localhost%3A4317*N___tls%3A*N_____insecure%3A_true_*H_Set_to_false_if_you_are_using_a_secure_connection*N*Nservice%3A*N_telemetry%3A*N___metrics%3A*N_____address%3A_0.0.0.0%3A9888_*H_Modified_as_2_collectors_running_on_same_host*N_pipelines%3A*N___logs%3A*N_____receivers%3A_%5Bfilelog%5D*N_____processors%3A_%5Bbatch%5D*N_____exporters%3A_%5Botlp%5D%7E\&distro=otelcol-contrib%7E\&distroVersion=v0.103.1%7E)

```yaml theme={null}
receivers:
  filelog:
    include:
      - /opt/data/logs/access-structured.log
    start_at: beginning
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time_local
          layout: '%Y-%m-%d %H:%M:%S'
processors:
  batch:
    timeout: 5s
    send_batch_size: 10000
exporters:
  otlp:
    endpoint: localhost:4317
    tls:
      insecure: true # Set to false if you are using a secure connection
service:
  telemetry:
    metrics:
      address: 0.0.0.0:9888 # Modified as 2 collectors running on same host
  pipelines:
    logs:
      receivers: [filelog]
      processors: [batch]
      exporters: [otlp]
```

[clickhouse-gateway-config.yaml](https://www.otelbin.io/#config=receivers%3A*N__otlp%3A*N____protocols%3A*N____grpc%3A*N____endpoint%3A_0.0.0.0%3A4317*N*Nprocessors%3A*N__batch%3A*N____timeout%3A_5s*N____send*_batch*_size%3A_10000*N*Nexporters%3A*N__clickhouse%3A*N____endpoint%3A_tcp%3A%2F%2Flocalhost%3A9000*Qdial*_timeout*E10s*Acompress*Elz4*N____ttl%3A_96h*N____traces*_table*_name%3A_otel*_traces*N____logs*_table*_name%3A_otel*_logs*N____create*_schema%3A_true*N____timeout%3A_10s*N____database%3A_default*N____sending*_queue%3A*N____queue*_size%3A_10000*N____retry*_on*_failure%3A*N____enabled%3A_true*N____initial*_interval%3A_5s*N____max*_interval%3A_30s*N____max*_elapsed*_time%3A_300s*N*Nservice%3A*N__pipelines%3A*N____logs%3A*N______receivers%3A_%5Botlp%5D*N______processors%3A_%5Bbatch%5D*N______exporters%3A_%5Bclickhouse%5D%7E\&distro=otelcol-contrib%7E\&distroVersion=v0.103.1%7E)

```yaml theme={null}
receivers:
  otlp:
    protocols:
    grpc:
    endpoint: 0.0.0.0:4317
processors:
  batch:
    timeout: 5s
    send_batch_size: 10000
exporters:
  clickhouse:
    endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4
    ttl: 96h
    traces_table_name: otel_traces
    logs_table_name: otel_logs
    create_schema: true
    timeout: 10s
    database: default
    sending_queue:
      queue_size: 10000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s
service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [clickhouse]
```

Vous pouvez exécuter ces configurations à l’aide des commandes suivantes.

```bash theme={null}
./otelcol-contrib --config clickhouse-gateway-config.yaml
./otelcol-contrib --config clickhouse-agent-config.yaml
```

Le principal inconvénient de cette architecture réside dans le coût et la charge opérationnelle liés à la gestion d’un ensemble de collecteurs.

Pour un exemple de gestion d’architectures de plus grande envergure basées sur des passerelles, ainsi que des enseignements qui en sont tirés, nous recommandons cet [article de blog](https://clickhouse.com/blog/building-a-logging-platform-with-clickhouse-and-saving-millions-over-datadog).

<div id="adding-kafka">
  ### Ajout de Kafka
</div>

Les lecteurs remarqueront peut-être que les architectures ci-dessus n’utilisent pas Kafka comme file de messages.

L’utilisation d’une file Kafka comme tampon de messages est un modèle de conception courant dans les architectures de logs, popularisé par la stack ELK. Elle offre plusieurs avantages : principalement, elle permet de meilleures garanties de livraison des messages et aide à gérer le backpressure. Les messages sont envoyés par les agents de collecte vers Kafka, puis écrits sur disque. En théorie, une instance Kafka en cluster devrait fournir un tampon de messages à haut débit, car écrire des données de façon séquentielle sur disque demande moins de surcharge de calcul que d’analyser et de traiter un message — dans Elastic, par exemple, la tokenisation et l’indexation entraînent une surcharge importante. En déplaçant les données hors des agents, vous réduisez aussi le risque de perdre des messages à cause de la rotation des logs à la source. Enfin, cela offre des capacités de rejeu des messages et de réplication inter-régions, ce qui peut être intéressant pour certains cas d’usage.

Cependant, ClickHouse peut insérer des données très rapidement — des millions de lignes par seconde sur un matériel modeste. Le backpressure venant de ClickHouse est **rare**. Bien souvent, s’appuyer sur une file Kafka ajoute de la complexité architecturale et des coûts. Si vous adhérez au principe selon lequel les logs n’ont pas besoin des mêmes garanties de livraison que des transactions bancaires et d’autres données critiques, nous vous recommandons d’éviter la complexité de Kafka.

Cependant, si vous avez besoin de fortes garanties de livraison ou de la possibilité de rejouer les données (éventuellement vers plusieurs sources), Kafka peut être un ajout architectural utile.

<Image img="https://mintcdn.com/private-7c7dfe99/yqUlQ9JxYel6WYEx/images/use-cases/observability/observability-9.webp?fit=max&auto=format&n=yqUlQ9JxYel6WYEx&q=85&s=a3c001618140e81f8ca463da2fda430f" alt="Ajout de Kafka" size="md" width="1400" height="585" data-path="images/use-cases/observability/observability-9.webp" />

Dans ce cas, les agents OTel peuvent être configurés pour envoyer les données vers Kafka via le [Kafka exporter](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/kafkaexporter/README.md). Les instances passerelle, à leur tour, consomment les messages à l’aide du [Kafka receiver](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/kafkareceiver/README.md). Nous vous recommandons de consulter la documentation de Confluent et d’OTel pour plus de détails.

<div id="estimating-resources">
  ### Estimation des ressources
</div>

Les besoins en ressources de l’OTel collector dépendent du débit d’événements, de la taille des messages et du niveau de traitement appliqué. Le projet OpenTelemetry publie des [benchmarks](https://opentelemetry.io/docs/collector/benchmarks/) que les utilisateurs peuvent consulter pour estimer ces besoins.

[D’après notre expérience](https://clickhouse.com/blog/building-a-logging-platform-with-clickhouse-and-saving-millions-over-datadog#architectural-overview), une instance gateway disposant de 3 cœurs et de 12 GB de RAM peut traiter environ 60 k événements par seconde. Cela suppose un pipeline de traitement minimal, limité au renommage des champs et n’utilisant aucune expression régulière.

Pour les instances agent chargées d’acheminer les événements vers une gateway et de simplement définir le timestamp de l’événement, nous recommandons de dimensionner les ressources en fonction du volume de logs attendu par seconde. Les valeurs suivantes sont des ordres de grandeur que vous pouvez utiliser comme point de départ :

| Taux de logging | Ressources pour l’agent collector |
| --------------- | --------------------------------- |
| 1k/second       | 0.2CPU, 0.2GiB                    |
| 5k/second       | 0.5 CPU, 0.5GiB                   |
| 10k/second      | 1 CPU, 1GiB                       |
