pour les applications Ruby et Rails
Il n’y a pas d’étape deux.
Rails a un point d’accroche de démarrage documenté et un bus d’événements qui annonce déjà chaque requête, donc cet agent n’a besoin ni d’initializer ni d’enveloppe : ajoutez la gem, définissez deux variables d’environnement, et les contrôleurs deviennent des opérations avec leurs requêtes attribuées. Tout ce qui suit se produit sans que vous écriviez une ligne d’instrumentation.
Ce qu’il mesure
- Chaque action de contrôleur
- Nommée par contrôleur#action, donc le fil se lit comme votre fichier de routes. Le railtie les enveloppe au démarrage — il n’y a rien à inclure et rien à se rappeler au prochain contrôleur.
- Chaque requête émise par ActiveRecord
- Abonné via sql.active_record, le bus sur lequel Rails publie déjà. Les lignes, la requête normalisée, la taille de la réponse, et quelle action l’a émise.
- Trois bases, chacune selon ses règles
- pg avec les plans de requête via EXPLAIN ; mysql2 et trilogy lus selon les règles de citation de MySQL plutôt que celles de Postgres, parce qu’une chaîne entre guillemets doubles est un littéral dans l’une et un identifiant dans l’autre ; et mongo, ce qu’utilise Mongoid, avec la forme de la commande comme identité.
- Ce que la base a fait pour répondre
- On demande à Postgres le plan de chaque requête — un EXPLAIN à plan générique, mis en cache par requête, émis en dehors du span de l’appelant pour qu’il ne soit jamais mesuré comme son travail, et sans jamais lier un paramètre, donc aucune de vos valeurs n’est impliquée.
- Vos propres classes, quand vous le voulez
- include Sixty::Instrumented transforme chaque méthode d’instance publique en opération et laisse les méthodes privées et les accesseurs tranquilles. Ou Sixty.instrument(Stripe::Charge, :create) pour une méthode sur la classe de quelqu’un d’autre.
Ce qu’il trouve
Chacune de ces choses est comparée à la version précédente : le constat nomme donc le changement plutôt que le jour.
Une requête qui a cessé d’utiliser son index
Le seul constat ici qui nomme une cause plutôt qu’un symptôme, et il arrive souvent avant que quoi que ce soit ne soit lent : la table est encore assez petite pour qu’un balayage passe, et cela devient une panne des semaines plus tard, quand elle ne l’est plus.
Un N+1 qui n’était pas là à la version précédente
Le défaut dont Rails est le plus souvent accusé, attrapé par le compte plutôt que par l’horloge : une requête par action en est devenue vingt, toutes rapides, et le includes a sauté lors d’une refonte il y a trois semaines.
Une requête qui s’est mise à lire toute la table
Les lignes par appel sont passées de 30 à 30 000 — un scope dont le where est parti dans Ruby, qui renvoie la même réponse et se lit parfaitement raisonnablement.
Votre propre code qui ralentit
Le temps dans la méthode elle-même plutôt que dans ce qu’elle a appelé, donc « est-ce mon code qui a ralenti ou ce que j’ai appelé » est un chiffre au lieu d’un après-midi.
Une requête qui ne renvoie plus rien, en silence
Réussie, rien de levé, et revenue vide là où elle revenait avec des lignes. ActiveRecord est parfaitement content ; la page est blanche.
Quelque chose désormais appelé dans une boucle
Inchangé par appel et appelé des centaines de fois là où il l’était une seule — y compris via un job de fond, qui remonte comme son propre processus.
Ce qui arrive dans votre fil
Pas un tableau de bord à lire. Une carte par constat, avec les chiffres, la version qui les a changés, et les preuves dont votre agent de code a besoin pour écrire le correctif.
Ce sont les deux régressions qu’apps/demo-rails livre exprès, contre le jeu de données que sème bin/rails db:prepare — environ 30 000 commandes. Vous pouvez le lancer et les regarder arriver.
OrdersQuery#for_userQuelqu’un a refactoré le scope et le where est parti dans Ruby, donc chaque appel charge toute la table et filtre en mémoire. Cela renvoie la même réponse, et sur un portable cela coûte quelques millisecondes.
depuis la version v2, contre la v1
OrdersQuery#enrichUne recherche groupée est devenue une recherche par commande. Chaque requête est individuellement rapide et correctement indexée, ce qui est ce qui permet à cette classe de bug de survivre à la relecture et au staging.
depuis la version v2, contre la v1
Comment ça s’installe
Sur Rails, c’est toute l’installation : la gem, et deux variables d’environnement. Le railtie ajoute le middleware, s’abonne au bus de requêtes et enveloppe les actions de contrôleur au démarrage, donc il n’y a pas d’initializer à écrire et rien à appeler.
claude mcp add sixty \ -e SIXTY_API_KEY=sixty_sk_… \ -e SIXTY_ENDPOINT=https://ingest.sixty.sh \ -- npx -y @sixty-sh/mcp # or by hand: gem 'sixty' # Gemfile export SIXTY_API_KEY=sixty_sk_… export SIXTY_SERVICE=checkout-api # On Rails, that is the install. Outside it: require 'sixty' Sixty.init use Sixty::Instrument::Rack # config.ru — Sinatra, Hanami, a bare app # Your own classes, if you want them measured: class OrdersQuery include Sixty::Instrumented end
L’identifiant de version est récupéré tout seul chez Vercel, Render, Railway, Fly, Heroku ou GitHub Actions, et SIXTY_RELEASE le fixe partout ailleurs. La première comparaison arrive après votre prochain déploiement, parce qu’il n’y a rien à quoi comparer une version isolée.
Ce qu’il ne fait pas
- Les plans de requête ne concernent que Postgres. MySQL n’a pas d’EXPLAIN à plan générique et MongoDB n’a pas de requête à expliquer — et expliquer l’une ou l’autre voudrait dire conserver les valeurs de requête de quelqu’un pour les renvoyer à sa propre base dans une commande que nous aurions composée, ce que cet agent ne fera pas.
- Le CPU et l’attente ne sont pas séparés. Cela demande une horloge par thread et un span qui possède son thread, ce que seul l’agent Python a.
- Sous Puma avec des workers, ou Sidekiq, chaque processus remonte indépendamment et le collecteur les fusionne. C’est correct, et bon à savoir quand vous lisez un chiffre par processus.
- include Sixty::Instrumented mesure les méthodes d’instance publiques. Une méthode privée qui fait le vrai travail est invisible tant que vous n’en faites pas une opération autrement, ce qui est le prix à payer pour ne pas deviner ce qui mérite d’être mesuré.
Si vous êtes ici pour l’une de ces raisons
Découvrez ce qu’a fait votre dernier changement.
Essayez !Vous construisez autre chose ? Voyez services Node, applications PHP et Laravel ou services Python — ces pages sont différentes, et ce que nous voyons aussi.