Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional MongoSilencer plugin #89

Merged
merged 3 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ Metrics:
Metrics/LineLength:
Max: 512

Style/BracesAroundHashParameters:
Enabled: false

Style/Documentation:
Enabled: false

Style/GlobalVars:
Exclude:
- spec/**/*

inherit_from: .rubocop_todo.yml
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 3.0.1

* Your contribution here.
* [#89](https://github.com/collectiveidea/delayed_job_mongoid/pull/89): Add MongoSilencer plugin to silence Delayed Job polling - [johnnyshields](https://github.com/johnnyshields).
* [#88](https://github.com/collectiveidea/delayed_job_mongoid/pull/88): Extract out mixin to enable better backend customization - [johnnyshields](https://github.com/johnnyshields).

### 3.0.0
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ That's it. Use [delayed_job](http://github.com/collectiveidea/delayed_job) as no

## Advanced Usage

### Silencing Noisy Logging

By default, the Mongo Ruby Driver will print log lines every
5 seconds as Delayed Job polls your database. Use the following
plugin to silence logs which happen while polling (except `error`
level) and only log operations which happen during job execution.

```ruby
# in initializers/delayed_job.rb

require 'delayed/plugins/mongo_silencer'
Delayed::Worker.plugins << Delayed::Plugins::MongoSilencer
```

To ensure thread safety, this plugin requires your `Mongo::Logger.logger`
to be an instance of `ActiveSupport::Logger` class. It will ignore instances
of the Ruby standard library `Logger` class.

### Customizing Job Class

Delayed Job allows specifying a custom backend class for jobs.
Expand Down
49 changes: 49 additions & 0 deletions lib/delayed/plugins/mongo_silencer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'mongo'
require 'delayed/plugin'

module Delayed
module Plugins
# Silences the Mongo logger except when performing jobs.
# Requires the Mongoid/Mongo loggers to be instances of ActiveSupport::Logger.
class MongoSilencer < Delayed::Plugin
callbacks do |lifecycle|
lifecycle.before(:execute) do |*_args|
store_log_level
silence!
end

# As of Delayed Job 4.10, the :perform hook includes the
# operations for job deletion and job errors, so these will
# still appear in the log.
lifecycle.around(:perform) do |*_args, &block|
begin
unsilence!
block.call
ensure
silence!
end
end
end

class << self
def store_log_level
@mongo_log_level = Mongo::Logger.logger.level if mongo_logger?
end

def silence!
Mongo::Logger.logger.local_level = Logger::WARN if @mongo_log_level && mongo_logger?
end

def unsilence!
Mongo::Logger.logger.local_level = @mongo_log_level if @mongo_log_level && mongo_logger?
end

private

def mongo_logger?
Mongo::Logger.logger && Mongo::Logger.logger.respond_to?(:local_level)
end
end
end
end
end
4 changes: 1 addition & 3 deletions spec/delayed_job_mongoid_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
require 'helper'
require 'models/story'
require 'models/story_wrapper_job'
require 'spec_helper'

describe Delayed::Backend::Mongoid::Job do
it_behaves_like 'a delayed_job backend'
Expand Down
3 changes: 3 additions & 0 deletions spec/models/story_wrapper_job.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class StoryWrapperJob < SimpleJob
# TODO: remove this line when https://github.com/collectiveidea/delayed_job/pull/1166 is merged
@@runs = 0

def initialize
@story = Story.create!(text: 'My great story')
@story_again = @story
Expand Down
63 changes: 63 additions & 0 deletions spec/mongo_silencer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'spec_helper'

describe Delayed::Plugins::MongoSilencer do
let(:mongoid_io) { StringIO.new }
let(:mongoid_logger) { ActiveSupport::Logger.new(mongoid_io) }
let(:mongo_io) { StringIO.new }
let(:mongo_logger) { ActiveSupport::Logger.new(mongo_io) }
let(:run_worker) do
worker = Delayed::Worker.new
thread = Thread.new { worker.start }
sleep(0.5)
worker.stop
thread.join
end

before do
Delayed::Job.create(payload_object: StoryWrapperJob.new)
Mongoid.logger = mongoid_logger
Mongo::Logger.logger = mongo_logger
Delayed::Worker.sleep_delay = 0.1
end

after do
Delayed::Worker.reset
Delayed::Worker.plugins = []
Mongoid.logger = $mongoid_logger
Mongo::Logger.logger = $mongo_logger
end

context 'when plugin is set' do
before do
Delayed::Worker.plugins << described_class
end

context 'when using ActiveSupport::Logger' do
it do
run_worker
expect(mongoid_io.string.lines.size).to eq 0
expect(mongo_io.string.lines.any? { |l| l.include?('"find"=>"stories"') }).to eq true
expect(mongo_io.string.lines.any? { |l| l.include?('"findAndModify"=>"delayed_backend_mongoid_jobs"') }).to eq false
end
end

context 'when Mongo logger is a Logger' do
let(:mongo_logger) { Logger.new(mongo_io) }

it do
run_worker
expect(mongo_io.string.lines.any? { |l| l.include?('"find"=>"stories"') }).to eq true
expect(mongo_io.string.lines.any? { |l| l.include?('"findAndModify"=>"delayed_backend_mongoid_jobs"') }).to eq true
end
end
end

context 'when plugin is not set' do
it do
run_worker
expect(mongoid_io.string.lines.size).to eq 0
expect(mongo_io.string.lines.any? { |l| l.include?('"find"=>"stories"') }).to eq true
expect(mongo_io.string.lines.any? { |l| l.include?('"findAndModify"=>"delayed_backend_mongoid_jobs"') }).to eq true
end
end
end
6 changes: 6 additions & 0 deletions spec/helper.rb → spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@

require 'rspec'
require 'delayed_job_mongoid'
require 'delayed/plugins/mongo_silencer'
require 'delayed/backend/shared_spec'
require 'models/story'
require 'models/story_wrapper_job'

$mongoid_logger = Mongoid.logger
$mongo_logger = Mongo::Logger.logger

RSpec.configure do |config|
config.expect_with(:rspec) do |c|
Expand Down