Documentation développeur
Tout ce que fait SnagSpy, et comment y accéder
SnagSpy reçoit l’OpenTelemetry de votre application, regroupe les erreurs en incidents, les corrèle avec les déploiements, les requêtes en base, la topologie des services et les journaux, puis vous dit pourquoi quelque chose a cassé. Cette page est la référence complète : chaque point d’entrée, chaque réglage, chaque limite — et la liste honnête de ce qu’elle ne fait pas.
Cette page est une traduction. La version anglaise fait foi : en cas de divergence sur un détail technique, c’est elle qui décrit le comportement réel. La traduction n’a pas encore été relue par un locuteur natif.
Tout ce qui suit a été vérifié dans le code en cours d’exécution plutôt qu’écrit de mémoire. Si une fonctionnalité manque ici, considérez qu’elle manque à la plateforme et dites-le — la section finale énumère délibérément les manques.
Vue d’ensemble
La plateforme est un monolithe modulaire en Go avec un tableau de bord Nuxt. Deux processus vous concernent : ingest, qui accepte la télémétrie, et l’API, qui sert tout ce que vous lisez. Ils sont séparés pour qu’un afflux de télémétrie n’emporte pas le tableau de bord avec lui.
De l’OTLP standard en entrée
Traces, journaux et métriques arrivent en OpenTelemetry. Rien n’est propriétaire : une application qui fait déjà tourner un SDK OTel peut le pointer ici et se passer entièrement de nos SDK — et le pointer ailleurs plus tard.
Corrélé, pas seulement regroupé
Un incident porte le déploiement qui l’a précédé, les requêtes lentes autour de lui, les services en amont et les journaux à côté.
Expliqué, avec le raisonnement
Les investigations IA sélectionnent et formulent ; la plateforme calcule. Chaque chiffre d’une réponse est vérifiable, et une réponse qui ne peut être étayée n’est pas donnée.
Démarrage rapide
- Créez un compte et un projet. POST /v1/auth/register, puis connectez-vous — l’inscription ne renvoie volontairement pas de session. Créez un projet depuis le tableau de bord ou avec POST /v1/projects.
- Émettez un DSN. POST /v1/projects/{projectID}/dsns. Un DSN s’écrit scheme://publicKey@host/projectID et peut être livré sans risque dans un bundle navigateur — il peut écrire de la télémétrie et ne rien lire.
- Envoyez quelque chose. L’un des SDK ci-dessous, ou de l’OTLP brut vers le point d’ingestion.
- Regardez-le arriver. L’incident apparaît sous /v1/issues et dans le tableau de bord.
Go
import "github.com/rellinxe/snagspy/sdk/go/snagspy"
client, err := snagspy.New(snagspy.Options{
DSN: os.Getenv("SNAGSPY_DSN"),
Environment: "production",
Release: buildSHA,
})
if err != nil {
log.Fatal(err)
}
defer client.Close(context.Background())
if err := doWork(); err != nil {
client.CaptureException(context.Background(), err)
}
JavaScript et le navigateur
import { init, captureException } from "@snagspy/browser"
init({
dsn: globalThis._importMeta_.env.VITE_SNAGSPY_DSN,
environment: "production",
release: __BUILD_SHA__,
})
try {
risky()
} catch (error) {
captureException(error)
}
Les deux SDK masquent les valeurs qui ressemblent à des secrets avant que quoi que ce soit ne quitte le processus. Ce n’est pas une politesse côté serveur : un mot de passe qui nous est envoyé puis masqué à l’arrivée a déjà traversé le réseau.
Concepts
- Organisation
- La frontière de facturation et d’appartenance. Chaque donnée appartient à exactement une organisation, et l’isolation entre locataires est une condition de publication plutôt qu’une convention.
- Projet
- Une application. Possède ses DSN, son consentement à la relecture et sa limite d’ingestion.
- DSN
- Un identifiant d’écriture par projet, scheme://publicKey@host/projectID. Public par conception : il peut écrire de la télémétrie et ne rien lire.
- Clé d’API
- Un identifiant de lecture pour l’API du tableau de bord, limité à l’organisation. Affiché une seule fois à la création.
- Événement / occurrence
- Une erreur telle qu’elle s’est produite, avec sa pile, son contexte et les signaux corrélés.
- Incident
- Des occurrences regroupées par empreinte. Une pile minifiée est regroupée sur le message plus le nom de chunk de chaque frame, hash de contenu retiré, pour qu’un redéploiement ne scinde pas un incident en deux.
- Trace et span
- OTel standard. La liste des traces filtre sur les spans et agrège des traces entières, et indique lesquels de ses chiffres sont des estimations.
- Unité de relecture
- L’unité de facturation de la relecture de session : une unité par tranche de 64 Kio envoyée.
- Investigation
- Une analyse de cause racine par IA. Facturée par appel au modèle, avant d’en connaître le résultat — un appel en échec a quand même coûté un appel.
SDK
Les deux sont de fines couches d’ergonomie au-dessus d’OpenTelemetry plutôt que des bibliothèques d’instrumentation à part entière. Ce qu’elles ajoutent est la partie facile à rater : la gestion du DSN, l’enregistrement des exceptions dans la forme sur laquelle la plateforme regroupe, et le masquage avant envoi.
| SDK | Paquet | Apporte |
|---|
| Go | sdk/go/snagspy | Analyse du DSN, CaptureException, masquage, middleware HTTP. |
| Navigateur et Node | sdk/js | Analyse du DSN, capture des erreurs et des rejets non gérés, normalisation des piles vers la forme de V8, relecture de session, retours utilisateurs, masquage, un plugin Vite pour les source maps. |
Le SDK navigateur normalise la pile de chaque moteur vers la forme de V8 avant l’envoi, et transporte les identifiants de débogage dans un attribut de span. Un identifiant de débogage fait 32 caractères hexadécimaux sans séparateurs — le SDK retire pour vous les tirets d’un UUID canonique.
Envoyer de la télémétrie
Le service d’ingestion est distinct de l’API et écoute sur son propre port (:8081 par défaut ; publiez-le via INGEST_PUBLIC_URL). Chaque route ici s’authentifie avec un DSN, pas avec une session.
| Méthode | Chemin | Corps |
|---|
| POST | /v1/traces | Charge utile OTLP de traces. Les spans portant une exception deviennent des incidents. |
| POST | /v1/logs | Charge utile OTLP de journaux. |
| POST | /v1/metrics | Charge utile OTLP de métriques. |
| POST | /v1/replay | Un fragment de relecture. Voir ci-dessous. |
| GET | /healthz | Vivacité. |
Deux compteurs s’appliquent à chaque envoi : une limite de requêtes par projet et une limite d’événements par organisation. Les deux sont décrites sous Limites de débit.
Relecture de session
La relecture est enregistrée avec rrweb, et le masquage est inversé par rapport aux réglages par défaut de rrweb : le texte est masqué sauf autorisation explicite, plutôt qu’exposé sauf masquage explicite. Le masquage a lieu dans le navigateur avant la capture, car rien côté serveur ne peut défaire un enregistrement non masqué déjà arrivé.
Envoyer un fragment
POST /v1/replay
Content-Type: application/octet-stream
X-Replay-Session: <session id>
X-Replay-Seq: <0, 1, 2, …>
X-Replay-Encoding: json-zstd
X-Replay-Recorded-At: <RFC 3339, optional>
Le corps est constitué d’octets compressés opaques que cette plateforme s’engage à ne pas lire. Une horloge client absente ou illisible n’est pas une erreur — le serveur substitue la sienne, car un enregistrement horodaté à tort vaut toujours la peine d’être conservé.
Trois choses qui vous seront refusées
- Le projet n’a pas donné son consentement. La capture de relecture est par projet et reste désactivée jusqu’à activation via PUT /v1/projects/{projectID}/session-replay.
- Votre offre ne vend pas la relecture. L’offre gratuite ne la comprend pas, et l’envoi est refusé avec plan_excludes_replay en nommant votre offre. Ce n’est pas un dépassement — rien ici ne compte d’unités face à un volume inclus.
- Le fragment est trop volumineux. Le plafond s’applique aux octets réellement lus, pas à ce que Content-Length annonçait.
Regarder un enregistrement exige la portée propriétaire, revérifie le consentement du projet au moment de la lecture, et est inscrit au journal d’audit avant que les octets ne soient lus.
Source maps
Envoyez les artefacts à POST /v1/projects/{projectID}/artifacts. La ligne vit dans PostgreSQL et les octets dans un magasin d’objets, adressés par contenu — envoyer deux fois la même source map ne coûte donc qu’une copie.
Les frames sont résolues à la lecture, pas à l’ingestion. Une frame qui ne peut pas être résolue dit pourquoi au lieu de faire échouer la page : un envoi manquant se dégrade en frame minifiée accompagnée d’une explication, plutôt qu’en erreur.
API du tableau de bord
Servie par le processus API sur :8080 par défaut. Tout se trouve sous /v1. Les réponses sont en JSON ; les erreurs portent un code stable, un message lisible et un request_id.
Compte et projets
| POST | /v1/auth/register | Créer un compte. Ne renvoie pas de session — connectez-vous ensuite. |
| POST | /v1/auth/login | Échanger des identifiants contre un cookie de session. |
| POST | /v1/auth/logout | Terminer la session en cours. |
| GET | /v1/me | L’utilisateur connecté et son organisation. |
| GET | /v1/members | Les membres de l’organisation. |
| GET | /v1/projects | Lister les projets. |
| POST | /v1/projects | Créer un projet. |
| GET | /v1/projects/{projectID} | Un projet. |
| GET | /v1/projects/{projectID}/dsns | Les clés d’ingestion du projet. |
| POST | /v1/projects/{projectID}/dsns | Émettre un nouveau DSN. |
| DELETE | /v1/projects/{projectID}/dsns/{keyID} | Révoquer un DSN. |
| PUT | /v1/projects/{projectID}/session-replay | Activer ou désactiver la capture de relecture pour le projet. |
| GET | /v1/api-keys | Lister les clés d’API. |
| POST | /v1/api-keys | Créer une clé d’API. Le secret n’est affiché qu’une fois. |
| DELETE | /v1/api-keys/{keyID} | Révoquer une clé d’API. |
| GET | /v1/settings | Les réglages de l’organisation, dont la rétention. |
| PATCH | /v1/settings | Modifier les réglages de l’organisation. |
| GET | /v1/audit-log | Le journal d’audit. Non configurable par le client. |
Authentification unique
Disponible uniquement lorsque API_PUBLIC_URL est défini. Sans cela, chaque route ici répond sso_unavailable, et le seul autre signe est l’absence de la ligne « single sign-on enabled » au démarrage.
| POST | /v1/auth/sso/start | Démarrer une connexion SSO. |
| GET | /v1/auth/sso/callback | Retour du fournisseur d’identité. |
| GET | /v1/settings/sso | La connexion actuelle. |
| PUT | /v1/settings/sso | Configurer la connexion. |
| DELETE | /v1/settings/sso | Supprimer la connexion. |
| GET | /v1/settings/sso/domains | Les domaines de messagerie revendiqués. |
| POST | /v1/settings/sso/domains | Revendiquer un domaine. |
| POST | /v1/settings/sso/domains/verify | Prouver un domaine revendiqué. |
Incidents et événements
| GET | /v1/issues | Lister les incidents, filtrés et paginés. |
| GET | /v1/issues/{issueID} | Un incident. |
| GET | /v1/issues/{issueID}/events | Les occurrences d’un incident. |
| PATCH | /v1/issues/{issueID} | Changer le statut (résolu, ignoré, rouvert). |
| GET | /v1/users | Les utilisateurs finaux vus dans la télémétrie. |
| GET | /v1/feedback | Les retours utilisateurs soumis. |
| POST | /v1/feedback | Soumettre un retour utilisateur. |
Traces, services et performance
| GET | /v1/traces | Liste des traces. Filtre sur les spans, agrège des traces entières. |
| GET | /v1/traces/{traceID} | Une trace et ses spans. |
| GET | /v1/services | Liste des services avec leur santé. |
| GET | /v1/services/map | La topologie de services observée. |
| GET | /v1/services/structure | Les faits structurels de la topologie. |
| GET | /v1/services/dependencies | Les arêtes entre services. |
| GET | /v1/services/approaching | Métriques qui montent vers le seuil, avec la pente. |
| GET | /v1/traffic | Le trafic par projet plutôt que par service le plus lent. |
| GET | /v1/queues | Comportement des files et des workers. |
| GET | /v1/anomalies | Anomalies détectées. |
| GET | /v1/endpoints/surges | Signal d’abus par point d’entrée, sans identité de l’appelant. |
| GET | /v1/database/slow-queries | Requêtes lentes en base. |
| GET | /v1/database/query-patterns | Motifs de requêtes. |
Journaux et métriques (lecture)
| GET | /v1/logs | Rechercher dans les lignes de journal. |
| GET | /v1/logs/patterns | Formes de journaux récurrentes. |
| GET | /v1/logs/surges | Pics de volume de journaux. |
| GET | /v1/metrics/names | Noms de métriques observés. |
| GET | /v1/metrics/series | Points d’une série nommée. |
Relecture de session
| GET | /v1/projects/{projectID}/replay | Sessions enregistrées. |
| GET | /v1/projects/{projectID}/replay/{sessionID} | Les fragments d’un enregistrement. Portée propriétaire, revérifie le consentement, et inscrit le journal d’audit avant que les octets ne soient lus. |
Déploiements et versions
| POST | /v1/deployments | Enregistrer un déploiement. |
| GET | /v1/deployments | Lister les déploiements. |
| GET | /v1/deployments/{deploymentID} | Un déploiement. |
| GET | /v1/deployments/{deploymentID}/health | Ce déploiement a-t-il aggravé les choses, avec le calcul. |
| GET | /v1/releases | Les versions, dérivées des déploiements plutôt que stockées. |
| GET | /v1/projects/{projectID}/integrations | Les intégrations de gestion de code configurées. |
| PUT | /v1/projects/{projectID}/integrations/{provider} | Configurer github ou gitlab. |
| DELETE | /v1/projects/{projectID}/integrations/{provider} | En supprimer une. |
Source maps
| POST | /v1/projects/{projectID}/artifacts | Envoyer une source map ou un artefact de débogage. |
| GET | /v1/projects/{projectID}/artifacts | Lister les artefacts. |
| DELETE | /v1/projects/{projectID}/artifacts/{artifactID} | En supprimer un. |
Alertes, destinations et rapports
| GET | /v1/alerts | Historique des alertes. |
| GET | /v1/alert-destinations | Où les alertes sont envoyées. |
| POST | /v1/alert-destinations | Ajouter une destination. |
| DELETE | /v1/alert-destinations/{destinationID} | En supprimer une. |
| GET | /v1/reports/schedule | La planification des synthèses. |
| PUT | /v1/reports/schedule | La définir. |
| DELETE | /v1/reports/schedule | L’arrêter. |
| GET | /v1/reports/preview | Générer la prochaine synthèse sans l’envoyer. |
Tâches planifiées et disponibilité
| GET | /v1/cron/checks | Lister les contrôles de tâches planifiées. |
| POST | /v1/cron/checks | En créer un. |
| PATCH | /v1/cron/checks/{checkID} | Modifier la planification ou le délai de grâce. |
| DELETE | /v1/cron/checks/{checkID} | En supprimer un. |
| GET | /v1/cron/checks/{checkID}/pings | Historique des pointages. |
| POST | /v1/cron/checks/{checkID}/rotate | Renouveler le jeton de pointage. |
| GET | /v1/checkins/{token} | Pointer. Non authentifié — le jeton est l’identifiant. |
| POST | /v1/checkins/{token} | Pointer, avec un corps de requête. |
| GET | /v1/uptime/monitors | Lister les moniteurs de disponibilité. |
| POST | /v1/uptime/monitors | En créer un. |
| PATCH | /v1/uptime/monitors/{monitorID} | En modifier un. |
| DELETE | /v1/uptime/monitors/{monitorID} | En supprimer un. |
| GET | /v1/uptime/monitors/{monitorID}/checks | Résultats des sondes. |
Tableaux de bord
| GET | /v1/dashboards | Lister les tableaux de bord. |
| POST | /v1/dashboards | En créer un. |
| GET | /v1/dashboards/{dashboardID} | Un tableau de bord. |
| PATCH | /v1/dashboards/{dashboardID} | Renommer ou redécrire. |
| PUT | /v1/dashboards/{dashboardID}/widgets | Remplacer l’ensemble des widgets. |
| DELETE | /v1/dashboards/{dashboardID} | En supprimer un. |
Investigations IA
Chaque route ici nécessite ANTHROPIC_API_KEY. Sans elle la fonctionnalité est désactivée plutôt qu’en échec à chaque requête.
| POST | /v1/issues/{issueID}/investigate | Enquêter sur un incident. |
| GET | /v1/issues/{issueID}/investigation | Le résultat. |
| POST | /v1/alerts/{alertID}/investigate | Enquêter sur une alerte. |
| GET | /v1/alerts/{alertID}/investigation | Le résultat. |
| POST | /v1/projects/{projectID}/investigate | Enquêter sur un projet. |
| POST | /v1/projects/{projectID}/explain | Poser une question sur la topologie. |
| GET | /v1/investigations | Lister les investigations. |
| GET | /v1/investigations/{investigationID} | Une investigation. |
Facturation
GET /v1/usage est toujours disponible. POST /v1/checkout n’existe que si GENIUSPAY_API_KEY est défini — sinon la route n’est pas montée du tout et répond 404 plutôt que 401, parce que « il n’y a rien ici » est la réponse honnête.
| GET | /v1/usage | L’usage mesuré face à l’offre, avec une mise en garde dans chaque réponse. |
| POST | /v1/checkout | Démarrer un achat. Portée administrateur. Renvoie une URL de paiement hébergée. |
Exploitation
| GET | /healthz | Vivacité. Sur l’API comme sur le service d’ingestion. |
| GET | /readyz | Disponibilité, dépendances comprises. |
Authentification
| Identifiant | Sert à | Comment |
|---|
| DSN | Écrire de la télémétrie | Dans la configuration du SDK. Public par conception — il écrit et ne lit pas. |
| Cookie de session | Le tableau de bord | POST /v1/auth/login. Le cookie est slk_session et dure 720h par défaut. |
| Clé d’API | Scripter l’API du tableau de bord | En-tête Authorization. Créée via POST /v1/api-keys, affichée une seule fois. |
| Jeton de pointage | Pointages cron | Dans l’URL. Le jeton est l’identifiant : renouvelez-le avec POST /v1/cron/checks/{checkID}/rotate. |
| SSO | Le tableau de bord, pour un domaine revendiqué | Nécessite API_PUBLIC_URL. Ne fait confiance au fournisseur que pour le domaine que sa connexion revendique, et seulement pour des comptes déjà invités. |
Les requêtes authentifiées par cookie sont contrôlées sur l’en-tête Origin. Une requête sans Origin correspondant à DASHBOARD_ORIGIN est refusée avec origin_rejected (403). Scripter avec curl contre une pile locale demande donc -H "Origin: http://localhost:3000".
Limites de débit
Les limites de débit servent à contrer les abus, et ce sont les seules ici qui refusent réellement une requête. Elles n’ont rien à voir avec ce que comprend votre offre : dépasser un volume inclus ne vous ralentit jamais et ne rejette jamais de télémétrie. Redis fait autorité pour que toutes les instances partagent le même compteur, avec un repli par processus qui maintient la limitation si Redis est indisponible.
| Limite | Défaut | Portée |
|---|
INGEST_REQUESTS_PER_MINUTE | 600 | Par projet |
INGEST_EVENTS_PER_MINUTE | 30 000 | Par organisation |
AUTH_ATTEMPTS_PER_MINUTE | 10 | Par appelant |
INVESTIGATIONS_PER_HOUR | 100 | Par organisation |
Une requête refusée répond 429 avec Retry-After.
Offres, usage et rétention
L’usage est mesuré et rapporté. Il n’entraîne jamais d’action sur le chemin d’écriture. Dépasser un volume inclus ne vous ralentit pas, ne rejette pas votre télémétrie et ne déclenche aucun prélèvement — il n’y a aucune facturation à l’usage ici. Vous êtes prévenu une fois par signal et par période, et le message dit clairement que rien n’a été ralenti. La seule chose que décide une offre, c’est si un signal est vendu : une offre qui ne comprend pas la relecture de session refuse les envois de relecture, ce qui est un acte différent de la destruction de télémétrie déjà payée.
Ce tableau est généré à partir de la même constante que celle sur laquelle la plateforme facture : il ne peut donc pas annoncer un chiffre que le produit n’utilise pas.
Rétention
Une offre restreint le plafond de la plateforme et ne l’élargit jamais. Les plafonds sont de 90 jours pour les erreurs et événements et de 30 jours pour les spans de trace ; les lignes de journal suivent le réglage des traces. Une organisation peut restreindre sa propre rétention via PATCH /v1/settings. Le journal d’audit n’est pas configurable par le client.
Une offre expirée conserve ses données quatorze jours de plus. Les limites, les sièges et les fonctionnalités reviennent à l’offre gratuite dès la fin de la période payée, parce qu’un paiement les rétablit ; la fenêtre de rétention, non, parce qu’un historique d’erreurs supprimé ne revient pas.
Alertes et intégrations
Les destinations se configurent par organisation à /v1/alert-destinations. Le type d’une destination choisit le notificateur, et un type sans notificateur derrière lui échoue bruyamment plutôt que d’être ignoré.
| Type | Nécessite | Notes |
|---|
| Slack | Une URL de webhook entrant | Porte un champ text à côté de l’alerte structurée. |
| Discord | Une URL de webhook | Porte un champ content. |
| Webhook générique | Une URL | Les requêtes sortantes passent par un composeur qui refuse les adresses privées et lien-local. |
| Courriel | SMTP_* configuré | Une destination n’est pas confirmée tant que l’adresse ne s’est pas prouvée. |
Déploiements
Enregistrez les déploiements avec POST /v1/deployments, ou connectez GitHub ou GitLab à /v1/projects/{projectID}/integrations. Chaque fournisseur a son propre adaptateur de webhook, et un déploiement enregistre quel fournisseur l’a attesté, et pas seulement qu’un webhook l’a fait.
Synthèses
Un résumé planifié à /v1/reports/schedule. Prévisualisez le prochain sans l’envoyer à /v1/reports/preview.
Surveillance des tâches planifiées et disponibilité
Créez un contrôle, puis faites appeler par votre tâche son URL de pointage. Le jeton dans l’URL est l’identifiant, donc le point d’entrée n’est volontairement pas authentifié — une tâche cron sur une machine sans secrets peut quand même signaler son passage.
# at the end of your job
curl -fsS https://ingest.example.com/v1/checkins/<token>
Un pointage qui n’arrive pas dans son délai de grâce déclenche une alerte. Les moniteurs de disponibilité vont dans l’autre sens : la plateforme sonde une URL que vous indiquez et enregistre le résultat à /v1/uptime/monitors/{monitorID}/checks.
Investigations IA
Une investigation lit un incident, une alerte ou un projet et explique ce qui s’est passé. La répartition des rôles est délibérée et mérite d’être connue avant de faire confiance à une réponse : le modèle sélectionne et formule ; la plateforme calcule. Chaque chiffre d’une réponse provient d’une requête, pas du modèle, et une réponse qui ne peut être étayée par une requête n’est pas donnée.
- Entièrement désactivées sauf si ANTHROPIC_API_KEY est défini — désactivées, et non en échec à chaque requête.
- Facturées par appel au modèle, avant d’en connaître le résultat. Un appel en échec a quand même coûté un appel : ne facturer qu’en cas de succès masquerait une boucle emballée à l’endroit précis où vous la chercheriez.
- Refusables par organisation. Les données envoyées sont un sous-ensemble volontairement minimal d’un seul incident : type d’exception, message, pile, coupable, décomptes et la version corrélée. Jamais d’identifiants d’utilisateurs finaux, jamais de sacs d’attributs bruts, jamais d’événements entiers.
Auto-hébergement
La pile est en Docker Compose : PostgreSQL, Redis, ClickHouse, l’API, ingest, un worker et un service migrate à usage unique. Tout se configure par l’environnement.
Obligatoires
DATABASE_URL | Chaîne de connexion PostgreSQL. Aucune valeur par défaut. |
REDIS_URL | Redis, utilisé pour la limitation de débit. Aucune valeur par défaut. |
Essentiels
ENV | development (par défaut) ou production. En production, les livraisons de paiement de bac à sable sont refusées. |
LOG_LEVEL | info par défaut. |
DASHBOARD_ORIGIN | Où le tableau de bord est servi. Les requêtes authentifiées par cookie doivent envoyer un Origin correspondant, sinon origin_rejected. |
API_PUBLIC_URL | Active l’authentification unique. Non défini, le SSO répond sso_unavailable. |
INGEST_PUBLIC_URL | Le point d’entrée publié dans les DSN. |
SESSION_COOKIE_NAME | slk_session par défaut. |
SESSION_TTL | 720h par défaut. |
SECURE_COOKIES | À définir pour les déploiements HTTPS. |
SHUTDOWN_TIMEOUT | 15s par défaut. |
Limites
INGEST_REQUESTS_PER_MINUTE | 600 par défaut, par projet. |
INGEST_EVENTS_PER_MINUTE | 30000 par défaut, par organisation. |
AUTH_ATTEMPTS_PER_MINUTE | 10 par défaut. |
INVESTIGATIONS_PER_HOUR | 100 par défaut. |
Stockage et secrets
CLICKHOUSE_URL | Active le magasin d’événements ClickHouse. Sa présence bascule aussi les lectures vers lui. |
READ_EVENTS_FROM_CLICKHOUSE | Dérivé de CLICKHOUSE_URL. Lancez le backfill avant de basculer sur une base avec un historique. |
SECRET_ENCRYPTION_KEY | Requis par tout ce qui stocke un secret chiffré, sinon la réponse est secrets_not_durable. |
ARTIFACT_DIR / ARTIFACT_S3_* | Où vivent les artefacts de source maps. Un service pointé vers le mauvais magasin échoue silencieusement. |
BACKUP_ENCRYPTION_KEY | Requis par chaque commande de sauvegarde. Une valeur différente rend illisibles les artefacts existants. |
BACKUP_DIR / BACKUP_S3_* / BACKUP_WAL_SPOOL | Destination des sauvegardes et tampon d’écriture anticipée. |
BACKUP_RETENTION_DAYS / BACKUP_MIN_ARTIFACTS | Quelle quantité d’historique conserver. |
Fonctionnalités optionnelles
ANTHROPIC_API_KEY / ANTHROPIC_MODEL | Investigations IA. Entièrement désactivées si non défini. |
GENIUSPAY_API_KEY / _API_SECRET / _WEBHOOK_SECRET | Achat d’une offre. La clé est l’interrupteur : non définie, ni le paiement ni la route de webhook ne sont montés. |
GENIUSPAY_BASE_URL | Par défaut, la base de l’API marchand. |
SMTP_HOST / _PORT / _USERNAME / _PASSWORD / _FROM | Envoi des alertes par courriel. |
OPERATOR_WEBHOOK_URL | Alertes d’exploitation sur ce déploiement. Volontairement non défini par défaut : rien n’est envoyé. |
ACCOUNT_ALERT_WEBHOOK_URL | Alertes commerciales sur les clients. Repli sur OPERATOR_WEBHOOK_URL. |
OTLP_ENDPOINT | Où cette plateforme envoie sa propre télémétrie. |
Commandes
cmd/api | L’API du tableau de bord. |
cmd/ingest | Le service d’ingestion de télémétrie. Un processus séparé, à dessein. |
cmd/worker | Les tâches planifiées — rétention, purge, synthèses, évaluation des alertes. |
cmd/alerts | Évaluer les alertes une fois, à la main. |
cmd/migrate | Appliquer les migrations. Embarquées dans le binaire : un nouveau fichier .sql ne fait rien tant que l’image n’est pas reconstruite. |
cmd/seed | Construire l’organisation et les projets de test locaux. |
cmd/plan | Attribuer une offre à une organisation. Une action d’exploitation, et elle est auditée. |
cmd/retention | Appliquer la rétention maintenant. |
cmd/purge | Supprimer la télémétrie des organisations qui n’existent plus. |
cmd/erase | Effacer les données d’une personne sur demande. |
cmd/refingerprint | Recalculer le regroupement des incidents sur tout l’historique. |
cmd/backfill | Copier les événements existants dans ClickHouse avant d’y basculer les lectures. |
cmd/backup | Prendre une sauvegarde chiffrée. |
Les migrations sont embarquées dans le binaire. Un nouveau fichier .sql ne fait rien tant que l’image migrate n’est pas reconstruite, et le conteneur journalise « migrations applied » dans les deux cas. Vérifiez la version du schéma plutôt que la ligne de journal.
Sécurité et confidentialité
- Le masquage a lieu deux fois. Les SDK masquent les valeurs qui ressemblent à des secrets avant l’envoi, et le chemin d’ingestion masque à nouveau à l’arrivée — clés, jetons, en-têtes d’autorisation, JWT, identifiants cloud, et affectations clé=valeur dans le texte libre.
- La relecture est masquée avant la capture, dans le navigateur, avec les réglages par défaut de rrweb inversés.
- Les locataires sont isolés comme condition de publication, pas par convention. La suite inter-locataires fait partie des contrôles qui doivent passer.
- Les requêtes sortantes sont contrôlées. Les destinations d’alertes passent par un composeur qui refuse les adresses privées et lien-local : un webhook ne peut donc pas être pointé vers l’intérieur du réseau.
- Les changements d’offre sont audités. Qui a accordé quoi est le seul historique que garde cette attribution.
- Le site vitrine ne stocke rien et n’appelle personne — pas d’analytique, pas de CDN, pas de polices chargées à l’exécution — c’est pourquoi il ne porte aucune bannière de cookies. Un test l’impose.
Le registre des sous-traitants et les plafonds de rétention sont publiés séparément et relèvent du même engagement : voir les pages sécurité et confidentialité.
Ce que cette plateforme ne fait pas
Énuméré plutôt qu’omis. Un développeur qui ne trouve pas une fonctionnalité suppose qu’il l’a manquée, et l’apprend de la manière coûteuse.
- Elle n’agit pas sur ce que comprend une offre. Dépasser un volume inclus ne vous ralentit jamais, ne rejette jamais de télémétrie et ne déclenche aucun prélèvement — il n’y a aucune facturation au dépassement.
- Elle ne prédit pas les pannes. Elle signale une métrique qui monte vers une ligne qu’elle trace déjà, avec la pente et le trafic derrière, et dit ce qui invaliderait la projection. Il n’y a ni probabilité ni heure de décès.
- Elle ne suggère pas de mises à jour de dépendances. Une frame de pile nomme un paquet et jamais une version : une suggestion serait une instruction assurée à propos d’un logiciel qu’elle n’a jamais vu.
- Elle n’exécute aucune remédiation. Une suggestion est une phrase.
- Il n’y a pas de facturation annuelle. Le catalogue ne porte qu’un prix mensuel et le paiement vend des mois à ce prix.
- Il n’y a pas encore de factures. Rien n’est émis à personne.
- L’ingestion de points de métrique n’est pas conditionnée à l’offre, contrairement à la relecture. Une offre sans volume de points de métrique peut quand même en envoyer et les voir mesurés.
- Le tableau de bord est uniquement en anglais. Les pages vitrine, légales et de documentation sont en anglais et en français ; le produit, non.