在控制台中禁用Rails的SQL日志记录

312

在控制台执行命令时,有没有办法禁用 SQL 查询日志记录?理想情况下,如果我可以通过控制台中的一个命令来禁用并重新启用它,那就太好了。

我正在尝试调试某些内容,并使用“puts”打印出一些相关数据。但是 SQL 查询输出使得阅读变得困难。


编辑: 我找到了另一种解决方案,因为将记录器设置为 nil 有时可能会导致错误,如果除我的代码之外的其他东西尝试调用 logger.warn

您可以将记录器的级别设置为 1,而不是将记录器设置为 nil

ActiveRecord::Base.logger.level = 1 # or Logger::INFO

由于将记录器设置为nil有时会引发错误,所以当我尝试运行“rake db:migrate”时,我遇到了这个问题。http://stackoverflow.com/questions/1719212/undefined-method-info-for-nilnilclass-when-running-active-record-migration - abbood
3
在初始化程序中确认这在Rails 4.1.0中可行。 - Amal Chaudhuri
10个回答

373

关闭它的方法:

old_logger = ActiveRecord::Base.logger
ActiveRecord::Base.logger = nil
要重新打开它:
ActiveRecord::Base.logger = old_logger

1
有没有任何地方可以永久禁用 SQL 输出?我尝试将其添加到 envs/dev.rb,但没有成功。 - samvermette
7
你可以将这段代码放在 .irbrc 文件中,这个文件类似于 Rails console 的 .bashrc 文件。实际上,如果你想,你几乎可以在 .irbrc 文件中进行任何操作,例如语法高亮、历史记录、在 vi 编辑代码并在 Rails console 中执行等等。如果你使用的是 Ruby 1.8 版本,可以查看我的 gem utility_belt,如果使用的是 Ruby 1.9 版本,则可以查看名为 flyrb 的端口。 - Giles Bowkett
2
@giles bowkett:实际上,.irbrc就像是 .bashrc,但是它是为你的_ruby_交互式命令行而设计的。这不是一个rails的东西。我想如果你在rails环境之外运行irb并尝试引用rails类,你可能会遇到错误。 - eremzeit
9
@samvermette 你可以在配置文件中设置。例如:config/initializers/activerecord_logger.rb - Uri
22
如果您使用.info等其他方法,ActiveRecord::Base.logger.level = 1是更好的选择,因为它不会引发异常。 - Dirty Henry
显示剩余6条评论

96

这可能不是控制台的适当解决方案,但Rails有一个可以解决此问题的方法:Logger#silence

ActiveRecord::Base.logger.silence do
  # the stuff you want to be silenced
end

4
只能在Rails 3及以下版本中使用:"警告:silence已被弃用并将在Rails 4.0中被移除" - Kangur
7
@Kangur 我使用的是 Rails 4.2 版本,似乎静音功能正常运行。 - Benjamin Crouzier
3
我可以证实这种方法在Rails 4.2上也完全可行。 - seymore_strongboy
7
在Rails 5中运行,我没有看到任何警告。在我看来,这是最好的答案。 - Overload119
这个不再起作用了(未定义的静默)。Rails 5.2.2。 - Christopher Milne
4
在Rails 6中运行良好。也许只是把它移动了一下? - johncip

82

以下是我认为比较简洁的一个变体,仍然允许AR进行其他潜在的日志记录。在config/environments/development.rb文件中:

config.after_initialize do
  ActiveRecord::Base.logger = Rails.logger.clone
  ActiveRecord::Base.logger.level = Logger::INFO
end

在Rails 3.0或3.1中,我遇到了一些奇怪的问题。在after_initialize块中,为什么Rails.logger会为空?你是否有做过其他自定义的Rails初始化堆栈,或者可能忘记了使用config.after_initialize - jrochkind
1
在我的Rails 3.1应用程序中运行得非常好。看起来是最好的解决方案。+1 - Martijn
对我不起作用...在after_initialize块中设置级别是可以的,但是当控制台打开时级别又回到了0。奇怪。(我正在使用Pry作为控制台替代品,这是为什么?) - Mike Blyth

27

对于Rails 4,您可以将以下内容放入环境文件中:

# /config/environments/development.rb

config.active_record.logger = nil

那只有在生产环境中才会生效,而在那里日志记录通常被压制了... - Rob
在Rails 5中,这个不起作用。如果您在Linux环境下工作,则以下内容将起作用:config.active_record.logger = Logger.new('/dev/null')。不确定是否适用于更新的版本,如6和7。 - nadavgam

16

如果有人希望实际上关闭SQL语句记录(而不更改日志级别,同时保持其AR模型的记录),则可以执行以下操作:

在Rails 3.2.16中写入日志的行是调用lib/active_record/log_subscriber.rb:50中的debug方法。

debug方法由ActiveSupport::LogSubscriber 定义。

因此,我们可以通过覆盖它来关闭日志记录,如下所示:

module ActiveSupport
  class LogSubscriber
    def debug(*args, &block)
    end
  end
end

2
不错。这可以在记录 SQL 时不影响 Rails.logger.debug 语句的工作。 - Teemu Leisti
完全是新手。我们应该把这个放在哪里? - devius
我将其保存在lib/monkeypatch.rb中,并使用以下行在config/application.rb中让rails引入它:Dir.glob( "./lib/*.{rb}" ).each{ | file | require file }。请记住,一些人不赞成猴子补丁技术。也许不应该将其检入您的生产代码。 - fakeleft
我将其作为我的Rails / ActiveRecord 6解决方案的起点,并将其添加为答案。这个版本不太起作用,因为它实际上抑制了我想看到的很多其他日志。 - Chris R

11
我用了这个:config.log_level = :info,编辑在config/environments/performance.rb中。
对我非常有用,它能够拒绝 SQL 输出,并只显示渲染和重要信息。

我使用的是Rails 4.1.0版本,一直很稳定。谢谢。 - Zakaria
谢谢您提到这个问题,如果设置config.log_level = :fatal,它基本上会完全禁用对生产日志文件的输出,这正是我需要的,因为有一个自定义请求记录器在运行。 - Lev Lukomsky

4
在Rails 3.2中,我在config/environment/development.rb中执行类似以下的操作:
module MyApp
  class Application < Rails::Application
    console do
      ActiveRecord::Base.logger = Logger.new( Rails.root.join("log", "development.log") )
    end
  end
end

4
只是提醒一下,在Rails 2中,你可以这样做:
ActiveRecord::Base.silence { <code you don't want to log goes here> }

显然,如果需要,花括号可以用 do end 块来替换。

3
我使用 activerecord 6.0.3.3,并且我需要包含 ActiveSupport::LoggerSilence
include ActiveSupport::LoggerSilence

ActiveSupport::LoggerSilence.silence do
    ## everything you want to silence
end

然而,对于任何与创建或删除 SQL 表相关的操作,例如ActiveRecord::Migration.drop_table,这种方法都不起作用。为了使其静音,我添加了以下代码:

ActiveRecord::Schema.verbose = false

2

我不得不为ActiveRecord 6解决这个问题,我的答案基于fakeleft的回答,但它并不完全正确,因为它会抑制其他日志记录,如嵌套视图的日志记录。我所做的是创建了config/initializers/activerecord_logger.rb

# Suppress SQL statement logging if necessary
# This is a dirty, dirty trick, but it works:
if ENV["ACTIVERECORD_HIDE_SQL"].present?
  module ActiveRecord
    class LogSubscriber
      def sql(event)
      end
    end
  end
end

AR 6中的日志订阅者有一个“sql”事件,我们希望隐藏它,因此这个目标非常狭窄,只是跳过那个事件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接