loga 2.4.0 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +12 -0
- data/Appraisals +19 -7
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/gemfiles/rails60.gemfile +11 -0
- data/gemfiles/sidekiq51.gemfile +1 -1
- data/gemfiles/sidekiq6.gemfile +11 -0
- data/gemfiles/sinatra14.gemfile +1 -1
- data/gemfiles/unit.gemfile +1 -1
- data/lib/loga/configuration.rb +1 -0
- data/lib/loga/formatters/gelf_formatter.rb +16 -1
- data/lib/loga/rack/logger.rb +31 -41
- data/lib/loga/railtie.rb +1 -1
- data/lib/loga/sidekiq.rb +13 -5
- data/lib/loga/{sidekiq → sidekiq5}/job_logger.rb +1 -3
- data/lib/loga/sidekiq6/job_logger.rb +50 -0
- data/lib/loga/version.rb +1 -1
- data/loga.gemspec +1 -1
- data/spec/fixtures/rails60.rb +80 -0
- data/spec/integration/sidekiq5_spec.rb +143 -0
- data/spec/integration/sidekiq6_spec.rb +164 -0
- data/spec/integration/sinatra_spec.rb +1 -1
- data/spec/loga/{sidekiq → sidekiq5}/job_logger_spec.rb +2 -1
- data/spec/loga/sidekiq6/job_logger_spec.rb +121 -0
- data/spec/loga/sidekiq_spec.rb +10 -3
- data/spec/spec_helper.rb +17 -8
- data/spec/unit/loga/formatters/gelf_formatter_spec.rb +43 -0
- data/spec/unit/loga/rack/logger_spec.rb +58 -37
- metadata +18 -9
- data/spec/integration/sidekiq_spec.rb +0 -147
data/lib/loga/version.rb
CHANGED
data/loga.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency 'rack'
|
23
23
|
|
24
24
|
spec.add_development_dependency 'appraisal', '~> 2.2.0'
|
25
|
-
spec.add_development_dependency 'bundler', '
|
25
|
+
spec.add_development_dependency 'bundler', '>= 1.6'
|
26
26
|
spec.add_development_dependency 'byebug'
|
27
27
|
spec.add_development_dependency 'guard', '~> 2.13'
|
28
28
|
spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'action_controller/railtie'
|
2
|
+
require 'action_mailer/railtie'
|
3
|
+
|
4
|
+
Bundler.require(*Rails.groups)
|
5
|
+
|
6
|
+
STREAM = StringIO.new unless defined?(STREAM)
|
7
|
+
|
8
|
+
class Dummy < Rails::Application
|
9
|
+
config.eager_load = true
|
10
|
+
config.filter_parameters += [:password]
|
11
|
+
config.secret_key_base = '2624599ca9ab3cf3823626240138a128118a87683bf03ab8f155844c33b3cd8cbbfa3ef5e29db6f5bd182f8bd4776209d9577cfb46ac51bfd232b00ab0136b24'
|
12
|
+
config.session_store :cookie_store, key: '_rails60_session'
|
13
|
+
|
14
|
+
config.log_tags = [:uuid, 'TEST_TAG']
|
15
|
+
config.loga = {
|
16
|
+
device: STREAM,
|
17
|
+
host: 'bird.example.com',
|
18
|
+
service_name: 'hello_world_app',
|
19
|
+
service_version: '1.0',
|
20
|
+
}
|
21
|
+
config.action_mailer.delivery_method = :test
|
22
|
+
end
|
23
|
+
|
24
|
+
class ApplicationController < ActionController::Base
|
25
|
+
include Rails.application.routes.url_helpers
|
26
|
+
protect_from_forgery with: :null_session
|
27
|
+
|
28
|
+
def ok
|
29
|
+
render plain: 'Hello Rails'
|
30
|
+
end
|
31
|
+
|
32
|
+
def error
|
33
|
+
nil.name
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
render json: params
|
38
|
+
end
|
39
|
+
|
40
|
+
def create
|
41
|
+
render json: params
|
42
|
+
end
|
43
|
+
|
44
|
+
def new
|
45
|
+
redirect_to :ok
|
46
|
+
end
|
47
|
+
|
48
|
+
def update
|
49
|
+
@id = params[:id]
|
50
|
+
render '/user'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class FakeMailer < ActionMailer::Base
|
55
|
+
default from: 'notifications@example.com'
|
56
|
+
|
57
|
+
def self.send_email
|
58
|
+
basic_mail.deliver_now
|
59
|
+
end
|
60
|
+
|
61
|
+
def basic_mail
|
62
|
+
mail(
|
63
|
+
to: 'user@example.com',
|
64
|
+
subject: 'Welcome to My Awesome Site',
|
65
|
+
body: 'Banana muffin',
|
66
|
+
content_type: 'text/html',
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Dummy.routes.append do
|
72
|
+
get 'ok' => 'application#ok'
|
73
|
+
get 'error' => 'application#error'
|
74
|
+
get 'show' => 'application#show'
|
75
|
+
post 'users' => 'application#create'
|
76
|
+
get 'new' => 'application#new'
|
77
|
+
put 'users/:id' => 'application#update'
|
78
|
+
end
|
79
|
+
|
80
|
+
Dummy.initialize!
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
require 'fakeredis'
|
4
|
+
|
5
|
+
dummy_redis_config = ConnectionPool.new(size: 5) { Redis.new }
|
6
|
+
|
7
|
+
Sidekiq.configure_client do |config|
|
8
|
+
config.redis = dummy_redis_config
|
9
|
+
end
|
10
|
+
|
11
|
+
Sidekiq.configure_server do |config|
|
12
|
+
config.redis = dummy_redis_config
|
13
|
+
end
|
14
|
+
|
15
|
+
class MySidekiqWorker
|
16
|
+
include Sidekiq::Worker
|
17
|
+
|
18
|
+
def perform(_name); end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'Sidekiq client logger' do
|
22
|
+
let(:mgr) do
|
23
|
+
Class.new do
|
24
|
+
attr_reader :latest_error, :mutex, :cond
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@mutex = ::Mutex.new
|
28
|
+
@cond = ::ConditionVariable.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def processor_died(_inst, err)
|
32
|
+
@latest_error = err
|
33
|
+
|
34
|
+
@mutex.synchronize { @cond.signal }
|
35
|
+
end
|
36
|
+
|
37
|
+
def processor_stopped(_inst)
|
38
|
+
@mutex.synchronize { @cond.signal }
|
39
|
+
end
|
40
|
+
|
41
|
+
def options
|
42
|
+
{
|
43
|
+
concurrency: 3,
|
44
|
+
queues: ['default'],
|
45
|
+
job_logger: Loga::Sidekiq5::JobLogger,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:target) { StringIO.new }
|
52
|
+
|
53
|
+
def read_json_log(line:)
|
54
|
+
target.rewind
|
55
|
+
JSON.parse(target.each_line.drop(line - 1).first)
|
56
|
+
end
|
57
|
+
|
58
|
+
before do
|
59
|
+
Redis.current.flushall
|
60
|
+
|
61
|
+
Loga.reset
|
62
|
+
|
63
|
+
Loga.configure(
|
64
|
+
service_name: 'hello_world_app',
|
65
|
+
service_version: '1.0',
|
66
|
+
device: target,
|
67
|
+
format: :gelf,
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'has the proper job logger' do
|
72
|
+
expect(Sidekiq.options[:job_logger]).to eq Loga::Sidekiq5::JobLogger
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'has the proper logger for Sidekiq.logger' do
|
76
|
+
expect(Sidekiq.logger).to eq Loga.logger
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'pushes a new element in the default queue' do
|
80
|
+
MySidekiqWorker.perform_async('Bob')
|
81
|
+
|
82
|
+
last_element = JSON.parse(Redis.current.lpop('queue:default'))
|
83
|
+
|
84
|
+
aggregate_failures do
|
85
|
+
expect(last_element['class']).to eq 'MySidekiqWorker'
|
86
|
+
expect(last_element['args']).to eq ['Bob']
|
87
|
+
expect(last_element['retry']).to eq true
|
88
|
+
expect(last_element['queue']).to eq 'default'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'has the proper logger Sidekiq::Logging.logger' do
|
93
|
+
expect(Sidekiq::Logging.logger).to eq Loga.logger
|
94
|
+
end
|
95
|
+
|
96
|
+
# https://github.com/mperham/sidekiq/blob/97363210b47a4f8a1d8c1233aaa059d6643f5040/test/test_actors.rb#L57-L79
|
97
|
+
|
98
|
+
it 'logs the job processing event' do
|
99
|
+
MySidekiqWorker.perform_async('Bob')
|
100
|
+
|
101
|
+
require 'sidekiq/processor'
|
102
|
+
|
103
|
+
Sidekiq::Processor.new(mgr.new).start
|
104
|
+
sleep 0.5
|
105
|
+
|
106
|
+
json_line = read_json_log(line: 1)
|
107
|
+
|
108
|
+
aggregate_failures do
|
109
|
+
expect(json_line).to include(
|
110
|
+
'_queue'=> 'default',
|
111
|
+
'_retry'=> true,
|
112
|
+
'_params'=> ['Bob'],
|
113
|
+
'_class'=> 'MySidekiqWorker',
|
114
|
+
'_type'=> 'sidekiq',
|
115
|
+
'_service.name'=> 'hello_world_app',
|
116
|
+
'_service.version'=> '1.0',
|
117
|
+
'_tags'=> '',
|
118
|
+
'level'=> 6,
|
119
|
+
'version'=> '1.1',
|
120
|
+
)
|
121
|
+
|
122
|
+
%w[_created_at _enqueued_at _jid _duration timestamp host].each do |key|
|
123
|
+
expect(json_line).to have_key(key)
|
124
|
+
end
|
125
|
+
|
126
|
+
expect(json_line['short_message']).to match(/MySidekiqWorker with jid:*/)
|
127
|
+
end
|
128
|
+
|
129
|
+
# This was a bug - the duration was constantly incresing based on when
|
130
|
+
# the logger was created. https://github.com/FundingCircle/loga/pull/117
|
131
|
+
#
|
132
|
+
# Test that after sleeping for few seconds the duration is still under 500ms
|
133
|
+
sleep 1
|
134
|
+
|
135
|
+
MySidekiqWorker.perform_async('Bob')
|
136
|
+
|
137
|
+
sleep 1
|
138
|
+
|
139
|
+
json_line = read_json_log(line: 2)
|
140
|
+
|
141
|
+
expect(json_line['_duration']).to be < 500
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
require 'fakeredis'
|
4
|
+
|
5
|
+
dummy_redis_config = ConnectionPool.new(size: 5) { Redis.new }
|
6
|
+
|
7
|
+
Sidekiq.configure_client do |config|
|
8
|
+
config.redis = dummy_redis_config
|
9
|
+
end
|
10
|
+
|
11
|
+
Sidekiq.configure_server do |config|
|
12
|
+
config.redis = dummy_redis_config
|
13
|
+
end
|
14
|
+
|
15
|
+
class MySidekiqWorker
|
16
|
+
include Sidekiq::Worker
|
17
|
+
|
18
|
+
def perform(_name)
|
19
|
+
logger.info('Hello from MySidekiqWorker')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'Sidekiq client logger' do
|
24
|
+
let(:mgr) do
|
25
|
+
# https://github.com/mperham/sidekiq/blob/v6.1.2/test/test_actors.rb#L58-L82
|
26
|
+
Class.new do
|
27
|
+
attr_reader :latest_error, :mutex, :cond
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@mutex = ::Mutex.new
|
31
|
+
@cond = ::ConditionVariable.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def processor_died(_inst, err)
|
35
|
+
@latest_error = err
|
36
|
+
|
37
|
+
@mutex.synchronize { @cond.signal }
|
38
|
+
end
|
39
|
+
|
40
|
+
def processor_stopped(_inst)
|
41
|
+
@mutex.synchronize { @cond.signal }
|
42
|
+
end
|
43
|
+
|
44
|
+
def options
|
45
|
+
{
|
46
|
+
concurrency: 3,
|
47
|
+
queues: ['default'],
|
48
|
+
job_logger: Loga::Sidekiq6::JobLogger,
|
49
|
+
}.tap { |opts| opts[:fetch] = ::Sidekiq::BasicFetch.new(opts) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:target) { StringIO.new }
|
55
|
+
|
56
|
+
def read_json_log(line:)
|
57
|
+
target.rewind
|
58
|
+
JSON.parse(target.each_line.drop(line - 1).first)
|
59
|
+
end
|
60
|
+
|
61
|
+
before do
|
62
|
+
Redis.current.flushall
|
63
|
+
|
64
|
+
Loga.reset
|
65
|
+
|
66
|
+
Loga.configure(
|
67
|
+
service_name: 'hello_world_app',
|
68
|
+
service_version: '1.0',
|
69
|
+
device: target,
|
70
|
+
format: :gelf,
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'has the proper job logger' do
|
75
|
+
expect(Sidekiq.options[:job_logger]).to eq Loga::Sidekiq6::JobLogger
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'has the proper logger for Sidekiq.logger' do
|
79
|
+
expect(Sidekiq.logger).to eq Loga.logger
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'pushes a new element in the default queue' do
|
83
|
+
MySidekiqWorker.perform_async('Bob')
|
84
|
+
|
85
|
+
last_element = JSON.parse(Redis.current.lpop('queue:default'))
|
86
|
+
|
87
|
+
aggregate_failures do
|
88
|
+
expect(last_element['class']).to eq 'MySidekiqWorker'
|
89
|
+
expect(last_element['args']).to eq ['Bob']
|
90
|
+
expect(last_element['retry']).to eq true
|
91
|
+
expect(last_element['queue']).to eq 'default'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_log_from_worker(json_line)
|
96
|
+
aggregate_failures do
|
97
|
+
expect(json_line).to include(
|
98
|
+
'_class' => 'MySidekiqWorker',
|
99
|
+
'_service.name' => 'hello_world_app',
|
100
|
+
'_service.version' => '1.0',
|
101
|
+
'_tags' => '',
|
102
|
+
'level' => 6,
|
103
|
+
'version' => '1.1',
|
104
|
+
'short_message' => 'Hello from MySidekiqWorker',
|
105
|
+
)
|
106
|
+
|
107
|
+
%w[_jid timestamp host].each do |key|
|
108
|
+
expect(json_line).to have_key(key)
|
109
|
+
end
|
110
|
+
|
111
|
+
expect(json_line).not_to include('_duration')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_job_end_log(json_line) # rubocop:disable Metrics/MethodLength
|
116
|
+
aggregate_failures do
|
117
|
+
expect(json_line).to include(
|
118
|
+
'_queue' => 'default',
|
119
|
+
'_retry' => true,
|
120
|
+
'_params' => ['Bob'],
|
121
|
+
'_class' => 'MySidekiqWorker',
|
122
|
+
'_type' => 'sidekiq',
|
123
|
+
'_service.name' => 'hello_world_app',
|
124
|
+
'_service.version' => '1.0',
|
125
|
+
'_tags' => '',
|
126
|
+
'level' => 6,
|
127
|
+
'version' => '1.1',
|
128
|
+
)
|
129
|
+
|
130
|
+
%w[_created_at _enqueued_at _jid _duration timestamp host].each do |key|
|
131
|
+
expect(json_line).to have_key(key)
|
132
|
+
end
|
133
|
+
|
134
|
+
expect(json_line['_duration']).to be < 500
|
135
|
+
expect(json_line['short_message']).to match(/MySidekiqWorker with jid:*/)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'logs the job processing event' do
|
140
|
+
MySidekiqWorker.perform_async('Bob')
|
141
|
+
|
142
|
+
require 'sidekiq/processor'
|
143
|
+
|
144
|
+
sidekiq_manager = mgr.new
|
145
|
+
Sidekiq::Processor.new(sidekiq_manager, sidekiq_manager.options).start
|
146
|
+
sleep 0.5
|
147
|
+
|
148
|
+
test_log_from_worker(read_json_log(line: 1))
|
149
|
+
test_job_end_log(read_json_log(line: 2))
|
150
|
+
|
151
|
+
# This was a bug - the duration was constantly incresing based on when
|
152
|
+
# the logger was created. https://github.com/FundingCircle/loga/pull/117
|
153
|
+
#
|
154
|
+
# Test that after sleeping for few seconds the duration is still under 500ms
|
155
|
+
sleep 1
|
156
|
+
|
157
|
+
MySidekiqWorker.perform_async('Bob')
|
158
|
+
|
159
|
+
sleep 1
|
160
|
+
|
161
|
+
test_log_from_worker(read_json_log(line: 3))
|
162
|
+
test_job_end_log(read_json_log(line: 4))
|
163
|
+
end
|
164
|
+
end
|
@@ -68,7 +68,6 @@ RSpec.describe 'Structured logging with Sinatra', :with_hostname, :timecop do
|
|
68
68
|
end
|
69
69
|
let(:data) do
|
70
70
|
{
|
71
|
-
'status' => 200,
|
72
71
|
'method' => 'GET',
|
73
72
|
'path' => '/ok',
|
74
73
|
'params' => { 'username'=>'yoshi' },
|
@@ -76,6 +75,7 @@ RSpec.describe 'Structured logging with Sinatra', :with_hostname, :timecop do
|
|
76
75
|
'request_ip' => '127.0.0.1',
|
77
76
|
'user_agent' => nil,
|
78
77
|
'duration' => 0,
|
78
|
+
'status' => 200,
|
79
79
|
}
|
80
80
|
end
|
81
81
|
let(:data_as_text) { "data=#{{ request: data }.inspect}" }
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'loga/sidekiq6/job_logger'
|
3
|
+
|
4
|
+
RSpec.describe Loga::Sidekiq6::JobLogger do
|
5
|
+
subject(:job_logger) { described_class.new }
|
6
|
+
|
7
|
+
let(:target) { StringIO.new }
|
8
|
+
|
9
|
+
let(:json_line) do
|
10
|
+
target.rewind
|
11
|
+
JSON.parse(target.read.split("\n").last)
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
Loga.reset
|
16
|
+
|
17
|
+
Loga.configure(
|
18
|
+
service_name: 'hello_world_app',
|
19
|
+
service_version: '1.0',
|
20
|
+
device: target,
|
21
|
+
format: :gelf,
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
# https://github.com/mperham/sidekiq/blob/v6.1.2/lib/sidekiq/job_logger.rb
|
26
|
+
it 'inherits from ::Sidekiq::JobLogger' do
|
27
|
+
expect(subject).to be_a(::Sidekiq::JobLogger)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#call' do
|
31
|
+
context 'when the job passess successfully' do
|
32
|
+
let(:item_data) do
|
33
|
+
{
|
34
|
+
'class' => 'HardWorker',
|
35
|
+
'args' => ['asd'],
|
36
|
+
'retry' => true,
|
37
|
+
'queue' => 'default',
|
38
|
+
'jid' => '591f6f66ee0d218fb451dfb6',
|
39
|
+
'created_at' => 1_528_799_582.904939,
|
40
|
+
'enqueued_at' => 1_528_799_582.9049861,
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'has the the required attributes on call' do
|
45
|
+
job_logger.call(item_data, 'queue') do
|
46
|
+
# something
|
47
|
+
end
|
48
|
+
|
49
|
+
expected_body = {
|
50
|
+
'version' => '1.1',
|
51
|
+
'level' => 6,
|
52
|
+
'_type' => 'sidekiq',
|
53
|
+
'_created_at' => 1_528_799_582.904939,
|
54
|
+
'_enqueued_at' => 1_528_799_582.9049861,
|
55
|
+
'_jid' => '591f6f66ee0d218fb451dfb6',
|
56
|
+
'_retry' => true,
|
57
|
+
'_queue' => 'default',
|
58
|
+
'_service.name' => 'hello_world_app',
|
59
|
+
'_class' => 'HardWorker',
|
60
|
+
'_service.version' => '1.0',
|
61
|
+
'_tags' => '',
|
62
|
+
'_params' => ['asd'],
|
63
|
+
}
|
64
|
+
|
65
|
+
aggregate_failures do
|
66
|
+
expect(json_line).to include(expected_body)
|
67
|
+
expect(json_line['timestamp']).to be_a(Float)
|
68
|
+
expect(json_line['host']).to be_a(String)
|
69
|
+
expect(json_line['short_message']).to match(/HardWorker with jid:*/)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when the job fails' do
|
75
|
+
let(:item_data) do
|
76
|
+
{
|
77
|
+
'class' => 'HardWorker',
|
78
|
+
'args' => ['asd'],
|
79
|
+
'retry' => true,
|
80
|
+
'queue' => 'default',
|
81
|
+
'jid' => '591f6f66ee0d218fb451dfb6',
|
82
|
+
'created_at' => 1_528_799_582.904939,
|
83
|
+
'enqueued_at' => 1_528_799_582.9049861,
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'has the the required attributes on call' do
|
88
|
+
failed_job = lambda do
|
89
|
+
job_logger.call(item_data, 'queue') do
|
90
|
+
raise StandardError
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
expected_body = {
|
95
|
+
'version' => '1.1',
|
96
|
+
'level' => 4,
|
97
|
+
'_type' => 'sidekiq',
|
98
|
+
'_created_at' => 1_528_799_582.904939,
|
99
|
+
'_enqueued_at' => 1_528_799_582.9049861,
|
100
|
+
'_jid' => '591f6f66ee0d218fb451dfb6',
|
101
|
+
'_retry' => true,
|
102
|
+
'_queue' => 'default',
|
103
|
+
'_service.name' => 'hello_world_app',
|
104
|
+
'_class' => 'HardWorker',
|
105
|
+
'_service.version' => '1.0',
|
106
|
+
'_tags' => '',
|
107
|
+
'_params' => ['asd'],
|
108
|
+
'_exception' => 'StandardError',
|
109
|
+
}
|
110
|
+
|
111
|
+
aggregate_failures do
|
112
|
+
expect(&failed_job).to raise_error(StandardError)
|
113
|
+
expect(json_line).to include(expected_body)
|
114
|
+
expect(json_line['timestamp']).to be_a(Float)
|
115
|
+
expect(json_line['host']).to be_a(String)
|
116
|
+
expect(json_line['short_message']).to match(/HardWorker with jid:*/)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|