在Rails中记录长时间运行的事务

时间:2013-12-04 21:40:34

标签: ruby-on-rails activerecord

我的生产Rails应用程序中出现“Mysql2 :: Error:Lock wait timeout exceeded”错误,我正在寻找帮助调试哪个事务锁定表格的时间过长。据我所知,MySQL有一个“慢查询”日志,但不是慢速事务的日志。

有没有办法记录有关事务直接从ActiveRecord获取多长时间的信息?

1 个答案:

答案 0 :(得分:4)

我的团队记录这样的慢事务:

lib/slow_transaction_logger.rb

module SlowTransactionLogger
  LOG_IF_SLOWER_THAN_SECONDS = ENV.fetch("LOG_TRANSACTIONS_SLOWER_THAN_SECONDS", "5").to_f

  def transaction(*args)
    start = Time.now
    value = super
    finish = Time.now

    duration = finish - start

    return value if duration <= LOG_IF_SLOWER_THAN_SECONDS

    backtrace = caller.
      select { |path| path.start_with?(Rails.root.to_s) }.
      reject { |row|
        row.include?("/gems/") ||
        row.include?("/app/middleware/") ||
        row.include?("/config/initializers/")
      }

    puts "slow_transaction_logger: duration=#{duration.round(2)} start=#{start.to_s.inspect} finish=#{finish.to_s.inspect} class=#{name} caller=#{backtrace.to_json}"

    value
  end
end

config/initializers/active_record.rb

class ActiveRecord::Base
  class << self
    prepend SlowTransactionLogger
  end
end

因此,默认情况下,它会在每个环境中记录慢于5秒的事务。

如果您设置LOG_TRANSACTIONS_SLOWER_THAN_SECONDS环境变量(例如在Heroku上),则可以调整该限制。

我们故意用puts登录,因为它最终出现在Heroku的日志中,我们也在开发和测试中更容易看到它。但如果您愿意,可以随意使用Rails.logger