logglier 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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