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

  1. 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.
  2. É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.
  3. Envoyez quelque chose. L’un des SDK ci-dessous, ou de l’OTLP brut vers le point d’ingestion.
  4. 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.

SDKPaquetApporte
Gosdk/go/snagspyAnalyse du DSN, CaptureException, masquage, middleware HTTP.
Navigateur et Nodesdk/jsAnalyse 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éthodeCheminCorps
POST/v1/tracesCharge utile OTLP de traces. Les spans portant une exception deviennent des incidents.
POST/v1/logsCharge utile OTLP de journaux.
POST/v1/metricsCharge utile OTLP de métriques.
POST/v1/replayUn fragment de relecture. Voir ci-dessous.
GET/healthzVivacité.

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/registerCré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/logoutTerminer la session en cours.
GET/v1/meL’utilisateur connecté et son organisation.
GET/v1/membersLes membres de l’organisation.
GET/v1/projectsLister les projets.
POST/v1/projectsCréer un projet.
GET/v1/projects/{projectID}Un projet.
GET/v1/projects/{projectID}/dsnsLes 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-replayActiver ou désactiver la capture de relecture pour le projet.
GET/v1/api-keysLister les clés d’API.
POST/v1/api-keysCré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/settingsLes réglages de l’organisation, dont la rétention.
PATCH/v1/settingsModifier les réglages de l’organisation.
GET/v1/audit-logLe 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/startDémarrer une connexion SSO.
GET/v1/auth/sso/callbackRetour du fournisseur d’identité.
GET/v1/settings/ssoLa connexion actuelle.
PUT/v1/settings/ssoConfigurer la connexion.
DELETE/v1/settings/ssoSupprimer la connexion.
GET/v1/settings/sso/domainsLes domaines de messagerie revendiqués.
POST/v1/settings/sso/domainsRevendiquer un domaine.
POST/v1/settings/sso/domains/verifyProuver un domaine revendiqué.

Incidents et événements

GET/v1/issuesLister les incidents, filtrés et paginés.
GET/v1/issues/{issueID}Un incident.
GET/v1/issues/{issueID}/eventsLes occurrences d’un incident.
PATCH/v1/issues/{issueID}Changer le statut (résolu, ignoré, rouvert).
GET/v1/usersLes utilisateurs finaux vus dans la télémétrie.
GET/v1/feedbackLes retours utilisateurs soumis.
POST/v1/feedbackSoumettre un retour utilisateur.

Traces, services et performance

GET/v1/tracesListe des traces. Filtre sur les spans, agrège des traces entières.
GET/v1/traces/{traceID}Une trace et ses spans.
GET/v1/servicesListe des services avec leur santé.
GET/v1/services/mapLa topologie de services observée.
GET/v1/services/structureLes faits structurels de la topologie.
GET/v1/services/dependenciesLes arêtes entre services.
GET/v1/services/approachingMétriques qui montent vers le seuil, avec la pente.
GET/v1/trafficLe trafic par projet plutôt que par service le plus lent.
GET/v1/queuesComportement des files et des workers.
GET/v1/anomaliesAnomalies détectées.
GET/v1/endpoints/surgesSignal d’abus par point d’entrée, sans identité de l’appelant.
GET/v1/database/slow-queriesRequêtes lentes en base.
GET/v1/database/query-patternsMotifs de requêtes.

Journaux et métriques (lecture)

GET/v1/logsRechercher dans les lignes de journal.
GET/v1/logs/patternsFormes de journaux récurrentes.
GET/v1/logs/surgesPics de volume de journaux.
GET/v1/metrics/namesNoms de métriques observés.
GET/v1/metrics/seriesPoints d’une série nommée.

Relecture de session

GET/v1/projects/{projectID}/replaySessions 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/deploymentsEnregistrer un déploiement.
GET/v1/deploymentsLister les déploiements.
GET/v1/deployments/{deploymentID}Un déploiement.
GET/v1/deployments/{deploymentID}/healthCe déploiement a-t-il aggravé les choses, avec le calcul.
GET/v1/releasesLes versions, dérivées des déploiements plutôt que stockées.
GET/v1/projects/{projectID}/integrationsLes 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}/artifactsEnvoyer une source map ou un artefact de débogage.
GET/v1/projects/{projectID}/artifactsLister les artefacts.
DELETE/v1/projects/{projectID}/artifacts/{artifactID}En supprimer un.

Alertes, destinations et rapports

GET/v1/alertsHistorique des alertes.
GET/v1/alert-destinationsOù les alertes sont envoyées.
POST/v1/alert-destinationsAjouter une destination.
DELETE/v1/alert-destinations/{destinationID}En supprimer une.
GET/v1/reports/scheduleLa planification des synthèses.
PUT/v1/reports/scheduleLa définir.
DELETE/v1/reports/scheduleL’arrêter.
GET/v1/reports/previewGénérer la prochaine synthèse sans l’envoyer.

Tâches planifiées et disponibilité

GET/v1/cron/checksLister les contrôles de tâches planifiées.
POST/v1/cron/checksEn 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}/pingsHistorique des pointages.
POST/v1/cron/checks/{checkID}/rotateRenouveler 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/monitorsLister les moniteurs de disponibilité.
POST/v1/uptime/monitorsEn créer un.
PATCH/v1/uptime/monitors/{monitorID}En modifier un.
DELETE/v1/uptime/monitors/{monitorID}En supprimer un.
GET/v1/uptime/monitors/{monitorID}/checksRésultats des sondes.

Tableaux de bord

GET/v1/dashboardsLister les tableaux de bord.
POST/v1/dashboardsEn créer un.
GET/v1/dashboards/{dashboardID}Un tableau de bord.
PATCH/v1/dashboards/{dashboardID}Renommer ou redécrire.
PUT/v1/dashboards/{dashboardID}/widgetsRemplacer 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}/investigateEnquêter sur un incident.
GET/v1/issues/{issueID}/investigationLe résultat.
POST/v1/alerts/{alertID}/investigateEnquêter sur une alerte.
GET/v1/alerts/{alertID}/investigationLe résultat.
POST/v1/projects/{projectID}/investigateEnquêter sur un projet.
POST/v1/projects/{projectID}/explainPoser une question sur la topologie.
GET/v1/investigationsLister 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/usageL’usage mesuré face à l’offre, avec une mise en garde dans chaque réponse.
POST/v1/checkoutDémarrer un achat. Portée administrateur. Renvoie une URL de paiement hébergée.

Exploitation

GET/healthzVivacité. Sur l’API comme sur le service d’ingestion.
GET/readyzDisponibilité, dépendances comprises.

Authentification

IdentifiantSert àComment
DSNÉcrire de la télémétrieDans la configuration du SDK. Public par conception — il écrit et ne lit pas.
Cookie de sessionLe tableau de bordPOST /v1/auth/login. Le cookie est slk_session et dure 720h par défaut.
Clé d’APIScripter l’API du tableau de bordEn-tête Authorization. Créée via POST /v1/api-keys, affichée une seule fois.
Jeton de pointagePointages cronDans l’URL. Le jeton est l’identifiant : renouvelez-le avec POST /v1/cron/checks/{checkID}/rotate.
SSOLe 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.

LimiteDéfautPortée
INGEST_REQUESTS_PER_MINUTE600Par projet
INGEST_EVENTS_PER_MINUTE30 000Par organisation
AUTH_ATTEMPTS_PER_MINUTE10Par appelant
INVESTIGATIONS_PER_HOUR100Par 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.

OffrePrixErreursJournauxPoints de métriqueUnités de relectureInvestigationsRétention
freeGratuit5k25kNon disponibleNon disponible107 jours
team$25/mo50k250k250k25k25030 jours
business$75/mo65k1M1M250k2.5k90 jours
enterpriseSur devisIllimitéIllimitéIllimitéIllimitéIllimité90 jours

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

TypeNécessiteNotes
SlackUne URL de webhook entrantPorte un champ text à côté de l’alerte structurée.
DiscordUne URL de webhookPorte un champ content.
Webhook génériqueUne URLLes requêtes sortantes passent par un composeur qui refuse les adresses privées et lien-local.
CourrielSMTP_* 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_URLChaîne de connexion PostgreSQL. Aucune valeur par défaut.
REDIS_URLRedis, utilisé pour la limitation de débit. Aucune valeur par défaut.

Essentiels

ENVdevelopment (par défaut) ou production. En production, les livraisons de paiement de bac à sable sont refusées.
LOG_LEVELinfo par défaut.
DASHBOARD_ORIGINOù le tableau de bord est servi. Les requêtes authentifiées par cookie doivent envoyer un Origin correspondant, sinon origin_rejected.
API_PUBLIC_URLActive l’authentification unique. Non défini, le SSO répond sso_unavailable.
INGEST_PUBLIC_URLLe point d’entrée publié dans les DSN.
SESSION_COOKIE_NAMEslk_session par défaut.
SESSION_TTL720h par défaut.
SECURE_COOKIESÀ définir pour les déploiements HTTPS.
SHUTDOWN_TIMEOUT15s par défaut.

Limites

INGEST_REQUESTS_PER_MINUTE600 par défaut, par projet.
INGEST_EVENTS_PER_MINUTE30000 par défaut, par organisation.
AUTH_ATTEMPTS_PER_MINUTE10 par défaut.
INVESTIGATIONS_PER_HOUR100 par défaut.

Stockage et secrets

CLICKHOUSE_URLActive le magasin d’événements ClickHouse. Sa présence bascule aussi les lectures vers lui.
READ_EVENTS_FROM_CLICKHOUSEDérivé de CLICKHOUSE_URL. Lancez le backfill avant de basculer sur une base avec un historique.
SECRET_ENCRYPTION_KEYRequis 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_KEYRequis par chaque commande de sauvegarde. Une valeur différente rend illisibles les artefacts existants.
BACKUP_DIR / BACKUP_S3_* / BACKUP_WAL_SPOOLDestination des sauvegardes et tampon d’écriture anticipée.
BACKUP_RETENTION_DAYS / BACKUP_MIN_ARTIFACTSQuelle quantité d’historique conserver.

Fonctionnalités optionnelles

ANTHROPIC_API_KEY / ANTHROPIC_MODELInvestigations IA. Entièrement désactivées si non défini.
GENIUSPAY_API_KEY / _API_SECRET / _WEBHOOK_SECRETAchat 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_URLPar défaut, la base de l’API marchand.
SMTP_HOST / _PORT / _USERNAME / _PASSWORD / _FROMEnvoi des alertes par courriel.
OPERATOR_WEBHOOK_URLAlertes d’exploitation sur ce déploiement. Volontairement non défini par défaut : rien n’est envoyé.
ACCOUNT_ALERT_WEBHOOK_URLAlertes commerciales sur les clients. Repli sur OPERATOR_WEBHOOK_URL.
OTLP_ENDPOINTOù cette plateforme envoie sa propre télémétrie.

Commandes

cmd/apiL’API du tableau de bord.
cmd/ingestLe service d’ingestion de télémétrie. Un processus séparé, à dessein.
cmd/workerLes tâches planifiées — rétention, purge, synthèses, évaluation des alertes.
cmd/alertsÉvaluer les alertes une fois, à la main.
cmd/migrateAppliquer les migrations. Embarquées dans le binaire : un nouveau fichier .sql ne fait rien tant que l’image n’est pas reconstruite.
cmd/seedConstruire l’organisation et les projets de test locaux.
cmd/planAttribuer une offre à une organisation. Une action d’exploitation, et elle est auditée.
cmd/retentionAppliquer la rétention maintenant.
cmd/purgeSupprimer la télémétrie des organisations qui n’existent plus.
cmd/eraseEffacer les données d’une personne sur demande.
cmd/refingerprintRecalculer le regroupement des incidents sur tout l’historique.
cmd/backfillCopier les événements existants dans ClickHouse avant d’y basculer les lectures.
cmd/backupPrendre 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.

Quelque chose ici contredit ce que la plateforme a réellement fait ? C’est un défaut de cette page et cela mérite d’être signalé — elle est faite pour être vérifiable ligne à ligne.