Cómo identificar consultas lentas en Ruby on Rails sin la necesidad de instalar gemas

Te compartimos una forma sencilla de encontrar consultas lentas a la base de datos sin necesidad de instalar gemas extras. Para ello, vamos a usar Active Support Instrumentation API para que, cada vez que una consulta a nuestra base de datos tarde más de 2 segundos, recibamos una alerta en nuestra herramienta de monitoreo.

🤔 ¿Qué es y para qué sirve Active Support Instrumentation?

Active Support Instrumentation nos proveé de un mecanismo para suscribirnos a determinados eventos que ocurren dentro de nuestra aplicación Rails, como así también a eventos que definamos nosotros mismos.

Dentro de los eventos a los cuales podemos suscribirnos están los relacionados a los controladores, a las vistas, al uso de la Caché, a la interacción de nuestros objetos ActiveRecord con la base de datos, entre otros.

En esta ocasión, nos vamos a centrar en la suscripción a los eventos relacionados al acceso a la base de datos.

⏳ ¿Cómo suscribirse a un evento?

Para suscribirse a un evento en particular es tan simple como invocar al método subscribe del módulo ActiveSupport::Notifications

ActiveSupport::Notifications.subscribe 'sql.active_record' do |event|
puts "Event name: #{event.name}"
puts "Event duration: #{event.duration}"
puts "Event payload: #{event.payload[:sql]}"
end

El evento recibido contiene los siguientes atributos:
– name: Nombre del evento.
– duration: Tiempo que pasó entre el comienzo y el fin del evento. Está expresado en milisegundos.
– payload: Toda la información del evento.

Un ejemplo de lo que obtendríamos al recibir el evento sería como lo siguiente:

Event name: sql.active_record
Event duration: 1.511999998911051
Event payload: UPDATE "users" SET "last_activity_at" = $1 WHERE "users"."id" = $2

👨🏻‍💻 Ahora sí, vamos al caso práctico

# config/initializers/active_support_subscriptions.rb
class SlowQueryError < StandardError; end

ActiveSupport::Notifications.subscribe('sql.active_record') do |event|
if event.duration > 2_000
# La siguiente línea dependerá de la herramienta de monitoreo que uses
Sentry.capture_message(SlowQueryError.new(event.payload[:sql].to_s))
end
end

En este ejemplo se ve cómo vamos a mandar aquellas consultas que tarden más de dos segundos en su ejecución a nuestra herramienta de monitoreo. En nuestro caso usamos Sentry, pero podría ser cualquier otra.

Conclusión

Esto fue simplemente un ejemplo de cómo podemos suscribirnos a un evento particular de nuestra aplicación Rails y tomar alguna acción en base a nuestras necesidades.

Así como podemos suscribirnos a eventos que ocurren dentro de nuestra aplicación Rails, también tenemos la posibilidad de definir eventos personalizados y suscribirnos de la misma manera que lo hicimos con las consultas a la base de datos.

Te invitamos a consultar la documentación para crear eventos personalizados y ver cómo suscribirse a ellos.