Rails在生产环境中调试

时间:2010-01-16 15:12:08

标签: mysql ruby-on-rails debugging twitter sqlite

我正在创建一个Twitter应用程序,每次用户更新页面时,它都会重新加载来自Twitter的最新消息,并将它们保存到本地数据库,除非它们之前已经创建过。这在开发环境(数据库:sqlite3)中运行良好,但在生产环境(mysql)中,它总是会再次创建消息,即使它们已经创建过。

twitter_id检查消息创建,每条消息都有:

msg = Message.find_by_twitter_id(message_hash['id'].to_i)
if msg.nil?
  # creates new message from message_hash (and possibly new user too)
end
msg.save

显然,在生产环境中,由于某些原因,它无法通过twitter id找到消息(当我查看数据库时,它已经正确保存了所有属性)。

通过这个漫长的介绍,我想我的主要问题是如何调试这个? (当然,除非你已经找到了主要问题的答案:)当我查看production.log时,它只显示如下内容:

Processing MainPageController#feeds (for 91.154.7.200 at 2010-01-16 14:35:36) [GET]
Rendering template within layouts/application
Rendering main_page/feeds
Completed in 9774ms (View: 164, DB: 874) | 200 OK [http://www.tweets.vidious.net/]

...但不是数据库请求,logger.debug文本或任何可以帮助我找到问题的内容。

3 个答案:

答案 0 :(得分:9)

您可以通过在config / environment / production.rb中设置日志级别来更改生产中的日志级别

config.log_level = :debug

这将记录sql以及您在dev中看到的所有其他内容 - 它会使应用程序变慢,并且您的日志会很大,所以请谨慎使用。

但至于问题背后的实际问题......

可能是因为有多个连接访问mysql吗?

如果Twitter条目尚未提交,那么从另一个连接查询它们将不会返回它们,因此如果在提交之前调用它们的查询,那么您将找不到它们,而是将替换相同的条目再次。这种情况更有可能发生在拥有许多用户的生产环境中,而不是单独使用sqlite进行测试。

由于您使用的是mysql,因此您可以使用twitter id上的唯一键来防止欺骗,然后在尝试插入欺骗时捕获ActiveRecord异常。但这意味着处理一个错误,这不是处理这个问题的一种很好的方式(尽管我建议将其作为防止欺骗的备份方法 - mysql对此有好处,使用它)。

您还应该阻止尝试插入欺骗。一种方法是在公共记录上使用锁定,比如说所有推文都与之相关的用户记录,这样另一个进程就无法尝试为用户添加推文,直到它能够获得该锁定(只有在事务已完成),因此阻止同时提交相同的信息。

答案 1 :(得分:1)

我在将电子邮件保存到数据库时遇到了类似的问题,我同意Andrew的意见,将日志级别设置为调试,以获取有关具体情况的更多信息。

对于实际问题,您可以尝试向数据库添加唯一索引,以防止使用相同参数保存两个项目。这与validates_uniqueness类似,但在数据库级别,并且非常有效:Mysql Constraign Database Entries in Rails

例如,如果您不希望数据库中的消息对象具有重复的文本正文,并且重复的推特ID(这意味着同一个人在Twitter上发送相同的文本)。然后,您可以将其添加到迁移中:

add_index( :message, [:twitter_id, :body] , :unique => true)

在告诉Rails中的对象保存之前需要花费一些时间,在实际进入数据库之前,这可能是为什么id的查询还没有找到任何内容。

答案 2 :(得分:0)

对于您的生产服务器,我建议您设置rollbar以报告生产服务器中的所有未处理错误和例外情况。

您还可以存储一堆有用的信息,例如http请求,请求的用户,调用错误的代码等等,或者每次生产服务器上发生一些未处理的异常时发送电子邮件通知。

这是一个简单的article about debugging in rails,可以帮助你。