记录调用者应用程序堆栈跟踪以及每个 SQL 查询
我在寻找项目中某些 sql 查询的根源时遇到了问题。
为了排除故障,我想将应用程序调用者堆栈与触发的每个查询一起记录。
我在谷歌上搜索过没有开箱即用的解决方案,所以我决定制作可靠且可靠的解决方案。我自己可重复使用的解决方案。
通过跟踪堆栈,我发现所有查询都通过 Mysql2Adapter.execute 方法(当然我指的是 mysql 的情况)的地方
,我已经在 Rails 初始值设定项目录中重写了此方法,下面列出了带有调用者堆栈日志记录的猴子补丁:
module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractAdapter
def execute(sql, name = nil)
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
if name == :skip_logging
@connection.query(sql)
else
# caller logging
log_stack
# EO
log(sql, name) { @connection.query(sql) }
end
rescue ActiveRecord::StatementInvalid => exception
if exception.message.split(":").first =~ /Packets out of order/
raise ActiveRecord::StatementInvalid, "'Packets out of order'... bindings."
else
raise
end
end
private
def log_stack
#If marazmuz will take over i would not like to spam logs in production
return unless Rails.env == 'development'
#Regex with rails directory path would be helpful in taking app stack trace only
regexp = Regexp.new( Rails.root.to_s )
res = ''
caller.each_with_index{|x,i|
#We'll took only items containing Rails.root and we are not interested in current stack position, so skip i == 0
res << "#{ '#'+i.to_s}:\t#{ x.sub(regexp,'') }\n" if x =~ regexp && i != 0
}
Rails.logger.info( res ) unless res.blank?
end
end
end
end
最后将以下输出写入日志
\#4: /app/models/contact.rb:57:in `get_raw_cols'
\#5: /app/models/contact.rb:65:in `stat_cols'
\#6: /app/components/contacts_tab.rb:85:in `configuration'
\#19: /app/views/welcome/index.html.erb:1:in `_app_views_welcome_index_html_erb___736761216545810182_25680180__4434876849107960087'
SQL (0.1ms) SELECT `contacts`.`activity` FROM `contacts`
有人:
知道具有相同功能的开箱即用的分析解决方案吗?
曾经遇到过类似的问题&你是怎么解决的?
对上述代码的任何评论/改进也非常感谢。 提前致谢。
I have run into problem with hunting the roots of some sql queries in my project.
To troubleshoot it i wanted to log application caller stack together with each query fired.
I had googled no out of the box solution, so i decided to make reliable & reusable solution by myself.
By tracing the stack i found place where all queries passed Mysql2Adapter.execute
method ( i mean case of mysql of course )
I have overridden this method in rails initializers dir, monkey patch with caller stack logging is listed below:
module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractAdapter
def execute(sql, name = nil)
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
if name == :skip_logging
@connection.query(sql)
else
# caller logging
log_stack
# EO
log(sql, name) { @connection.query(sql) }
end
rescue ActiveRecord::StatementInvalid => exception
if exception.message.split(":").first =~ /Packets out of order/
raise ActiveRecord::StatementInvalid, "'Packets out of order'... bindings."
else
raise
end
end
private
def log_stack
#If marazmuz will take over i would not like to spam logs in production
return unless Rails.env == 'development'
#Regex with rails directory path would be helpful in taking app stack trace only
regexp = Regexp.new( Rails.root.to_s )
res = ''
caller.each_with_index{|x,i|
#We'll took only items containing Rails.root and we are not interested in current stack position, so skip i == 0
res << "#{ '#'+i.to_s}:\t#{ x.sub(regexp,'') }\n" if x =~ regexp && i != 0
}
Rails.logger.info( res ) unless res.blank?
end
end
end
end
finally the following output is written to log
\#4: /app/models/contact.rb:57:in `get_raw_cols'
\#5: /app/models/contact.rb:65:in `stat_cols'
\#6: /app/components/contacts_tab.rb:85:in `configuration'
\#19: /app/views/welcome/index.html.erb:1:in `_app_views_welcome_index_html_erb___736761216545810182_25680180__4434876849107960087'
SQL (0.1ms) SELECT `contacts`.`activity` FROM `contacts`
Does anybody:
know out of the box profiling solution with the same functionality?
have ran ever into similar problem & how you solved it?
Any comments / improvements to the code above are also much appreciated.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于未来的 Google 员工:active_record_query_trace gem 也可以做到这一点。
For future Googlers: The active_record_query_trace gem can also do that.
我想我已经找到了一个完美的解决方案
https://github.com/lightyear/sql-logging
到目前为止,它对我来说非常有效。
享受
I think I have found a perfect solution
https://github.com/lightyear/sql-logging
until now it works perfectly for me.
Enjoy