dispatch-rider 1.6.1 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20ecab8e18af62e4795b431f0860148f5929277c
4
- data.tar.gz: b87e0c608b4ee99a1e85279bf9d42afc5b4e8b53
3
+ metadata.gz: 697069b0aff03bae879decd081323fe5c90441b1
4
+ data.tar.gz: 25ae5e9c896c920864800e9dea6e7421cafe3aee
5
5
  SHA512:
6
- metadata.gz: 9e645f3c4257d14f8d17e1402ec5ef73ceee737b380ffa531391a010ad28e11fba30baa806af34d1d21f518583fd6bc44651fc65e5bc36a7f698f50c4edc1158
7
- data.tar.gz: 8aa77e404a4caa1680def056db848c6c124c1e1ee935278770b9a35c8e278100a23c5b347b80c2bdadc5c62c3e2b8a494b8f2f5850af531abc46299b824811ea
6
+ metadata.gz: a0496f4be0ffffa3bcf025abc4a92dd8fc42c621a667bf8c69841120a8472cf0c37f37663b2fc0226b59b7e01990219eb8eec528fcb851974f0848eb4f6af445
7
+ data.tar.gz: 407419063fd8c30148d644156ddbaba8342250f9310dc6323d5affa259ec15dcf2ba9694893d209530f978ff7fb5cee5c21551b8d00652c71584fbcc47b8a3b8
data/Gemfile CHANGED
@@ -15,6 +15,7 @@ gem 'yard'
15
15
 
16
16
  # Testing
17
17
  gem "rspec", "~> 3.3"
18
+ gem "factory_girl"
18
19
 
19
20
  # CI
20
21
  gem "travis-lint"
@@ -1,6 +1,16 @@
1
1
  module DispatchRider
2
2
  class Configuration
3
- attr_accessor :handler_path, :error_handler, :queue_info, :queue_kind, :subscriber, :logger, :log_formatter, :debug
3
+ attr_accessor(
4
+ :handler_path,
5
+ :error_handler,
6
+ :queue_info,
7
+ :queue_kind,
8
+ :subscriber,
9
+ :logger,
10
+ :log_formatter,
11
+ :debug,
12
+ :additional_info_injector
13
+ )
4
14
  attr_reader :callbacks
5
15
 
6
16
  def initialize
@@ -11,6 +21,7 @@ module DispatchRider
11
21
  @callbacks = Callbacks::Storage.new
12
22
  @subscriber = DispatchRider::Subscriber
13
23
  @log_formatter = DispatchRider::Logging::TextFormatter.new
24
+ @additional_info_injector = -> (data) { data }
14
25
  @logger = Logger.new(STDERR)
15
26
  @debug = false
16
27
 
@@ -4,7 +4,7 @@ module DispatchRider
4
4
  end
5
5
  end
6
6
 
7
+ require_relative 'logging/translator'
7
8
  require_relative 'logging/lifecycle_logger'
8
- require_relative 'logging/base_formatter'
9
9
  require_relative 'logging/text_formatter'
10
10
  require_relative 'logging/json_formatter'
@@ -3,79 +3,12 @@ require 'json'
3
3
  # JSON Log Formatter
4
4
  module DispatchRider
5
5
  module Logging
6
- class JsonFormatter < BaseFormatter
7
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
8
- # @param [Exception] exception
9
- # @return [String] JSON representation of the log item
10
- def format_error_handler_fail(message, exception)
11
- as_json do
12
- {
13
- phase: :failed,
14
- }.merge exception_info_fragment(message, exception)
15
- end
16
- end
17
-
18
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
19
- # @param [String] reason
20
- # @return [String] JSON representation of the log item
21
- def format_got_stop(message, reason)
22
- as_json do
23
- {
24
- phase: :stop,
25
- reason: reason,
26
- }.merge message_info_fragment(message)
27
- end
28
- end
29
-
30
- # @param [Symbol] kind of log action. one of: :start, :success, :fail, :complete
31
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
32
- # @param [Exception] exception
33
- # @param [Float] Job execution duration
34
- # @return [String] JSON representation of the log item
35
- def format_handling(kind, message, exception: nil, duration: nil)
36
- as_json do
37
- fragment = case kind
38
- when :start
39
- message_info_fragment(message)
40
- when :success
41
- message_info_fragment(message)
42
- when :fail
43
- exception_info_fragment(message, exception)
44
- when :complete
45
- duration_fragment = { duration: format_duration(duration) }
46
- message_info_fragment(message).merge duration_fragment
47
- end
48
- { phase: kind }.merge fragment
49
- end
50
- end
51
-
52
- private
6
+ class JsonFormatter
53
7
 
54
- def format_duration(duration)
55
- duration
8
+ def format(data)
9
+ data.to_json
56
10
  end
57
11
 
58
- def as_json
59
- JSON.generate yield
60
- end
61
-
62
- def message_info_fragment(message)
63
- {
64
- guid: message.guid.to_s,
65
- subject: message.subject,
66
- body: message_info_arguments(message),
67
- }
68
- end
69
-
70
- def exception_info_fragment(message, exception)
71
- exception_details = {
72
- expection: {
73
- class: exception.class.to_s,
74
- message: exception.message,
75
- }
76
- }
77
- message_info_fragment(message).merge exception_details
78
- end
79
12
  end
80
13
  end
81
14
  end
@@ -3,11 +3,11 @@ module DispatchRider
3
3
  class LifecycleLogger
4
4
  class << self
5
5
  def log_error_handler_fail(message, exception)
6
- logger.error formatter.format_error_handler_fail(message, exception)
6
+ new(:error_handler_fail, message, exception: exception).log
7
7
  end
8
8
 
9
9
  def log_got_stop(reason, message)
10
- logger.info formatter.format_got_stop(message, reason)
10
+ new(:stop, message, reason: reason).log
11
11
  end
12
12
 
13
13
  def wrap_handling(message)
@@ -25,29 +25,71 @@ module DispatchRider
25
25
  private
26
26
 
27
27
  def log_complete(message, duration)
28
- logger.info formatter.format_handling :complete, message, duration: duration
28
+ new(:complete, message, duration: duration).log
29
29
  end
30
30
 
31
31
  def log_fail(message, exception)
32
- logger.error formatter.format_handling :fail, message, exception: exception
32
+ new(:fail, message, exception: exception).log
33
33
  end
34
34
 
35
35
  def log_success(message)
36
- logger.info formatter.format_handling :success, message
36
+ new(:success, message).log
37
37
  end
38
38
 
39
39
  def log_start(message)
40
- logger.info formatter.format_handling :start, message
40
+ new(:start, message).log
41
41
  end
42
+ end
42
43
 
43
- def formatter
44
- DispatchRider.config.log_formatter
45
- end
44
+ def initialize(kind, message, options = {})
45
+ @kind = kind
46
+ @message = message
47
+ @options = options
48
+ end
49
+
50
+ def log
51
+ logger.send(log_action, formatted_data)
52
+ end
53
+
54
+ private
55
+
56
+ attr_reader :kind, :message, :options
57
+
58
+ def formatter
59
+ DispatchRider.config.log_formatter
60
+ end
61
+
62
+ def logger
63
+ DispatchRider.config.logger
64
+ end
46
65
 
47
- def logger
48
- DispatchRider.config.logger
66
+ def additional_info_injector
67
+ DispatchRider.config.additional_info_injector
68
+ end
69
+
70
+ def translator
71
+ Translator
72
+ end
73
+
74
+ def translated_message
75
+ translator.translate(message, kind, options)
76
+ end
77
+
78
+ def interjected_message
79
+ additional_info_injector.call(translated_message)
80
+ end
81
+
82
+ def formatted_data
83
+ formatter.format(interjected_message)
84
+ end
85
+
86
+ def log_action
87
+ case kind
88
+ when :fail, :error_handler_fail then :error
89
+ when :start, :stop, :complete, :success then :info
49
90
  end
50
91
  end
92
+
51
93
  end
52
94
  end
53
95
  end
@@ -1,48 +1,48 @@
1
1
  # Text Log Formatter
2
2
  module DispatchRider
3
3
  module Logging
4
- class TextFormatter < BaseFormatter
5
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
6
- # @param [Exception] exception
7
- # @return [String] log item
8
- def format_error_handler_fail(message, exception)
9
- "Failed error handling of: #{exception_info_fragment(message, exception)}"
10
- end
11
-
12
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
13
- # @param [String] reason
14
- # @return [String] log item
15
- def format_got_stop(message, reason)
16
- "Got stop #{reason ? '(' + reason + ') ' : ' ' }while executing: #{message_info_fragment(message)}"
17
- end
4
+ class TextFormatter
18
5
 
19
- # @param [Symbol] kind of log action. one of: :start, :success, :fail, :complete
20
- # @param [DispatchRider::QueueServices::ReceivedMessage] message
21
- # @param [Exception] exception
22
- # @param [Float] Job execution duration
23
- # @return [String] log item
24
- def format_handling(kind, message, exception: nil, duration: nil)
25
- case kind
6
+ def format(data)
7
+ case data[:phase]
8
+ when :complete
9
+ "Completed execution of: #{message_info_fragment(data)} in #{format_duration(data[:duration])} seconds"
10
+ when :fail
11
+ "Failed execution of: #{exception_info_fragment(data)}"
26
12
  when :start
27
- "Starting execution of: #{message_info_fragment(message)}"
13
+ "Starting execution of: #{message_info_fragment(data)}"
28
14
  when :success
29
- "Succeeded execution of: #{message_info_fragment(message)}"
30
- when :fail
31
- "Failed execution of: #{exception_info_fragment(message, exception)}"
32
- when :complete
33
- "Completed execution of: #{message_info_fragment(message)} in #{format_duration(duration)} seconds"
15
+ "Succeeded execution of: #{message_info_fragment(data)}"
16
+ when :stop
17
+ "Got stop #{data[:reason] ? '(' + data[:reason] + ')' : '' } while executing: #{message_info_fragment(data)}"
18
+ when :error_handler_fail
19
+ "Failed error handling of: #{exception_info_fragment(data)}"
20
+ else
21
+ raise ArgumentError, "Invalid phase : #{data[:phase].inspect}"
34
22
  end
35
23
  end
36
24
 
37
25
  private
38
26
 
39
- def message_info_fragment(message)
40
- "(#{message.guid}): #{message.subject} : #{message_info_arguments(message).inspect}"
27
+ def message_info_fragment(data)
28
+ "(#{data[:guid]}): #{data[:subject]} : #{message_info_arguments(data[:body]).inspect}"
41
29
  end
42
30
 
43
- def exception_info_fragment(message, exception)
44
- "(#{message.guid}): #{message.subject} with #{exception.class}: #{exception.message}"
31
+ def exception_info_fragment(data)
32
+ "(#{data[:guid]}): #{data[:subject]} with #{data[:exception][:class]}: #{data[:exception][:message]}"
45
33
  end
34
+
35
+ def message_info_arguments(body)
36
+ body.dup.tap do |m|
37
+ m.delete('guid')
38
+ m.delete('object_id')
39
+ end
40
+ end
41
+
42
+ def format_duration(duration)
43
+ '%.2f' % [duration]
44
+ end
45
+
46
46
  end
47
47
  end
48
48
  end
@@ -0,0 +1,26 @@
1
+ module DispatchRider
2
+ module Logging
3
+
4
+ # Translates a message into a loggable hash based on its result.
5
+ class Translator
6
+ def self.translate(message, kind, **args)
7
+ klass = translator_class(kind)
8
+ fragment = klass.new(message, **args).translate
9
+ { phase: kind }.merge fragment
10
+ end
11
+
12
+ def self.translator_class(kind)
13
+ const_get("#{kind}_translator".classify)
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+
20
+ require_relative 'translator/base_translator'
21
+ require_relative 'translator/complete_translator'
22
+ require_relative 'translator/fail_translator'
23
+ require_relative 'translator/error_handler_fail_translator'
24
+ require_relative 'translator/start_translator'
25
+ require_relative 'translator/stop_translator'
26
+ require_relative 'translator/success_translator'
@@ -0,0 +1,44 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class BaseTranslator
6
+ def initialize(message, **)
7
+ @message = message
8
+ end
9
+
10
+ def translate
11
+ raise NotImplementedError, 'Translators must implement #translate'
12
+ end
13
+
14
+ private
15
+
16
+ def message_info_fragment(message)
17
+ {
18
+ guid: message.guid.to_s,
19
+ subject: message.subject,
20
+ body: message_info_arguments(message),
21
+ }
22
+ end
23
+
24
+ def message_info_arguments(message)
25
+ message.body.dup.tap do |m|
26
+ m.delete('guid')
27
+ m.delete('object_id')
28
+ end
29
+ end
30
+
31
+ def exception_info_fragment(message, exception)
32
+ exception_details = {
33
+ exception: {
34
+ class: exception.class.to_s,
35
+ message: exception.message,
36
+ }
37
+ }
38
+ message_info_fragment(message).merge exception_details
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class CompleteTranslator < BaseTranslator
6
+ def initialize(message, duration:)
7
+ super(message)
8
+ @duration = duration
9
+ end
10
+
11
+ def translate
12
+ message_info_fragment(@message).merge duration: @duration
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class ErrorHandlerFailTranslator < FailTranslator
6
+ end
7
+
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class FailTranslator < BaseTranslator
6
+ def initialize(message, exception:)
7
+ super(message)
8
+ @exception = exception
9
+ end
10
+
11
+ def translate
12
+ exception_info_fragment(@message, @exception)
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class StartTranslator < BaseTranslator
6
+ def translate
7
+ message_info_fragment(@message)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class StopTranslator < BaseTranslator
6
+ def initialize(message, reason:)
7
+ super(message)
8
+ @reason = reason
9
+ end
10
+
11
+ def translate
12
+ message_info_fragment(@message).merge reason: @reason
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ module DispatchRider
2
+ module Logging
3
+ class Translator
4
+
5
+ class SuccessTranslator < StartTranslator
6
+ end
7
+
8
+ end
9
+ end
10
+ end
@@ -1,4 +1,4 @@
1
1
  # This file specifies the current version of the gem.
2
2
  module DispatchRider
3
- VERSION = "1.6.1"
3
+ VERSION = "1.6.2"
4
4
  end
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :message, class: 'DispatchRider::Message' do
3
+ subject 'sample_handler'
4
+ body(
5
+ 'key' => 'value',
6
+ 'guid' => DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
7
+ )
8
+ initialize_with { DispatchRider::Message.new(attributes) }
9
+ end
10
+ end
@@ -97,7 +97,7 @@ describe "Logging" do
97
97
  'guid' => 'test-mode-not-random-guid',
98
98
  'subject' => 'crashing_handler',
99
99
  'body' => {},
100
- 'expection' => {
100
+ 'exception' => {
101
101
  'class' => 'RuntimeError',
102
102
  'message' => 'I crashed!',
103
103
  },
@@ -1,72 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe DispatchRider::Logging::JsonFormatter do
4
- let(:fs_message) { DispatchRider::Message.new(subject: 'test', body: { 'key' => 'value', 'guid' => 123 }) }
5
- let(:item) { double :item }
6
- let(:queue) { double :queue }
7
- let(:message) { DispatchRider::QueueServices::FileSystem::FsReceivedMessage.new(fs_message, item, queue) }
8
- let(:exception) { StandardError.new }
9
- let(:reason) { "Stop reason" }
4
+ let(:data) { { some: :data } }
10
5
 
11
- let(:result_object) do
12
- {
13
- "subject" => "test",
14
- "guid" => "123",
15
- "body" => {
16
- "key" => "value"
17
- },
18
- }
19
- end
20
- let(:result_exception) do
21
- {
22
- "expection" => {
23
- "class" => "StandardError",
24
- "message" => "StandardError"
25
- }
26
- }
27
- end
28
-
29
- context "format_error_handler_fail" do
30
- let(:formatted_message) { result_object.merge("phase" => "failed").merge(result_exception) }
31
- let(:result_message) { JSON.parse subject.format_error_handler_fail(message, exception) }
32
-
33
- example { expect(result_message).to eq(formatted_message) }
34
- end
35
-
36
- context "format_got_stop" do
37
- let(:formatted_message) { result_object.merge("phase" => "stop", "reason" => reason) }
38
- let(:result_message) { JSON.parse subject.format_got_stop(message, reason) }
39
-
40
- example { expect(result_message).to eq(formatted_message) }
41
- end
42
-
43
- context "format_handling" do
44
- context "start" do
45
- let(:formatted_message) { result_object.merge("phase" => "start") }
46
- let(:result_message) { JSON.parse subject.format_handling(:start, message) }
47
-
48
- example { expect(result_message).to eq(formatted_message) }
49
- end
50
-
51
- context "success" do
52
- let(:formatted_message) { result_object.merge("phase" => "success") }
53
- let(:result_message) { JSON.parse subject.format_handling(:success, message) }
54
-
55
- example { expect(result_message).to eq(formatted_message) }
56
- end
57
-
58
- context "complete" do
59
- let(:formatted_message) { result_object.merge("phase" => "complete", "duration" => 2.0) }
60
- let(:result_message) { JSON.parse subject.format_handling(:complete, message, duration: 2.0) }
61
-
62
- example { expect(result_message).to eq(formatted_message) }
63
- end
64
-
65
- context "fail" do
66
- let(:formatted_message) { result_object.merge("phase" => "fail").merge(result_exception) }
67
- let(:result_message) { JSON.parse subject.format_handling(:fail, message, exception: exception) }
6
+ let(:formatted_data) { %{{"some":"data"}} }
68
7
 
69
- example { expect(formatted_message).to eq(formatted_message) }
70
- end
8
+ example do
9
+ expect(described_class.new.format(data)).to eq(formatted_data)
71
10
  end
72
11
  end
@@ -1,72 +1,168 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe DispatchRider::Logging::LifecycleLogger do
3
+ describe DispatchRider::Logging::LifecycleLogger, aggregrate_failures: true do
4
4
  subject { DispatchRider::Logging::LifecycleLogger }
5
5
 
6
- let(:message) { DispatchRider::Message.new(subject: 'test', body: 'test_handler') }
7
- let(:string_to_log) { "string to log" }
8
- let(:exception) { StandardError.new }
6
+ let(:queue) { double :queue }
7
+ let(:item) { double :item }
8
+ let(:fs_message) { DispatchRider::QueueServices::FileSystem::FsReceivedMessage.new(message, item, queue) }
9
+ let(:message) { DispatchRider::Message.new(subject: 'test', body: { 'guid' => '123', 'some' => 'key' }) }
10
+ let(:exception) { StandardError.new('something failed') }
9
11
  let(:reason) { "Stop reason" }
10
12
 
11
13
  let(:formatter) { DispatchRider.config.log_formatter }
12
- let(:logger) { DispatchRider.config.logger }
14
+ let(:logger) { double :logger }
13
15
 
14
16
  before do
15
- allow(formatter).to receive(:format_got_stop).and_return(string_to_log)
16
- allow(formatter).to receive(:format_error_handler_fail).and_return(string_to_log)
17
- allow(formatter).to receive(:format_handling).and_return(string_to_log)
17
+ DispatchRider.config.logger = logger
18
18
  end
19
19
 
20
- context "log_error_handler_fail" do
21
- after { subject.log_error_handler_fail message, exception }
22
-
23
- it "calls logger with error" do
24
- expect(logger).to receive(:error).with(string_to_log)
25
- end
20
+ after do
21
+ DispatchRider.clear_configuration!
26
22
  end
27
23
 
28
- context "log_got_stop" do
29
- after { subject.log_got_stop reason, message }
24
+ context 'when log formatter is json' do
25
+ before { DispatchRider.config.log_formatter = DispatchRider::Logging::JsonFormatter.new }
30
26
 
31
- it "calls logger with info" do
32
- expect(logger).to receive(:info).with(string_to_log)
33
- end
34
- end
27
+ context 'when additional_info_injector is customized' do
28
+ let(:additional_info_injector) do
29
+ -> (message) do
30
+ message[:employee_id] = 47
31
+ message[:account_id] = 42
32
+ message
33
+ end
34
+ end
35
35
 
36
- context "wrap_handling" do
37
- context "block runs successfully" do
38
- let(:block) { Proc.new { true } }
39
- after { subject.wrap_handling(message, &block) }
36
+ before do
37
+ DispatchRider.config.additional_info_injector = additional_info_injector
38
+ end
40
39
 
41
- it "logs start" do
42
- expect(subject).to receive(:log_start).with(message)
40
+ describe 'log_error_handler_fail' do
41
+ let(:expected_info) do
42
+ {
43
+ phase: 'error_handler_fail',
44
+ guid: '123',
45
+ subject: 'test',
46
+ body: { some: 'key' },
47
+ exception: { class: 'StandardError', message: 'something failed' },
48
+ employee_id: 47,
49
+ account_id: 42,
50
+ }.deep_stringify_keys.to_json
51
+ end
52
+
53
+ it "calls logger with error" do
54
+ expect(logger).to receive(:error).with(expected_info)
55
+ subject.log_error_handler_fail fs_message, exception
56
+ end
43
57
  end
44
58
 
45
- it "logs success" do
46
- expect(subject).to receive(:log_success).with(message)
59
+ describe "log_got_stop" do
60
+ let(:expected_info) do
61
+ {
62
+ phase: 'stop',
63
+ guid: '123',
64
+ subject: 'test',
65
+ body: { some: 'key' },
66
+ reason: reason,
67
+ employee_id: 47,
68
+ account_id: 42,
69
+ }.deep_stringify_keys.to_json
70
+ end
71
+
72
+ it "calls logger with info" do
73
+ expect(logger).to receive(:info).with(expected_info)
74
+ subject.log_got_stop reason, fs_message
75
+ end
47
76
  end
48
77
 
49
- it "logs complete" do
50
- expect(subject).to receive(:log_complete).with(message, an_instance_of(Float))
78
+ describe "wrap_handling" do
79
+ let(:expected_start_info) do
80
+ {
81
+ phase: 'start',
82
+ guid: '123',
83
+ subject: 'test',
84
+ body: { some: 'key' },
85
+ employee_id: 47,
86
+ account_id: 42,
87
+ }.deep_stringify_keys.to_json
88
+ end
89
+
90
+ let(:expected_succeed_info) do
91
+ {
92
+ phase: 'success',
93
+ guid: '123',
94
+ subject: 'test',
95
+ body: { some: 'key' },
96
+ employee_id: 47,
97
+ account_id: 42,
98
+ }.deep_stringify_keys.to_json
99
+ end
100
+
101
+ let(:expected_complete_info) do
102
+ /{"phase":"complete","guid":"123","subject":"test","body":{"some":"key"},"duration":\d+(?:.\d+)?,"employee_id":47,"account_id":42}/
103
+ end
104
+
105
+ context 'succeeding the handler' do
106
+ example do
107
+ expect(logger).to receive(:info).with(expected_start_info)
108
+ expect(logger).to receive(:info).with(expected_succeed_info)
109
+ expect(logger).to receive(:info).with(expected_complete_info)
110
+ expect {
111
+ subject.wrap_handling(fs_message) { true }
112
+ }.not_to raise_exception
113
+ end
114
+ end
51
115
  end
52
116
  end
53
117
 
54
- context "block fails" do
55
- let(:block) { Proc.new { raise exception } }
56
- after do
57
- expect { subject.wrap_handling(message, &block) }.to raise_error(exception)
118
+ context 'when log formatter is text based' do
119
+ before do
120
+ DispatchRider.config.log_formatter = DispatchRider::Logging::TextFormatter.new
58
121
  end
59
122
 
60
- it "logs start" do
61
- expect(subject).to receive(:log_start).with(message)
123
+ describe "log_error_handler_fail" do
124
+ it "calls logger with error" do
125
+ expect(logger).to receive(:error).with(
126
+ "Failed error handling of: (123): test with StandardError: something failed"
127
+ )
128
+ subject.log_error_handler_fail fs_message, exception
129
+ end
62
130
  end
63
131
 
64
- it "logs fail" do
65
- expect(subject).to receive(:log_fail).with(message, exception)
132
+ describe "log_got_stop" do
133
+ it "calls logger with info" do
134
+ expect(logger).to receive(:info).with(
135
+ %{Got stop (Stop reason) while executing: (123): test : {"some"=>"key"}})
136
+ subject.log_got_stop reason, fs_message
137
+ end
66
138
  end
67
139
 
68
- it "logs complete" do
69
- expect(subject).to receive(:log_complete).with(message, an_instance_of(Float))
140
+ describe "wrap_handling" do
141
+ context 'succeeding the handler' do
142
+ example do
143
+ expect(logger).to receive(:info).with(%{Starting execution of: (123): test : {"some"=>"key"}})
144
+ expect(logger).to receive(:info).with(%{Succeeded execution of: (123): test : {"some"=>"key"}})
145
+ expect(logger).to receive(:info).with(
146
+ /Completed execution of: \(123\): test : {"some"=>"key"} in \d+(?:.\d+)? seconds/
147
+ )
148
+ expect {
149
+ subject.wrap_handling(fs_message) { true }
150
+ }.not_to raise_exception
151
+ end
152
+ end
153
+
154
+ context 'failing the handler' do
155
+ example do
156
+ expect(logger).to receive(:info).with(%{Starting execution of: (123): test : {"some"=>"key"}})
157
+ expect(logger).to receive(:error).with(%{Failed execution of: (123): test with RuntimeError: failed!})
158
+ expect(logger).to receive(:info).with(
159
+ /Completed execution of: \(123\): test : {"some"=>"key"} in \d+(?:.\d+)? seconds/
160
+ )
161
+ expect {
162
+ subject.wrap_handling(fs_message) { raise "failed!" }
163
+ }.to raise_exception "failed!"
164
+ end
165
+ end
70
166
  end
71
167
  end
72
168
  end
@@ -1,60 +1,73 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe DispatchRider::Logging::TextFormatter do
4
- let(:fs_message) { DispatchRider::Message.new(subject: 'test', body: { 'key' => 'value', 'guid' => 123 }) }
5
- let(:item) { double :item }
6
- let(:queue) { double :queue }
7
- let(:message) { DispatchRider::QueueServices::FileSystem::FsReceivedMessage.new(fs_message, item, queue) }
8
-
9
- let(:string_to_log) { "string to log" }
10
- let(:exception) { StandardError.new }
11
- let(:reason) { "Stop reason" }
12
-
13
- before do
14
- allow(subject).to receive(:message_info_fragment).and_return(string_to_log)
15
- allow(subject).to receive(:exception_info_fragment).and_return(string_to_log)
16
- end
4
+ describe "#format" do
5
+ subject(:format_result) { described_class.new.format(data) }
17
6
 
18
- context "format_error_handler_fail" do
19
- let(:formatted_message) { "Failed error handling of: string to log" }
20
- example do
21
- expect(subject.format_error_handler_fail(message, exception)).to eq(formatted_message)
7
+ let(:data) do
8
+ {
9
+ phase: phase,
10
+ guid: '123',
11
+ body: { foo: :bar },
12
+ subject: 'sample_handler',
13
+ }
22
14
  end
23
- end
24
15
 
25
- context "format_got_stop" do
26
- let(:formatted_message) { "Got stop (Stop reason) while executing: string to log" }
27
- example do
28
- expect(subject.format_got_stop(message, reason)).to eq(formatted_message)
16
+ context 'when phase is :complete' do
17
+ let(:phase) { :complete }
18
+
19
+ before { data[:duration] = 10 }
20
+
21
+ example do
22
+ expect(format_result).to eq("Completed execution of: (123): sample_handler : {:foo=>:bar} in 10.00 seconds")
23
+ end
29
24
  end
30
- end
31
25
 
32
- context "format_handling" do
33
- context "start" do
34
- let(:formatted_message) { "Starting execution of: string to log" }
26
+ context 'when phase is :fail' do
27
+ let(:phase) { :fail }
28
+
29
+ before { data[:exception] = { class: StandardError, message: 'Foo is not bar' } }
30
+
35
31
  example do
36
- expect(subject.format_handling(:start, message)).to eq(formatted_message)
32
+ expect(format_result).to eq("Failed execution of: (123): sample_handler with StandardError: Foo is not bar")
37
33
  end
38
34
  end
39
35
 
40
- context "success" do
41
- let(:formatted_message) { "Succeeded execution of: string to log" }
36
+ context 'when phase is :start' do
37
+ let(:phase) { :start }
38
+
42
39
  example do
43
- expect(subject.format_handling(:success, message)).to eq(formatted_message)
40
+ expect(format_result).to eq("Starting execution of: (123): sample_handler : {:foo=>:bar}")
44
41
  end
45
42
  end
46
43
 
47
- context "complete" do
48
- let(:formatted_message) { "Completed execution of: string to log in 2.12 seconds" }
44
+ context 'when phase is :success' do
45
+ let(:phase) { :success }
46
+
49
47
  example do
50
- expect(subject.format_handling(:complete, message, duration: 2.12)).to eq(formatted_message)
48
+ expect(format_result).to eq("Succeeded execution of: (123): sample_handler : {:foo=>:bar}")
51
49
  end
52
50
  end
53
51
 
54
- context "fail" do
55
- let(:formatted_message) { "Failed execution of: string to log" }
52
+ context 'when phase is :stop' do
53
+ let(:phase) { :stop }
54
+
55
+ before { data[:reason] = 'Ninja Attack' }
56
+
57
+ example do
58
+ expect(format_result).to eq("Got stop (Ninja Attack) while executing: (123): sample_handler : {:foo=>:bar}")
59
+ end
60
+ end
61
+
62
+ context 'when phase is :error_handler_fail' do
63
+ let(:phase) { :error_handler_fail }
64
+
65
+ before { data[:exception] = { class: StandardError, message: 'Foo is not bar' } }
66
+
56
67
  example do
57
- expect(subject.format_handling(:fail, message, exception: exception)).to eq(formatted_message)
68
+ expect(format_result).to eq(
69
+ "Failed error handling of: (123): sample_handler with StandardError: Foo is not bar"
70
+ )
58
71
  end
59
72
  end
60
73
  end
@@ -0,0 +1,160 @@
1
+ require 'spec_helper'
2
+
3
+ describe DispatchRider::Logging::Translator do
4
+ let(:queue) { double :queue }
5
+ let(:message) { build(:message) }
6
+ let(:item) { double :item }
7
+ let(:fs_message) { DispatchRider::QueueServices::FileSystem::FsReceivedMessage.new(message, item, queue) }
8
+
9
+ let(:exception) { nil }
10
+ let(:duration) { nil }
11
+ let(:reason) { nil }
12
+
13
+ describe '.translate' do
14
+ context 'when the job is starting' do
15
+ subject(:result) do
16
+ described_class.translate(fs_message, kind)
17
+ end
18
+ let(:kind) { :start }
19
+ let(:expected_hash) do
20
+ {
21
+ phase: :start,
22
+ subject: 'sample_handler',
23
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
24
+ body: {
25
+ 'key' => 'value',
26
+ },
27
+ }
28
+ end
29
+
30
+ example do
31
+ expect(result).to eq(expected_hash)
32
+ end
33
+ end
34
+
35
+ context 'when the job has succeeded' do
36
+ subject(:result) do
37
+ described_class.translate(fs_message, kind)
38
+ end
39
+ let(:kind) { :success }
40
+ let(:expected_hash) do
41
+ {
42
+ phase: :success,
43
+ subject: 'sample_handler',
44
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
45
+ body: {
46
+ 'key' => 'value',
47
+ },
48
+ }
49
+ end
50
+
51
+ example do
52
+ expect(result).to eq(expected_hash)
53
+ end
54
+ end
55
+
56
+ context 'when the job has failed' do
57
+ subject(:result) do
58
+ described_class.translate(fs_message, kind, exception: exception)
59
+ end
60
+ let(:kind) { :fail }
61
+ let(:exception) do
62
+ ArgumentError.new("Foo is not bar")
63
+ end
64
+
65
+ let(:expected_hash) do
66
+ {
67
+ phase: :fail,
68
+ subject: 'sample_handler',
69
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
70
+ body: {
71
+ 'key' => 'value',
72
+ },
73
+ exception: {
74
+ class: 'ArgumentError',
75
+ message: 'Foo is not bar',
76
+ }
77
+ }
78
+ end
79
+
80
+ example do
81
+ expect(result).to eq(expected_hash)
82
+ end
83
+ end
84
+
85
+ context 'when the job has completed' do
86
+ subject(:result) do
87
+ described_class.translate(fs_message, kind, duration: duration)
88
+ end
89
+ let(:kind) { :complete }
90
+ let(:duration) { 5 }
91
+ let(:expected_hash) do
92
+ {
93
+ phase: :complete,
94
+ subject: 'sample_handler',
95
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
96
+ body: {
97
+ 'key' => 'value',
98
+ },
99
+ duration: 5,
100
+ }
101
+ end
102
+
103
+ example do
104
+ expect(result).to eq(expected_hash)
105
+ end
106
+ end
107
+
108
+ context 'when the error handler fails' do
109
+ subject(:result) do
110
+ described_class.translate(fs_message, kind, exception: exception)
111
+ end
112
+ let(:kind) { :error_handler_fail }
113
+ let(:exception) do
114
+ ArgumentError.new("Foo is not bar")
115
+ end
116
+
117
+ let(:expected_hash) do
118
+ {
119
+ phase: :error_handler_fail,
120
+ subject: 'sample_handler',
121
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
122
+ body: {
123
+ 'key' => 'value',
124
+ },
125
+ exception: {
126
+ class: 'ArgumentError',
127
+ message: 'Foo is not bar',
128
+ }
129
+ }
130
+ end
131
+
132
+ example do
133
+ expect(result).to eq(expected_hash)
134
+ end
135
+ end
136
+
137
+ context 'when the job has completed' do
138
+ subject(:result) do
139
+ described_class.translate(fs_message, kind, reason: reason)
140
+ end
141
+ let(:kind) { :stop }
142
+ let(:reason) { "Got TERM" }
143
+ let(:expected_hash) do
144
+ {
145
+ phase: :stop,
146
+ subject: 'sample_handler',
147
+ guid: DispatchRider::Debug::PUBLISHER_MESSAGE_GUID,
148
+ body: {
149
+ 'key' => 'value',
150
+ },
151
+ reason: 'Got TERM',
152
+ }
153
+ end
154
+
155
+ example do
156
+ expect(result).to eq(expected_hash)
157
+ end
158
+ end
159
+ end
160
+ end
data/spec/spec_helper.rb CHANGED
@@ -10,6 +10,9 @@ require 'tempfile'
10
10
  require 'dispatch-rider'
11
11
  Dir['./spec/support/**/*.rb'].each { |fn| require(fn) }
12
12
 
13
+ FactoryGirl.definition_file_paths = %w{spec/factories/}
14
+ FactoryGirl.find_definitions
15
+
13
16
  RSpec.configure do |config|
14
17
  config.raise_errors_for_deprecations!
15
18
  config.mock_with :rspec
@@ -25,6 +28,8 @@ RSpec.configure do |config|
25
28
  config.before do
26
29
  DispatchRider.config.logger = NullLogger.new
27
30
  end
31
+
32
+ config.include FactoryGirl::Syntax::Methods
28
33
  end
29
34
 
30
35
  # Airbrake dummy module
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dispatch-rider
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Suman Mukherjee
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-06-24 00:00:00.000000000 Z
14
+ date: 2015-06-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport
@@ -115,10 +115,17 @@ files:
115
115
  - lib/dispatch-rider/handlers/named_process.rb
116
116
  - lib/dispatch-rider/integrations/appsignal.rb
117
117
  - lib/dispatch-rider/logging.rb
118
- - lib/dispatch-rider/logging/base_formatter.rb
119
118
  - lib/dispatch-rider/logging/json_formatter.rb
120
119
  - lib/dispatch-rider/logging/lifecycle_logger.rb
121
120
  - lib/dispatch-rider/logging/text_formatter.rb
121
+ - lib/dispatch-rider/logging/translator.rb
122
+ - lib/dispatch-rider/logging/translator/base_translator.rb
123
+ - lib/dispatch-rider/logging/translator/complete_translator.rb
124
+ - lib/dispatch-rider/logging/translator/error_handler_fail_translator.rb
125
+ - lib/dispatch-rider/logging/translator/fail_translator.rb
126
+ - lib/dispatch-rider/logging/translator/start_translator.rb
127
+ - lib/dispatch-rider/logging/translator/stop_translator.rb
128
+ - lib/dispatch-rider/logging/translator/success_translator.rb
122
129
  - lib/dispatch-rider/message.rb
123
130
  - lib/dispatch-rider/notification_services.rb
124
131
  - lib/dispatch-rider/notification_services/aws_sns.rb
@@ -163,6 +170,7 @@ files:
163
170
  - lib/generators/dispatch_rider/job/templates/handler/handler_spec.rb.erb
164
171
  - lib/generators/dispatch_rider/job/templates/publisher/publisher.rb.erb
165
172
  - lib/generators/dispatch_rider/job/templates/publisher/publisher_spec.rb.erb
173
+ - spec/factories/messages.rb
166
174
  - spec/fixtures/handlers/another_test_handler.rb
167
175
  - spec/fixtures/handlers/test_handler.rb
168
176
  - spec/integration/logging_spec.rb
@@ -178,6 +186,7 @@ files:
178
186
  - spec/lib/dispatch-rider/logging/json_formatter_spec.rb
179
187
  - spec/lib/dispatch-rider/logging/lifecycle_logger_spec.rb
180
188
  - spec/lib/dispatch-rider/logging/text_formatter_spec.rb
189
+ - spec/lib/dispatch-rider/logging/translator_spec.rb
181
190
  - spec/lib/dispatch-rider/message_spec.rb
182
191
  - spec/lib/dispatch-rider/notification_services/aws_sns_spec.rb
183
192
  - spec/lib/dispatch-rider/notification_services/base_spec.rb
@@ -240,6 +249,7 @@ specification_version: 4
240
249
  summary: Messaging system that is customizable based on which queueing system we are
241
250
  using.
242
251
  test_files:
252
+ - spec/factories/messages.rb
243
253
  - spec/fixtures/handlers/another_test_handler.rb
244
254
  - spec/fixtures/handlers/test_handler.rb
245
255
  - spec/integration/logging_spec.rb
@@ -255,6 +265,7 @@ test_files:
255
265
  - spec/lib/dispatch-rider/logging/json_formatter_spec.rb
256
266
  - spec/lib/dispatch-rider/logging/lifecycle_logger_spec.rb
257
267
  - spec/lib/dispatch-rider/logging/text_formatter_spec.rb
268
+ - spec/lib/dispatch-rider/logging/translator_spec.rb
258
269
  - spec/lib/dispatch-rider/message_spec.rb
259
270
  - spec/lib/dispatch-rider/notification_services/aws_sns_spec.rb
260
271
  - spec/lib/dispatch-rider/notification_services/base_spec.rb
@@ -1,30 +0,0 @@
1
- module DispatchRider
2
- module Logging
3
- class BaseFormatter
4
- def format_error_handler_fail(*)
5
- raise NotImplementedError
6
- end
7
-
8
- def format_got_stop(*)
9
- raise NotImplementedError
10
- end
11
-
12
- def format_handling(*)
13
- raise NotImplementedError
14
- end
15
-
16
- private
17
-
18
- def message_info_arguments(message)
19
- message.body.dup.tap do |m|
20
- m.delete('guid')
21
- m.delete('object_id')
22
- end
23
- end
24
-
25
- def format_duration(duration)
26
- format '%.2f', duration
27
- end
28
- end
29
- end
30
- end