<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Avuru Obs Blog</title>
        <link>https://avuruobs.io/fr/blog</link>
        <description>Avuru Obs Blog</description>
        <lastBuildDate>Sun, 19 Jul 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>fr</language>
        <item>
            <title><![CDATA[Un seul ClickHouse, quatre signaux : le schéma derrière avuru obs]]></title>
            <link>https://avuruobs.io/fr/blog/one-clickhouse-four-signals</link>
            <guid>https://avuruobs.io/fr/blog/one-clickhouse-four-signals</guid>
            <pubDate>Sun, 19 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Une visite du schéma de tables qui permet à avuru obs de garder traces, logs, métriques et profilage dans un seul moteur ClickHouse — et pourquoi cela fait de la corrélation inter-signaux une simple requête SQL.]]></description>
            <content:encoded><![CDATA[<p>Le pitch d'<strong>avuru obs</strong>, c'est que chaque signal vit dans un seul moteur. C'est
facile à dire sur une page d'accueil. Ce billet en montre les dessous : les vraies
tables ClickHouse, les colonnes qu'elles partagent, et pourquoi « un seul stockage »
transforme la corrélation inter-signaux en une simple <code>JOIN</code> SQL plutôt qu'en un
travail de câblage entre quatre systèmes.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="une-base-de-données-un-moteur">Une base de données, un moteur<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#une-base-de-donn%C3%A9es-un-moteur" class="hash-link" aria-label="Lien direct vers Une base de données, un moteur" title="Lien direct vers Une base de données, un moteur" translate="no">​</a></h2>
<p>Tout arrive dans une seule base de données ClickHouse, <code>otel</code>, et presque chaque
table est un simple <code>MergeTree</code>. Pas de stockage par signal à dimensionner, scaler
et sauvegarder séparément — traces, logs, métriques et profils sont des tables
côte à côte, sur les mêmes disques, dans le même moteur de requêtes.</p>
<p>Les tables de traces et de logs ne sont pas faites main. Leur contrat de colonnes
est <strong>figé à l'identique depuis l'exportateur ClickHouse du Collector
OpenTelemetry</strong> (épinglé en <code>0.154.0</code>), si bien que l'exportateur peut faire un
<code>INSERT</code> avec une liste de colonnes explicite et que le <code>hub</code> d'avuru lit
exactement la même forme. C'est la force discrète du choix d'OTLP : le schéma de
stockage <em>est</em> le modèle de données OpenTelemetry, pas un ré-encodage
propriétaire.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-quatre-signaux-table-par-table">Les quatre signaux, table par table<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#les-quatre-signaux-table-par-table" class="hash-link" aria-label="Lien direct vers Les quatre signaux, table par table" title="Lien direct vers Les quatre signaux, table par table" translate="no">​</a></h2>
<p>Les <strong>traces</strong> vivent dans <code>otel.otel_traces</code> :</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#9CDCFE"><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLE</span><span class="token plain"> otel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">otel_traces</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token plain">          DateTime64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">9</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    TraceId            String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    SpanId             String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    ParentSpanId       String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    SpanName           LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    ServiceName        LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    ResourceAttributes Map</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    SpanAttributes     Map</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    Duration           UInt64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    StatusCode         LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token comment" style="color:rgb(106, 153, 85)">-- Events.*, Links.*, index de saut sur TraceId / attrs / Duration …</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ENGINE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> MergeTree</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">PARTITION</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> toDate</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">Tenant</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> ServiceName</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> SpanName</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> toDateTime</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></div></code></pre></div></div>
<p>Une table compagne et une vue matérialisée maintiennent un index
<code>TraceId → [début, fin]</code>, de sorte qu'« ouvrir cette trace » est une lecture
bornée dans le temps plutôt qu'un scan. <code>TraceId</code> et <code>SpanId</code> portent des index de
saut <code>bloom_filter</code> ; <code>Duration</code> reçoit un index <code>minmax</code>, si bien que « les spans
plus lents que X » élague les granules tôt.</p>
<p>Les <strong>logs</strong> vivent dans <code>otel.otel_logs</code>, et ils portent les mêmes colonnes
<code>TraceId</code>, <code>SpanId</code> et <code>ServiceName</code> que les spans. Sur ClickHouse 26.x, le corps
du log et les maps d'attributs reçoivent des index plein texte <code>text</code>, et les
attributs de ressource Kubernetes courants (<code>k8s.namespace.name</code>, <code>k8s.pod.name</code>,
…) sont matérialisés dans leurs propres colonnes pour que le filtrage par pod ou
namespace reste bon marché.</p>
<p>Les <strong>métriques</strong> sont cinq tables — <code>otel_metrics_gauge</code>, <code>_sum</code>, <code>_histogram</code>,
<code>_exponential_histogram</code>, <code>_summary</code> — une par type de métrique OTLP. Les cinq sont
créées même quand seules certaines servent, car avec un schéma fixe une table
<em>manquante</em> signifie des insertions silencieusement perdues le jour où une nouvelle
appli émet des histogrammes. Chaque ligne conserve un tableau <code>Exemplars.TraceId</code> /
<code>Exemplars.SpanId</code> — le fil qui recoud un point de mesure à la trace exacte qui l'a
produit.</p>
<p>Le <strong>profilage</strong> — le signal le plus récent, en opt-in — est le seul schéma
entièrement possédé par avuru, car OTLP Profiles est encore en alpha et
l'exportateur ne le gère pas. Il utilise une répartition en deux tables pour que
les stacks répétés ne coûtent presque rien :</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Stacks uniques stockés une seule fois, indexés par un hash 64 bits.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLE</span><span class="token plain"> otel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">profiling_stacks</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    Tenant    LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    StackHash UInt64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    Frames    Array</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    LastSeen  </span><span class="token keyword" style="color:rgb(86, 156, 214)">DateTime</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">now</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ENGINE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> ReplacingMergeTree</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">LastSeen</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">Tenant</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> StackHash</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token comment" style="color:rgb(106, 153, 85)">-- Les échantillons référencent un stack par hash au lieu de répéter les frames.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">TABLE</span><span class="token plain"> otel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">profiling_samples</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token plain">   DateTime64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">9</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    Tenant      LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    ServiceName LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    SampleType  LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    StackHash   UInt64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    </span><span class="token keyword" style="color:rgb(86, 156, 214)">Value</span><span class="token plain">       UInt64</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    NodeName    LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    PodName     String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">    ContainerName LowCardinality</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">String</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ENGINE</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> MergeTree</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">Tenant</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> ServiceName</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-erreurs--un-cinquième-signal-dérivé-pas-ingéré">Les erreurs : un cinquième signal dérivé, pas ingéré<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#les-erreurs--un-cinqui%C3%A8me-signal-d%C3%A9riv%C3%A9-pas-ing%C3%A9r%C3%A9" class="hash-link" aria-label="Lien direct vers Les erreurs : un cinquième signal dérivé, pas ingéré" title="Lien direct vers Les erreurs : un cinquième signal dérivé, pas ingéré" translate="no">​</a></h2>
<p>Le suivi des erreurs n'est pas un pipeline séparé — c'est une <strong>vue matérialisée</strong>
au-dessus de la table des logs. Tout enregistrement <code>ERROR</code>/<code>FATAL</code> (OTLP
<code>SeverityNumber &gt;= 17</code>) est projeté dans une table <code>error_events</code> au moment de
l'insertion, avec une <strong>empreinte</strong> de stack trace calculée en SQL : on normalise
les adresses hexadécimales et les numéros de ligne, on hache les premières frames,
et on regroupe les plantages identiques en un seul incident. Les exceptions
ingérées depuis un SDK compatible Sentry arrivent dans la même table de logs
(étiquetées au niveau du gateway) et passent par la même vue — de sorte que les
erreurs navigateur et les panics backend se dédupliquent ensemble, gratuitement,
sans stockage supplémentaire.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ce-qui-en-fait-un-seul-stockage">Ce qui en fait <em>un seul</em> stockage<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#ce-qui-en-fait-un-seul-stockage" class="hash-link" aria-label="Lien direct vers ce-qui-en-fait-un-seul-stockage" title="Lien direct vers ce-qui-en-fait-un-seul-stockage" translate="no">​</a></h2>
<p>Regardez les clés de tri et vous verrez les mêmes colonnes revenir :
<code>ServiceName</code>, <code>Timestamp</code>, et surtout <code>TraceId</code>. Parce que chaque signal est
indexé sur la ressource et l'identité de trace OpenTelemetry, la corrélation est
une requête, pas une intégration :</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- D'un span lent directement aux logs qui l'expliquent.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">SeverityText</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">Body</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> otel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">otel_logs </span><span class="token keyword" style="color:rgb(86, 156, 214)">AS</span><span class="token plain"> l</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">TraceId </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> {trace_id:String}</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> l</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></div></code></pre></div></div>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#9CDCFE;--prism-background-color:#1E1E1E"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#9CDCFE;background-color:#1E1E1E"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#9CDCFE"><span class="token comment" style="color:rgb(106, 153, 85)">-- Latence p99 par endpoint pour un service, sur la dernière heure.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">SELECT</span><span class="token plain"> SpanName</span><span class="token punctuation" style="color:rgb(212, 212, 212)">,</span><span class="token plain"> quantile</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token number" style="color:rgb(181, 206, 168)">0.99</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token plain">Duration</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">/</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain">e6 </span><span class="token keyword" style="color:rgb(86, 156, 214)">AS</span><span class="token plain"> p99_ms</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">FROM</span><span class="token plain"> otel</span><span class="token punctuation" style="color:rgb(212, 212, 212)">.</span><span class="token plain">otel_traces</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">WHERE</span><span class="token plain"> ServiceName </span><span class="token operator" style="color:rgb(212, 212, 212)">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(206, 145, 120)">'checkout'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain">  </span><span class="token operator" style="color:rgb(212, 212, 212)">AND</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">Timestamp</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(220, 220, 170)">now</span><span class="token punctuation" style="color:rgb(212, 212, 212)">(</span><span class="token punctuation" style="color:rgb(212, 212, 212)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(212, 212, 212)">-</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">INTERVAL</span><span class="token plain"> </span><span class="token number" style="color:rgb(181, 206, 168)">1</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">HOUR</span><span class="token plain"></span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> SpanName</span><br></div><div class="token-line" style="color:#9CDCFE"><span class="token plain"></span><span class="token keyword" style="color:rgb(86, 156, 214)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(86, 156, 214)">BY</span><span class="token plain"> p99_ms </span><span class="token keyword" style="color:rgb(86, 156, 214)">DESC</span><span class="token punctuation" style="color:rgb(212, 212, 212)">;</span><br></div></code></pre></div></div>
<p>L'exemplar d'un histogramme de latence porte le <code>TraceId</code> d'une requête
représentative : un pic sur un tableau de bord renvoie donc directement à la trace
qui le sous-tend — même stockage, une seule jointure. Aucun pont
<code>trace_id</code>-vers-<code>trace_id</code> à configurer entre des systèmes séparés.</p>
<p>Et tout tient dans <strong>un seul langage de requête</strong>. Pas de PromQL pour les
métriques, un langage de logs pour les logs et un troisième dialecte pour les
traces — c'est du SQL pour les quatre, sur des tables que vous pouvez inspecter avec
<code>SHOW CREATE TABLE</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quelques-choix-délibérés">Quelques choix délibérés<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#quelques-choix-d%C3%A9lib%C3%A9r%C3%A9s" class="hash-link" aria-label="Lien direct vers Quelques choix délibérés" title="Lien direct vers Quelques choix délibérés" translate="no">​</a></h2>
<ul>
<li class=""><strong>Partitionner par jour, purger par partie.</strong> Chaque table est
<code>PARTITION BY toDate(...)</code> avec <code>ttl_only_drop_parts = 1</code>, de sorte que la
rétention s'applique en supprimant des parties journalières entières (rapide)
plutôt que par des mutations TTL au niveau des lignes (lent). Les fenêtres de
rétention sont fixées au moment de la migration depuis l'environnement, pas gelées
dans le DDL.</li>
<li class=""><strong>Le bon index pour la forme.</strong> Filtres de Bloom pour les recherches
d'identifiants/attributs à forte cardinalité sur les traces et métriques ; index
<code>text</code> de ClickHouse pour la recherche plein texte dans les logs.</li>
<li class=""><strong>Une couture multi-tenant gratuite en mono-tenant.</strong> Chaque table place en tête
de sa clé de tri une colonne <code>Tenant</code> qui vaut <code>'default'</code> par défaut. Avec un
seul tenant, c'est une valeur constante unique — zéro coût de stockage et de tri —
mais la colonne dont un déploiement managé multi-tenant a besoin est déjà là.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="regardez-les-tables-vous-même">Regardez les tables vous-même<a href="https://avuruobs.io/fr/blog/one-clickhouse-four-signals#regardez-les-tables-vous-m%C3%AAme" class="hash-link" aria-label="Lien direct vers Regardez les tables vous-même" title="Lien direct vers Regardez les tables vous-même" translate="no">​</a></h2>
<p>Rien de tout cela n'est caché : les migrations qui créent ces tables sont livrées
dans le dépôt du moteur, et une instance en fonctionnement est à un
<code>SHOW CREATE TABLE</code> de distance. Pour voir l'ensemble s'allumer via OTLP,
<a class="" href="https://avuruobs.io/fr/docs/getting-started/30-seconds">installez en 30 secondes</a>, parcourez
l'<a class="" href="https://avuruobs.io/fr/guides/architecture">architecture</a>, ou lisez comment avuru obs
<a class="" href="https://avuruobs.io/fr/docs/compare">se compare aux outils que vous utilisez déjà</a>.</p>]]></content:encoded>
            <category>Engineering</category>
        </item>
        <item>
            <title><![CDATA[Your errors, finally next to your traces]]></title>
            <link>https://avuruobs.io/fr/blog/error-tracking</link>
            <guid>https://avuruobs.io/fr/blog/error-tracking</guid>
            <pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[avuru obs now does error tracking — issues derived from the OTLP telemetry you already send, plus Sentry-SDK-compatible ingest, all correlated with traces and logs in one ClickHouse store.]]></description>
            <content:encoded><![CDATA[<p>Error tracking is the newest signal in <strong>avuru obs</strong>. It captures exceptions two
ways — <strong>derived automatically</strong> from the OTLP telemetry you already send, and
<strong>ingested directly from Sentry SDKs</strong> — then stores those errors right next to
the traces and logs that explain them, in one ClickHouse engine.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="two-ways-to-capture-errors-no-rewrite">Two ways to capture errors, no rewrite<a href="https://avuruobs.io/fr/blog/error-tracking#two-ways-to-capture-errors-no-rewrite" class="hash-link" aria-label="Lien direct vers Two ways to capture errors, no rewrite" title="Lien direct vers Two ways to capture errors, no rewrite" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="derived-from-telemetry-you-already-send">Derived from telemetry you already send<a href="https://avuruobs.io/fr/blog/error-tracking#derived-from-telemetry-you-already-send" class="hash-link" aria-label="Lien direct vers Derived from telemetry you already send" title="Lien direct vers Derived from telemetry you already send" translate="no">​</a></h3>
<p>avuru obs reads the exceptions already flowing in over eBPF and OTLP — span
<code>exception</code> events, error spans and ERROR/FATAL logs — and groups them into
deduplicated <strong>issues</strong> at insert time in ClickHouse. For a backend service that
already exports to avuru obs, error tracking needs <strong>zero instrumentation</strong>: no
SDK, no code change, no extra agent.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="sentry-sdk-compatible-ingest">Sentry-SDK-compatible ingest<a href="https://avuruobs.io/fr/blog/error-tracking#sentry-sdk-compatible-ingest" class="hash-link" aria-label="Lien direct vers Sentry-SDK-compatible ingest" title="Lien direct vers Sentry-SDK-compatible ingest" translate="no">​</a></h3>
<p>For the errors eBPF can't see — browser exceptions above all — the gateway runs
a Sentry-protocol receiver. Point an existing Sentry SDK's <strong>DSN</strong> at the avuru
obs gateway and its events flow into the same store. You keep the SDKs you
already run and change a single config value.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="one-store-correlated-by-default">One store, correlated by default<a href="https://avuruobs.io/fr/blog/error-tracking#one-store-correlated-by-default" class="hash-link" aria-label="Lien direct vers One store, correlated by default" title="Lien direct vers One store, correlated by default" translate="no">​</a></h2>
<p>Because every error shares a <code>trace_id</code> with the rest of your telemetry, an
issue links straight back to the trace that produced it, the logs around it, and
the metrics and profiles for that service — no jump to a separate tool. It's one
ClickHouse to size, back up and query, instead of a separate error database
bolted on beside your traces and logs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="triage-and-regression-detection">Triage and regression detection<a href="https://avuruobs.io/fr/blog/error-tracking#triage-and-regression-detection" class="hash-link" aria-label="Lien direct vers Triage and regression detection" title="Lien direct vers Triage and regression detection" translate="no">​</a></h2>
<p>Each issue carries what you need to triage it: a grouped stack trace, first- and
last-seen timestamps, an occurrence count and a triage state. A resolved issue
that reappears is flagged as a <strong>regression</strong>, so a fix that quietly breaks again
doesn't slip back in unnoticed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-it-is-today">Where it is today<a href="https://avuruobs.io/fr/blog/error-tracking#where-it-is-today" class="hash-link" aria-label="Lien direct vers Where it is today" title="Lien direct vers Where it is today" translate="no">​</a></h2>
<p>Error tracking is the youngest module in avuru obs. Derivation from your existing
telemetry runs by default; the Sentry ingest port is opt-in. Some things you'd
expect from a mature error tracker — deminified JavaScript frames from source
maps, release tracking and alerting on new or spiking issues — aren't here yet.
Check <a class="" href="https://avuruobs.io/fr/docs/status">Feature status</a> for exactly what's live before you rely on
it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="learn-more">Learn more<a href="https://avuruobs.io/fr/blog/error-tracking#learn-more" class="hash-link" aria-label="Lien direct vers Learn more" title="Lien direct vers Learn more" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://avuruobs.io/fr/docs/signals/errors">Errors signal</a> — how derivation and Sentry ingest work.</li>
<li class=""><a class="" href="https://avuruobs.io/fr/docs/compare/sentry">avuru obs vs. Sentry</a> — derived issues, DSN ingest and
no per-event meter.</li>
<li class=""><a class="" href="https://avuruobs.io/fr/docs/compare/glitchtip">avuru obs vs. GlitchTip</a> — the same Sentry protocol,
unified with your other signals.</li>
</ul>]]></content:encoded>
            <category>Announcement</category>
        </item>
        <item>
            <title><![CDATA[Hello, avuru obs docs]]></title>
            <link>https://avuruobs.io/fr/blog/hello-avuru-obs</link>
            <guid>https://avuruobs.io/fr/blog/hello-avuru-obs</guid>
            <pubDate>Mon, 22 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the avuru obs docs — all-in-one, eBPF-native observability with zero code changes. Start with the 30-second guide.]]></description>
            <content:encoded><![CDATA[<p>Welcome to the <strong>avuru obs</strong> documentation site.</p>
<p>avuru obs is all-in-one observability — traces, metrics, logs and continuous
profiling — in a single install, on one storage engine, with <strong>zero code
changes</strong>. eBPF discovers your services; OpenTelemetry carries the detail.</p>
<!-- -->
<p>This site is where the onboarding funnel, guides, reference and integrations
live. The fastest way in is the
<a class="" href="https://avuruobs.io/fr/docs/getting-started/30-seconds">30-second guide</a>: one <code>helm install</code> and the
service map lights up.</p>
<p>The docs are open and bilingual (English + French). Found a typo or a gap? Hit
<strong>"Edit this page"</strong> on any doc — it's a three-click pull request from there.</p>]]></content:encoded>
            <category>Announcement</category>
        </item>
    </channel>
</rss>