16

I'm using Rails' ActiveJob, and one of my jobs take a raw email as input. When debugging, this can result in a huge amount of noise in my application log. How can I avoid that?

[ActiveJob] Enqueued EmailParserJob (Job ID: 9678f343-c876-4f9f-9cc7-db440634e178) to DelayedJob(default) with arguments: "NOISE"
Jeppe Liisberg
  • 3,734
  • 3
  • 25
  • 24

7 Answers7

7

See https://github.com/rails/rails/blob/4-2-stable/activejob/lib/active_job/logging.rb#L10

ActiveJob::Base.logger = Logger.new(nil)
Mihai Târnovan
  • 652
  • 8
  • 12
  • @DenisTataurov That can potentially lead to problems if some code expects `ActiveJob::Base.logger` to quack like a `Logger` without checking for `nil`. – Mihai Târnovan Jul 24 '18 at 12:47
  • 1
    This works well, add it inside your own subclass of ActiveJob, like: self.logger = Logger.new(nil) if Rails.env.test? – Algorini Apr 23 '20 at 20:11
  • I ended up combining this with another answer and use this in a particular job to disable logging: `self.logger = Logger.new(IO::NULL) unless ENV['ENABLE_UPDATE_ONLINE_STATUS_LOGS'] == true` – FireDragon Mar 17 '21 at 23:27
6

One thing that may be useful to note here: In any instance of a class that is subclassed from (Rails 5.1) ActiveJob::Base (or, any class instance called by a class subclassed from ActiveJob::Base) The normal Rails.logger.info('log this') commands are going to get logged to the rails console (presumably via STDOUT).

I haven't quite figured out the mechanism that causes this hijacking of Rails.logger, but you can switch to ActiveJob::Base.logger and use the knowledge of this: (https://github.com/rails/rails/blob/b205ea2dc6c70b2b8e2134640e3056ed33fdc6be/activejob/lib/active_job/logging.rb#L13) to change the behavior as you wish.

So, this allows you to log as you want:

1) Include require "active_job/logging" in your application.rb

2) In config/development.rb (or whatever environments you want) include this line:

config.active_job.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new("log/#{Rails.env}.log"))

3) Any logging inside of subclasses of ActiveJob, use this for logging:

ActiveJob::Base.logger.info('(MyJob) Inside of a job but not going to STDOUT')

If anyone can point out the code that explains why Rails.logger.info behaves differently when inside of an ActiveJob class that would be some good reading.

Dave Collins
  • 1,077
  • 1
  • 15
  • 23
5

It seems the only way is to override ActiveJob's internal logging method:

class ActiveJob::Logging::LogSubscriber
  private def args_info(job)
    ''
  end
end

Put it somewhere into app/initializers/active_job_logger_patch.rb.

EugZol
  • 6,476
  • 22
  • 41
  • 1
    This did end up working for me, but I had to add this to my initializer in Rails 5.0.2: `require 'active_job/logging'` – rbhitchcock Apr 25 '17 at 17:02
4

I used after_initialize to hook beforehand. It turned out to work only in perform_start method but not enqueue.
Using on_load method to hook works. I think it's the lazyload feature in Rails causing the class to be loaded after the override.

ActiveSupport.on_load :active_job do
  class ActiveJob::Logging::LogSubscriber
    private def args_info(job)
      # override this method to filter arguments shown in app log
    end
  end
end
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
atitan
  • 123
  • 5
4

From Rails 6.1, you can turn off the logging with log_arguments like the below. This will turn off logging the arguments for all the jobs derived from ApplicationJob, You can also set it on per job basis.

class ApplicationJob < ActiveJob::Base
  self.log_arguments = false
end

Reference:

https://github.com/rails/rails/pull/37660

user11350468
  • 1,357
  • 1
  • 6
  • 22
2

It looks like they added the feature Add an option to disable logging for jobs with sensitive arguments in Rail 6. This would prevent any arguments from appearing in the log lines.

Edit: To use this with ActionMailer, using a custom mailer job might work, haven't tested this myself yet.

David Basalla
  • 2,996
  • 3
  • 18
  • 22
1

Found the following recommendation here:

ActiveJob::Base.logger = Logger.new(IO::NULL)

Seems to be better than passing a nil

inem
  • 96
  • 5