sixty

para aplicaciones Ruby y Rails

No hay paso dos.

Rails tiene un gancho de arranque documentado y un bus de eventos que ya anuncia cada consulta, así que este agente no necesita ni inicializador ni envoltorio: añade la gema, define dos variables de entorno, y los controladores pasan a ser operaciones con sus consultas atribuidas. Todo lo de abajo ocurre sin que escribas una línea de instrumentación.

Qué mide

Cada acción de controlador
Nombrada por controlador#acción, así que la lista se lee como tu archivo de rutas. El railtie las envuelve al arrancar — no hay nada que incluir ni nada que recordar en el siguiente controlador.
Cada consulta que emite ActiveRecord
Suscrito a través de sql.active_record, que es el bus en el que Rails ya publica. Filas, la sentencia normalizada, el tamaño de la respuesta y qué acción la emitió.
Tres bases de datos, con sus propias reglas
pg con planes de consulta vía EXPLAIN; mysql2 y trilogy leídos con las reglas de comillas de MySQL y no con las de Postgres, porque una cadena entre comillas dobles es un literal en una y un identificador en la otra; y mongo, que es lo que usa Mongoid, con la forma del comando como identidad.
Qué hizo la base de datos para responder
A Postgres se le pide el plan de cada sentencia — un EXPLAIN de plan genérico, cacheado por sentencia, emitido fuera del span de quien llama para que nunca se mida como su trabajo, y sin enlazar nunca un parámetro, así que no interviene ningún valor tuyo.
Tus propias clases, cuando quieras
include Sixty::Instrumented convierte cada método público de instancia en una operación y deja en paz los métodos privados y los accesores. O Sixty.instrument(Stripe::Charge, :create) para un método de la clase de otro.

Qué encuentra

Cada una de estas se compara con la versión anterior, así que el hallazgo nombra el cambio y no el día.

Una consulta que dejó de usar su índice

El único hallazgo aquí que nombra una causa en vez de un síntoma, y a menudo llega antes de que nada vaya lento: la tabla todavía es lo bastante pequeña como para que un escaneo esté bien, y se convierte en una caída semanas después, cuando ya no lo es.

Un N+1 que no estaba en la versión anterior

El defecto del que más se acusa a Rails, detectado por número y no por reloj: una consulta por acción se convirtió en veinte, todas rápidas, y el includes se cayó en una refactorización hace tres semanas.

Una consulta que empezó a leer la tabla entera

Las filas por llamada pasaron de 30 a 30.000 — un scope cuyo where se mudó a Ruby, que devuelve la misma respuesta y se lee perfectamente sensato.

Tu propio código volviéndose más lento

Tiempo en el propio método y no en lo que llamó, así que «¿se volvió lento mi código o lo que llamé?» es un número en vez de una tarde.

Una consulta que calladamente no devuelve nada

Funcionó, no lanzó nada, y volvió vacía donde antes volvía con filas. ActiveRecord está perfectamente contento; la página está en blanco.

Algo que ahora se llama dentro de un bucle

Sin cambios por llamada y llamado cientos de veces donde antes se llamaba una — incluso a través de un trabajo en segundo plano, que reporta como su propio proceso.

Qué aparece en tu lista

No es un panel que leer. Una tarjeta por hallazgo, con las cifras, la versión que las cambió y las pruebas que tu agente de código necesita para escribir el arreglo.

Estas son las dos regresiones que apps/demo-rails incluye a propósito, contra el conjunto de datos que siembra bin/rails db:prepare — unos 30.000 pedidos. Puedes ejecutarlo y verlas llegar.

filasOrdersQuery#for_user
30 filas30.000 filas1000×

Alguien refactorizó el scope y el where se mudó a Ruby, así que cada llamada carga la tabla entera y filtra en memoria. Devuelve la misma respuesta, y en un portátil cuesta unos milisegundos.

desde la versión v2, frente a la v1

N+1OrdersQuery#enrich
1 consulta20 consultas20×

Una búsqueda por lotes se convirtió en una por pedido. Cada consulta es individualmente rápida y está correctamente indexada, que es lo que permite a esta clase de fallo sobrevivir a la revisión de código y a staging.

desde la versión v2, frente a la v1

Cómo se instala

En Rails esta es toda la instalación: la gema y dos variables de entorno. El railtie añade el middleware, se suscribe al bus de consultas y envuelve las acciones de los controladores al arrancar, así que no hay inicializador que escribir ni nada que llamar.

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

El identificador de versión se recoge por su cuenta de Vercel, Render, Railway, Fly, Heroku o GitHub Actions, y SIXTY_RELEASE lo fija en cualquier otro sitio. La primera comparación llega tras tu siguiente despliegue, porque no hay nada con lo que comparar una sola versión.

Qué no hace

  • Los planes de consulta son solo de Postgres. MySQL no tiene EXPLAIN de plan genérico y MongoDB no tiene sentencia que explicar — y explicar cualquiera de las dos significaría retener los valores de las consultas de alguien para devolvérselos a su propia base de datos en un comando compuesto por nosotros, cosa que este agente no hará.
  • La CPU y la espera no se separan. Eso necesita un reloj por hilo y un span que sea dueño de su hilo, que solo tiene el agente de Python.
  • Bajo Puma con workers, o Sidekiq, cada proceso reporta por separado y el colector los fusiona. Eso es correcto, y conviene saberlo cuando leas un número por proceso.
  • include Sixty::Instrumented mide métodos públicos de instancia. Un método privado que hace el trabajo de verdad es invisible hasta que lo conviertas en operación de alguna otra forma, que es el precio de no adivinar qué merece medirse.

Si estás aquí por una de estas

Descubre qué hizo tu último cambio.

¡Pruébalo!

¿Construyes otra cosa? Mira servicios Node, aplicaciones PHP y Laravel o servicios Python — esas páginas son distintas, y también lo es lo que podemos ver.

Monitorización de rendimiento para Rails — Postgres, MySQL y MongoDB — Sixty