logglier 0.2.5 → 0.2.6

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.
@@ -16,7 +16,7 @@ module Logglier
16
16
  unless input_url
17
17
  raise URLRequired.new
18
18
  end
19
-
19
+
20
20
  opts.merge!({ :input_url => input_url })
21
21
 
22
22
  begin
@@ -33,7 +33,7 @@ module Logglier
33
33
  else
34
34
  raise Logglier::UnsupportedScheme.new("#{input_uri.scheme} is unsupported")
35
35
  end
36
-
36
+
37
37
  end
38
38
 
39
39
  module InstanceMethods
@@ -7,18 +7,35 @@ module Logglier
7
7
  # Used to wrap and setup Net::HTTP as we need it
8
8
  class NetHTTPProxy
9
9
 
10
+ RETRY_EXCEPTIONS = [
11
+ TimeoutError, OpenSSL::SSL::SSLError, Errno::EPIPE,
12
+ EOFError, Errno::ECONNRESET, Errno::ETIMEDOUT,
13
+ Errno::ECONNREFUSED
14
+ ]
15
+
16
+ RETRIES = 3
17
+
18
+ attr_accessor :failsafe
19
+
10
20
  # @param [URI] input_uri URI to deliver messages to
11
21
  # @param [Hash] opts Option hash
12
22
  # @option [Integer] read_timeout Read timeout for the http session. defaults to 2
13
23
  # @option [Integer] open_timeout Open timeout for the http session. defaults to 2
14
24
  # @option [Integer] verify_mode OpenSSL::SSL::VERIFY_* constant
15
25
  # @option [String] ca_file Path to the ca file
26
+ # @option [IO] failsafe Where to `#puts` delivery errors. defaults to `$stderr`
16
27
  def initialize(input_uri, opts={})
17
28
  @input_uri = input_uri
18
29
  @verify_mode = opts[:verify_mode] || OpenSSL::SSL::VERIFY_PEER
19
30
  @ca_file = opts[:ca_file]
20
31
  @read_timeout = opts[:read_timeout] || 5
21
32
  @open_timeout = opts[:open_timeout] || 5
33
+ @failsafe = opts[:failsafe] || $stderr
34
+ @format = opts[:format] ? opts[:format].to_sym : nil
35
+ @headers = {}
36
+ if @format == :json
37
+ @headers['Content-Type'] = 'application/json'
38
+ end
22
39
 
23
40
  connect!
24
41
  end
@@ -27,21 +44,22 @@ module Logglier
27
44
  #
28
45
  # @param [String] message The message to deliver
29
46
  def deliver(message)
30
- retried = false
47
+ retries = 0
48
+
31
49
  begin
32
- @http.request_post(@input_uri.path, message)
33
- # We're using persistent connections, so connection can be closed by the other side
34
- # after a timeout. Don't consider it an error, just retry once.
35
- rescue Errno::ECONNRESET
36
- unless retried
37
- retried = true
50
+ @http.request_post(@input_uri.path, message, @headers)
51
+ rescue *RETRY_EXCEPTIONS => e
52
+ if retries < RETRIES
53
+ retries += 1
54
+ failsafe_retrying(e, message, retries)
55
+ sleep retries
38
56
  connect!
39
57
  retry
40
58
  else
41
- $stderr.puts "WARNING: connection was reset while posting message: #{message}"
59
+ failsafe_errored(e, message)
42
60
  end
43
- rescue TimeoutError, OpenSSL::SSL::SSLError, EOFError, Errno::ECONNRESET => e
44
- $stderr.puts "WARNING: #{e.class} posting message: #{message}"
61
+ rescue Exception => e
62
+ failsafe_errored(e, message)
45
63
  end
46
64
  end
47
65
 
@@ -64,6 +82,18 @@ module Logglier
64
82
  @http.open_timeout = @open_timeout
65
83
 
66
84
  end
85
+
86
+ def failsafe_retrying(exception, message, retries)
87
+ @failsafe.puts "WARNING: [#{retries}/#{RETRIES}] " + failsafe_message(exception, message)
88
+ end
89
+
90
+ def failsafe_errored(exception, message)
91
+ @failsafe.puts "ERROR: " + failsafe_message(exception, message)
92
+ end
93
+
94
+ def failsafe_message(exception, message)
95
+ "caught `#{exception.class}: #{exception.message}` while attempting to deliver: #{message}"
96
+ end
67
97
  end
68
98
 
69
99
  end
@@ -1,3 +1,3 @@
1
1
  module Logglier
2
- VERSION = '0.2.5'
2
+ VERSION = '0.2.6'
3
3
  end
@@ -7,7 +7,9 @@ describe 'HTTP' do
7
7
  @http.stub!(:read_timeout=)
8
8
  @http.stub!(:open_timeout=)
9
9
  Net::HTTP.stub!(:new).and_return(@http)
10
- @proxy = Logglier::Client::HTTP::NetHTTPProxy.new(URI.parse('http://localhost:9292'))
10
+ @failsafe = StringIO.new
11
+ @proxy = Logglier::Client::HTTP::NetHTTPProxy.new(URI.parse('http://localhost:9292'), :failsafe => @failsafe)
12
+ @proxy.stub(:sleep)
11
13
  end
12
14
 
13
15
  it "retries after connection is reset" do
@@ -16,14 +18,69 @@ describe 'HTTP' do
16
18
  @proxy.deliver('message')
17
19
  end
18
20
 
19
- it "retries only once connection is reset" do
20
- @http.should_receive(:request_post).exactly(2).times.and_raise Errno::ECONNRESET
21
- @proxy.deliver('message')
21
+ it "defaults its failsafe to $stderr" do
22
+ proxy = Logglier::Client::HTTP::NetHTTPProxy.new(URI.parse('http://localhost:9292'))
23
+ proxy.failsafe.should == $stderr
22
24
  end
23
25
 
24
- it "fails for other errors" do
25
- @http.should_receive(:request_post).once.and_raise EOFError
26
- @proxy.deliver('message')
26
+ describe "error handling" do
27
+ Logglier::Client::HTTP::NetHTTPProxy::RETRY_EXCEPTIONS.each do |error|
28
+ context "for #{error}" do
29
+ context "with total failure" do
30
+ before do
31
+ @http.should_receive(:request_post).exactly(4).times.and_raise error
32
+ end
33
+
34
+ it "retries 3 times then fails" do
35
+ @proxy.deliver('message')
36
+ end
37
+
38
+ it "logs messages to the failsafe along the way" do
39
+ @proxy.deliver('message')
40
+
41
+ @failsafe.rewind
42
+ lines = @failsafe.readlines
43
+ lines.size.should == 4
44
+ lines[0..2].each {|l| l.should =~ /^WARNING/ }
45
+ lines.last.should =~ /^ERROR/
46
+ end
47
+ end
48
+
49
+ context "if things start working again" do
50
+ before do
51
+ @http.should_receive(:request_post).exactly(3).times.and_raise error
52
+ @http.should_receive(:request_post)
53
+ end
54
+
55
+ it "is successful if things start working again" do
56
+ @proxy.deliver('message')
57
+ end
58
+
59
+ it "logs messages to the failsafe along the way" do
60
+ @proxy.deliver('message')
61
+
62
+ @failsafe.rewind
63
+ lines = @failsafe.readlines
64
+ lines.size.should == 3
65
+ lines[0..2].each {|l| l.should =~ /^WARNING/ }
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ context "for an unknown error" do
72
+ it "logs a message" do
73
+ error = Class.new(StandardError)
74
+
75
+ @http.should_receive(:request_post).and_raise error
76
+ @proxy.deliver('message')
77
+
78
+ @failsafe.rewind
79
+ lines = @failsafe.readlines
80
+ lines.size.should == 1
81
+ lines.first.should =~ /^ERROR/
82
+ end
83
+ end
27
84
  end
28
85
 
29
86
  describe "json format" do
@@ -1,6 +1,7 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
2
 
3
3
  require 'logglier'
4
+ require 'stringio'
4
5
 
5
6
  module LoggerHacks
6
7
  def logdev
metadata CHANGED
@@ -1,62 +1,44 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: logglier
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.6
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 5
10
- version: 0.2.5
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Edward Muller (aka freeformz)
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-07-08 00:00:00 -07:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2011-09-22 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: rake
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70175089585180 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
33
22
  type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rspec
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70175089585180
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70175093319600 !ruby/object:Gem::Requirement
39
28
  none: false
40
- requirements:
29
+ requirements:
41
30
  - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 27
44
- segments:
45
- - 2
46
- - 5
47
- - 0
31
+ - !ruby/object:Gem::Version
48
32
  version: 2.5.0
49
33
  type: :development
50
- version_requirements: *id002
34
+ prerelease: false
35
+ version_requirements: *70175093319600
51
36
  description: Logger => Loggly
52
37
  email: edwardam@interlix.com
53
38
  executables: []
54
-
55
39
  extensions: []
56
-
57
40
  extra_rdoc_files: []
58
-
59
- files:
41
+ files:
60
42
  - README.md
61
43
  - Gemfile
62
44
  - LICENSE
@@ -74,45 +56,31 @@ files:
74
56
  - ./spec/logglier_spec.rb
75
57
  - ./spec/spec_helper.rb
76
58
  - ./spec/threaded_spec.rb
77
- has_rdoc: true
78
59
  homepage: http://github.com/freeformz/logglier
79
60
  licenses: []
80
-
81
61
  post_install_message:
82
62
  rdoc_options: []
83
-
84
- require_paths:
63
+ require_paths:
85
64
  - lib
86
- required_ruby_version: !ruby/object:Gem::Requirement
65
+ required_ruby_version: !ruby/object:Gem::Requirement
87
66
  none: false
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- hash: 59
92
- segments:
93
- - 1
94
- - 8
95
- - 6
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
96
70
  version: 1.8.6
97
- required_rubygems_version: !ruby/object:Gem::Requirement
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
72
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- hash: 23
103
- segments:
104
- - 1
105
- - 3
106
- - 6
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
107
76
  version: 1.3.6
108
77
  requirements: []
109
-
110
78
  rubyforge_project: logglier
111
- rubygems_version: 1.6.2
79
+ rubygems_version: 1.8.6
112
80
  signing_key:
113
81
  specification_version: 3
114
82
  summary: Loggly "plugin" for Logger
115
- test_files:
83
+ test_files:
116
84
  - ./spec/client_spec.rb
117
85
  - ./spec/http_spec.rb
118
86
  - ./spec/logglier_spec.rb