> ## 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.

> Comment acheminer en continu un fichier de log vers ClickHouse avec Vector

# Intégrer Vector à ClickHouse

export const PartnerBadge = () => {
  return <div className="PartnerBadge">
            <div className="PartnerBadgeIcon">
                <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <polyline points="12.5 9.5 10 12 6 11 2.5 8.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <polyline points="4.54 4.41 8 3.5 11.46 4.41" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M2.15,3.78 L0.55,6.95 A0.5,0.5 0,0,0 0.77,7.62 L2.5,8.5 L4.54,4.41 L2.82,3.55 A0.5,0.5 0,0,0 2.15,3.78 Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M13.5,8.5 L15.23,7.62 A0.5,0.5 0,0,0 15.45,6.95 L13.85,3.78 A0.5,0.5 0,0,0 13.18,3.55 L11.46,4.41 Z" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <path d="M11.5,4.5 L9,4.5 L6.15,7.27 A0.5,0.5 0,0,0 6.24,8.05 C7.33,8.74 8.81,8.72 10,7.5 L12.5,9.5 L13.5,8.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                    <polyline points="7.75 13.5 5.15 12.85 3.5 11.67" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1" />
                </svg>
            </div>
            Intégration partenaire
        </div>;
};

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>;
};

<PartnerBadge />

Pouvoir analyser vos logs en temps réel est essentiel pour les applications en production.
ClickHouse excelle dans le stockage et l’analyse des logs grâce à son excellente compression (jusqu’à [170x](https://clickhouse.com/blog/log-compression-170x) pour les logs)
et à sa capacité à agréger rapidement de grandes quantités de données.

Ce guide vous montre comment utiliser le pipeline de données populaire [Vector](https://vector.dev/docs/introduction/) pour lire en continu un fichier de log Nginx et l’envoyer vers ClickHouse.
Les étapes ci-dessous sont similaires pour la lecture en continu de tout type de fichier de log.

**Prérequis :**

* Vous avez déjà ClickHouse opérationnel
* Vous avez installé Vector

<Steps>
  <Step title="Créer une base de données et une table" id="1-create-a-database-and-table">
    Définissez une table pour stocker les événements de logs :

    1. Commencez par créer une base de données nommée `nginxdb` :

    ```sql theme={null}
    CREATE DATABASE IF NOT EXISTS nginxdb
    ```

    2. Insérez l’intégralité de l’événement de log sous la forme d’une seule chaîne. Ce n’est évidemment pas un format idéal pour effectuer des analyses sur les données de log, mais nous verrons ci-dessous comment y remédier à l’aide de ***vues matérialisées***.

    ```sql theme={null}
    CREATE TABLE IF NOT EXISTS  nginxdb.access_logs (
      message String
    )
    ENGINE = MergeTree()
    ORDER BY tuple()
    ```

    <Note>
      **ORDER BY** est défini comme **tuple()** (un tuple vide), car il n’est pas encore nécessaire d’utiliser une clé primaire.
    </Note>
  </Step>

  <Step title="Configurer Nginx" id="2--configure-nginx">
    Dans cette étape, vous allez voir comment configurer la journalisation de Nginx.

    1. La directive `access_log` suivante envoie les logs vers `/var/log/nginx/my_access.log` au format **combined**.
       Cette valeur se place dans la section `http` de votre fichier `nginx.conf` :

    ```bash theme={null}
    http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      access_log  /var/log/nginx/my_access.log combined;
      sendfile        on;
      keepalive_timeout  65;
      include /etc/nginx/conf.d/*.conf;
    }
    ```

    2. Veillez à redémarrer Nginx si vous avez dû modifier `nginx.conf`.

    3. Générez quelques événements dans le log d'accès en visitant des pages sur votre serveur web.
       Les logs au format **combined** se présentent comme suit :

    ```bash theme={null}
    192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    192.168.208.1 - - [12/Oct/2021:03:31:44 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    192.168.208.1 - - [12/Oct/2021:03:31:49 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    ```
  </Step>

  <Step title="Configurer Vector" id="3-configure-vector">
    Vector collecte, transforme et achemine les logs, les métriques et les traces (appelés **sources**) vers de nombreux fournisseurs différents (appelés **sinks**), avec une compatibilité native avec ClickHouse.
    Les sources et les sinks sont définis dans un fichier de configuration nommé **vector.toml**.

    1. Le fichier **vector.toml** suivant définit une **source** de type **file** qui lit en continu la fin de **my\_access.log**, et définit également un **sink** correspondant à la table **access\_logs** définie ci-dessus :

    ```bash theme={null}
    [sources.nginx_logs]
    type = "file"
    include = [ "/var/log/nginx/my_access.log" ]
    read_from = "end"

    [sinks.clickhouse]
    type = "clickhouse"
    inputs = ["nginx_logs"]
    endpoint = "http://clickhouse-server:8123"
    database = "nginxdb"
    table = "access_logs"
    skip_unknown_fields = true
    ```

    2. Démarrez Vector à l’aide de la configuration ci-dessus. Consultez la [documentation](https://vector.dev/docs/) de Vector pour plus de détails sur la définition des sources et des destinations.

    3. Vérifiez que les logs d’accès sont bien insérés dans ClickHouse en exécutant la requête suivante. Vous devriez voir les logs d’accès dans votre table :

    ```sql theme={null}
    SELECT * FROM nginxdb.access_logs
    ```

    <Image img="https://mintcdn.com/private-7c7dfe99/pIetLsS_hOGHqoPJ/images/integrations/data-ingestion/etl-tools/vector_01.webp?fit=max&auto=format&n=pIetLsS_hOGHqoPJ&q=85&s=17d0b62d95271cb39b27558a8391172a" size="lg" border alt="Afficher les logs ClickHouse sous forme de tableau" width="2364" height="776" data-path="images/integrations/data-ingestion/etl-tools/vector_01.webp" />
  </Step>

  <Step title="Analyser les journaux" id="4-parse-the-logs">
    Avoir les logs dans ClickHouse est une bonne chose, mais stocker chaque événement sous forme d'une chaîne unique ne permet pas une analyse approfondie des données.
    Nous allons maintenant voir comment parser les événements de log à l'aide d'une [vue matérialisée](/docs/fr/concepts/features/materialized-views/incremental-materialized-view).

    Une **vue matérialisée** fonctionne de manière similaire à un déclencheur d'insertion en SQL. Lorsque des lignes de données sont insérées dans une table source, la vue matérialisée effectue une transformation de ces lignes et insère les résultats dans une table cible.
    La vue matérialisée peut être configurée pour produire une représentation parsée des événements de logs dans **access\_logs**.
    Un exemple d'un tel événement de log est présenté ci-dessous :

    ```bash theme={null}
    192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"
    ```

    ClickHouse propose diverses fonctions pour analyser la chaîne ci-dessus. La fonction [`splitByWhitespace`](/docs/fr/reference/functions/regular-functions/splitting-merging-functions#splitByWhitespace) analyse une chaîne en la découpant par espaces blancs et renvoie chaque token dans un tableau.
    Pour illustrer, exécutez la commande suivante :

    ```sql title="Query" theme={null}
    SELECT splitByWhitespace('192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')
    ```

    ```text title="Response" theme={null}
    ["192.168.208.1","-","-","[12/Oct/2021:15:32:43","+0000]","\"GET","/","HTTP/1.1\"","304","0","\"-\"","\"Mozilla/5.0","(Macintosh;","Intel","Mac","OS","X","10_15_7)","AppleWebKit/537.36","(KHTML,","like","Gecko)","Chrome/93.0.4577.63","Safari/537.36\""]
    ```

    Quelques-unes des chaînes contiennent des caractères supplémentaires, et le user agent (les détails du navigateur) n'avait pas besoin d'être parsé, mais
    le tableau résultant est proche de ce dont nous avons besoin.

    Semblable à `splitByWhitespace`, la fonction [`splitByRegexp`](/docs/fr/reference/functions/regular-functions/splitting-merging-functions#splitByRegexp) divise une chaîne en tableau à partir d'une expression régulière.
    Exécutez la commande suivante, qui renvoie deux chaînes.

    ```sql theme={null}
    SELECT splitByRegexp('\S \d+ "([^"]*)"', '192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"')
    ```

    Notez que la deuxième chaîne retournée est le user agent correctement extrait du log :

    ```text theme={null}
    ["192.168.208.1 - - [12/Oct/2021:15:32:43 +0000] \"GET / HTTP/1.1\" 30"," \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36\""]
    ```

    Avant d'examiner la commande finale `CREATE MATERIALIZED VIEW`, voyons quelques fonctions supplémentaires utilisées pour nettoyer les données.
    Par exemple, la valeur de `RequestMethod` est `"GET`, qui contient un guillemet double indésirable.
    Vous pouvez utiliser la fonction [`trimBoth` (alias `trim`)](/docs/fr/reference/functions/regular-functions/string-functions#trimBoth) pour supprimer ce guillemet double :

    ```sql theme={null}
    SELECT trim(LEADING '"' FROM '"GET')
    ```

    La chaîne temporelle commence par `[` et n'est pas non plus dans un format que ClickHouse peut analyser en date.
    Cependant, si nous remplaçons le séparateur deux-points (**:**) par une virgule (**,**), l'analyse fonctionne parfaitement :

    ```sql theme={null}
    SELECT parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM '[12/Oct/2021:15:32:43'), ':', ' '))
    ```

    Nous sommes maintenant prêts à définir la vue matérialisée.
    La définition ci-dessous inclut `POPULATE`, ce qui signifie que les lignes existantes dans **access\_logs** seront traitées et insérées immédiatement.
    Exécutez l'instruction SQL suivante :

    ```sql theme={null}
    CREATE MATERIALIZED VIEW nginxdb.access_logs_view
    (
      RemoteAddr String,
      Client String,
      RemoteUser String,
      TimeLocal DateTime,
      RequestMethod String,
      Request String,
      HttpVersion String,
      Status Int32,
      BytesSent Int64,
      UserAgent String
    )
    ENGINE = MergeTree()
    ORDER BY RemoteAddr
    POPULATE AS
    WITH
      splitByWhitespace(message) as split,
      splitByRegexp('\S \d+ "([^"]*)"', message) as referer
    SELECT
      split[1] AS RemoteAddr,
      split[2] AS Client,
      split[3] AS RemoteUser,
      parseDateTimeBestEffort(replaceOne(trim(LEADING '[' FROM split[4]), ':', ' ')) AS TimeLocal,
      trim(LEADING '"' FROM split[6]) AS RequestMethod,
      split[7] AS Request,
      trim(TRAILING '"' FROM split[8]) AS HttpVersion,
      split[9] AS Status,
      split[10] AS BytesSent,
      trim(BOTH '"' from referer[2]) AS UserAgent
    FROM
      (SELECT message FROM nginxdb.access_logs)
    ```

    Vérifiez maintenant que cela a fonctionné.
    Vous devriez voir les journaux d'accès correctement parsés en colonnes :

    ```sql theme={null}
    SELECT * FROM nginxdb.access_logs_view
    ```

    <Image img="https://mintcdn.com/private-7c7dfe99/pIetLsS_hOGHqoPJ/images/integrations/data-ingestion/etl-tools/vector_02.webp?fit=max&auto=format&n=pIetLsS_hOGHqoPJ&q=85&s=975c0592f270bafe012c4fdbae48fb49" size="lg" border alt="Consulter les logs ClickHouse analysés sous forme de tableau" width="2824" height="1180" data-path="images/integrations/data-ingestion/etl-tools/vector_02.webp" />

    <Note>
      La leçon ci-dessus a stocké les données dans deux tables, mais vous pouvez modifier la table initiale `nginxdb.access_logs` pour utiliser le moteur de table [`Null`](/docs/fr/reference/engines/table-engines/special/null).
      Les données parsées aboutiront toujours dans la table `nginxdb.access_logs_view`, mais les données brutes ne seront pas stockées dans une table.
    </Note>
  </Step>
</Steps>

> En utilisant Vector, qui ne nécessite qu'une installation simple et une configuration rapide, vous pouvez envoyer les logs d'un serveur Nginx vers une Table dans ClickHouse. En utilisant une vue matérialisée, vous pouvez parser ces logs en colonnes pour en faciliter l'analyse.
