buffered_remote_syslog_logger 0.2.0
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 +7 -0
- data/.gitignore +28 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +50 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +2 -0
- data/Rakefile +2 -0
- data/buffered_remote_syslog_logger.gemspec +29 -0
- data/lib/buffered_remote_syslog_logger.rb +6 -0
- data/lib/buffered_remote_syslog_logger/middleware.rb +28 -0
- data/lib/buffered_remote_syslog_logger/tcp_logger.rb +214 -0
- data/lib/buffered_remote_syslog_logger/version.rb +3 -0
- data/spec/lib/buffered_remote_syslog_logger/tcp_logger_spec.rb +68 -0
- data/spec/lib/buffered_remote_syslog_logger_spec.rb +6 -0
- data/spec/spec_helper.rb +25 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 97a525c5cc52ca6b91f1cf5d0a7dd1cd52a47cda
|
4
|
+
data.tar.gz: 208ff7834713e68cd03379eee74cf4c0c6823493
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c5d298b56ca787cdc59bd563b4c43c5ddfde36375d64278de5fd024807d50995fca3ab301df9cddcc0277afa23840aac112ad06524689d069ff8bcc091513e6d
|
7
|
+
data.tar.gz: 37af117ebd30bd10581e82d708c0270ef3388fabdd9ed6c74b3640f6b5e1977acfaad4fb886fc553a357ff1ff4421a1173c6cbf95b8e18488faa7f54a5d372d0
|
data/.gitignore
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
coverage
|
6
|
+
InstalledFiles
|
7
|
+
lib/bundler/man
|
8
|
+
pkg
|
9
|
+
rdoc
|
10
|
+
spec/reports
|
11
|
+
test/tmp
|
12
|
+
test/version_tmp
|
13
|
+
tmp
|
14
|
+
.rspec
|
15
|
+
|
16
|
+
# YARD artifacts
|
17
|
+
.yardoc
|
18
|
+
_yardoc
|
19
|
+
doc/
|
20
|
+
|
21
|
+
|
22
|
+
# ignore eclipse
|
23
|
+
.buildpath
|
24
|
+
.project
|
25
|
+
|
26
|
+
# ignore rvm
|
27
|
+
.rvmrc
|
28
|
+
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
buffered_remote_syslog_logger (0.2.0)
|
5
|
+
activesupport (< 4.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (3.2.19)
|
11
|
+
i18n (~> 0.6, >= 0.6.4)
|
12
|
+
multi_json (~> 1.0)
|
13
|
+
byebug (3.1.2)
|
14
|
+
columnize (~> 0.8)
|
15
|
+
debugger-linecache (~> 1.2)
|
16
|
+
columnize (0.8.9)
|
17
|
+
debugger-linecache (1.2.0)
|
18
|
+
diff-lcs (1.2.5)
|
19
|
+
docile (1.1.5)
|
20
|
+
i18n (0.6.9)
|
21
|
+
multi_json (1.10.1)
|
22
|
+
rake (10.3.2)
|
23
|
+
rspec (3.0.0)
|
24
|
+
rspec-core (~> 3.0.0)
|
25
|
+
rspec-expectations (~> 3.0.0)
|
26
|
+
rspec-mocks (~> 3.0.0)
|
27
|
+
rspec-core (3.0.2)
|
28
|
+
rspec-support (~> 3.0.0)
|
29
|
+
rspec-expectations (3.0.2)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.0.0)
|
32
|
+
rspec-mocks (3.0.2)
|
33
|
+
rspec-support (~> 3.0.0)
|
34
|
+
rspec-support (3.0.2)
|
35
|
+
simplecov (0.8.2)
|
36
|
+
docile (~> 1.1.0)
|
37
|
+
multi_json
|
38
|
+
simplecov-html (~> 0.8.0)
|
39
|
+
simplecov-html (0.8.0)
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
buffered_remote_syslog_logger!
|
46
|
+
bundler (~> 1.6)
|
47
|
+
byebug
|
48
|
+
rake
|
49
|
+
rspec
|
50
|
+
simplecov
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 DailyDeal GmbH
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'buffered_remote_syslog_logger/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "buffered_remote_syslog_logger"
|
8
|
+
spec.version = BufferedRemoteSyslogLogger::VERSION
|
9
|
+
spec.authors = ["DailyDeal Development"]
|
10
|
+
spec.email = ["dev@dailydeal.de"]
|
11
|
+
spec.summary = %q{centralize logging without interleaving in a remote syslog}
|
12
|
+
spec.description = %q{centralize logging without interleaving in a remote syslog}
|
13
|
+
spec.homepage = "http://github.com/DailyDeal/buffered_remote_syslog_logger.git"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6" # usability
|
22
|
+
spec.add_development_dependency "rake" # functionality
|
23
|
+
spec.add_development_dependency "rspec" # testability
|
24
|
+
spec.add_development_dependency "simplecov" # coverage, obviously
|
25
|
+
spec.add_development_dependency "byebug" # replacement for 'debugger' under 2.0+
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'activesupport', '< 4.0' # use buffered logger base implementation
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module BufferedRemoteSyslogLogger
|
3
|
+
|
4
|
+
class Middleware
|
5
|
+
|
6
|
+
attr_accessor :app, :logger
|
7
|
+
|
8
|
+
|
9
|
+
def initialize(app, options = {})
|
10
|
+
@logger = Rails.logger
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
request_id = env['HTTP_X_REQUEST_ID'] || rand(100000000)
|
17
|
+
request_id = sprintf("%08d", request_id)
|
18
|
+
Thread.current.thread_variable_set(:http_request_id, request_id)
|
19
|
+
|
20
|
+
@status, @headers, @response = app.call(env)
|
21
|
+
[@status, @headers, @response]
|
22
|
+
ensure
|
23
|
+
logger.flush
|
24
|
+
logger.close
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'syslog'
|
3
|
+
require 'logger'
|
4
|
+
require 'timeout'
|
5
|
+
require 'active_support'
|
6
|
+
|
7
|
+
# BufferedRemoteSyslogLogger is used as a dead-simple replacement for
|
8
|
+
# syslog ruby libs. None of them is able to send logs
|
9
|
+
# to a remote server, and even less in TCP.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# For rails (3.X) :
|
14
|
+
#
|
15
|
+
# config.logger = BufferedRemoteSyslogLogger::TcpLogger.new(:host => 'localhost')
|
16
|
+
#
|
17
|
+
# For more info about Syslog protocol, please refer to the RFC:
|
18
|
+
# http://www.faqs.org/rfcs/rfc3164.html
|
19
|
+
#
|
20
|
+
# Major Parts taken from TcpSyslog which in turn has Parts taken from SyslogLogger gem and ActiveSupport
|
21
|
+
#
|
22
|
+
module BufferedRemoteSyslogLogger
|
23
|
+
class TcpLogger < ::ActiveSupport::BufferedLogger
|
24
|
+
include Logger::Severity
|
25
|
+
|
26
|
+
# From 'man syslog.h':
|
27
|
+
# LOG_EMERG A panic condition was reported to all processes.
|
28
|
+
# LOG_ALERT A condition that should be corrected immediately.
|
29
|
+
# LOG_CRIT A critical condition.
|
30
|
+
# LOG_ERR An error message.
|
31
|
+
# LOG_WARNING A warning message.
|
32
|
+
# LOG_NOTICE A condition requiring special handling.
|
33
|
+
# LOG_INFO A general information message.
|
34
|
+
# LOG_DEBUG A message useful for debugging programs.
|
35
|
+
|
36
|
+
# From logger rdoc:
|
37
|
+
# FATAL: an unhandleable error that results in a program crash
|
38
|
+
# ERROR: a handleable error condition
|
39
|
+
# WARN: a warning
|
40
|
+
# INFO: generic (useful) information about system operation
|
41
|
+
# DEBUG: low-level information for developers
|
42
|
+
|
43
|
+
# Maps Logger warning types to syslog(3) warning types.
|
44
|
+
LOGGER_MAP = {
|
45
|
+
:unknown => Syslog::LOG_ALERT,
|
46
|
+
:fatal => Syslog::LOG_CRIT,
|
47
|
+
:error => Syslog::LOG_ERR,
|
48
|
+
:warn => Syslog::LOG_WARNING,
|
49
|
+
:info => Syslog::LOG_INFO,
|
50
|
+
:debug => Syslog::LOG_DEBUG
|
51
|
+
}
|
52
|
+
|
53
|
+
SOCKET_SEND_RETRY_ATTEMPTS = 2
|
54
|
+
class SocketTimeoutError < StandardError; end
|
55
|
+
|
56
|
+
# Maps Logger log levels to their values so we can silence.
|
57
|
+
LOGGER_LEVEL_MAP = {}
|
58
|
+
|
59
|
+
LOGGER_MAP.each_key do |key|
|
60
|
+
LOGGER_LEVEL_MAP[key] = Logger.const_get key.to_s.upcase
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# Maps Logger log level values to syslog log levels.
|
65
|
+
LEVEL_LOGGER_MAP = {}
|
66
|
+
|
67
|
+
LOGGER_LEVEL_MAP.invert.each do |level, severity|
|
68
|
+
LEVEL_LOGGER_MAP[level] = LOGGER_MAP[severity]
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
OPTION_DEFAULTS = {
|
73
|
+
:level => Logger::DEBUG,
|
74
|
+
:host => '127.0.0.1',
|
75
|
+
:port => '514',
|
76
|
+
:facility => Syslog::LOG_USER,
|
77
|
+
:program_name => 'buffered_remote_syslog_logger',
|
78
|
+
:auto_flushing => 1,
|
79
|
+
:remove_ansi_colors => true
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
attr_accessor :host, :port, :program_name, :level, :facility, :auto_flushing, :remove_ansi_colors, :buffer, :socket, :hostname
|
84
|
+
|
85
|
+
|
86
|
+
# Usage :
|
87
|
+
# * +options+ : A hash with the following options
|
88
|
+
# ** +level+ : severity level, defaults to debug
|
89
|
+
# ** +host+ : syslog daemon host, defaults to 'localhost'
|
90
|
+
# ** +port+ : syslog daemon port, defaults to '514'
|
91
|
+
# ** +facility+ : used syslog facility, defaults to log_user
|
92
|
+
# ** +program_name+ : name of the application, defaults to 'OPTION_DEFAULTS'
|
93
|
+
# ** +auto_flushing+ : number of messages to buffer before flushing, defaults to 1 (always flush right away)
|
94
|
+
# ** +remove_ansi_colors+ : boolean to determine, whether or not to remove ansi colors, defaults to true
|
95
|
+
def initialize(options = {})
|
96
|
+
@buffer = []
|
97
|
+
@socket = {}
|
98
|
+
|
99
|
+
options = OPTION_DEFAULTS.merge(Hash[options.map{ |key, value| [key.to_sym, value] }])
|
100
|
+
|
101
|
+
[:host, :port, :facility, :program_name, :auto_flushing, :remove_ansi_colors].each do |key|
|
102
|
+
self.public_send("#{key}=", options[key])
|
103
|
+
end
|
104
|
+
|
105
|
+
@level = LEVEL_LOGGER_MAP[options[:level]]
|
106
|
+
@hostname = `hostname`
|
107
|
+
|
108
|
+
return if defined? SYSLOG
|
109
|
+
self.class.const_set :SYSLOG, true
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# Almost duplicates Logger#add.
|
114
|
+
def add(severity, message, progname = nil, &block)
|
115
|
+
severity ||= Logger::UNKNOWN
|
116
|
+
return if @level < severity
|
117
|
+
|
118
|
+
message = clean(message || block.call)
|
119
|
+
@buffer << {:severity => severity, :body => clean(message)}
|
120
|
+
auto_flush
|
121
|
+
message
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
def auto_flush
|
126
|
+
flush if 0 == @auto_flushing || @auto_flushing <= @buffer.count
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# In Logger, this dumps the raw message; the closest equivalent
|
131
|
+
# would be Logger::UNKNOWN
|
132
|
+
def <<(message)
|
133
|
+
add(Logger::UNKNOWN, message)
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def close
|
138
|
+
# flush
|
139
|
+
# socket.close
|
140
|
+
# @socket[Thread.current] = nil
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# Flush buffered logs to Syslog
|
145
|
+
def flush
|
146
|
+
@buffer.each do |message|
|
147
|
+
log(message[:severity], message[:body])
|
148
|
+
end
|
149
|
+
@buffer.clear
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def socket
|
155
|
+
@socket[Thread.current] ||= TCPSocket.new(host, port)
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
protected
|
160
|
+
|
161
|
+
|
162
|
+
# Clean up messages so they're nice and pretty.
|
163
|
+
def clean(message)
|
164
|
+
message = message.to_s.dup
|
165
|
+
message.strip!
|
166
|
+
message.gsub!(/%/, '%%') # syslog(3) freaks on % (printf)
|
167
|
+
message.gsub!(/\e\[[^m]*m/, '') if @remove_ansi_colors # remove useless ansi color codes
|
168
|
+
return message
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def request_id
|
173
|
+
Thread.current.thread_variable_get(:http_request_id) || '1'
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
# send the message
|
178
|
+
def log(severity, message)
|
179
|
+
return if 0 == message.bytesize
|
180
|
+
|
181
|
+
retry_attempt ||= 0
|
182
|
+
|
183
|
+
message_chunks = self.format_message(severity, message)
|
184
|
+
Timeout::timeout(2, SocketTimeoutError) do
|
185
|
+
message_chunks.each do |chunk|
|
186
|
+
packet = chunk.rstrip + "\n"
|
187
|
+
socket.write(packet)
|
188
|
+
end
|
189
|
+
socket.flush
|
190
|
+
end
|
191
|
+
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE, SocketTimeoutError => e
|
192
|
+
retry_attempt += 1
|
193
|
+
|
194
|
+
@socket[Thread.current].close
|
195
|
+
@socket[Thread.current] = nil
|
196
|
+
retry if retry_attempt <= SOCKET_SEND_RETRY_ATTEMPTS
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
def format_message severity, message
|
201
|
+
message_marker = "<#{facility + LEVEL_LOGGER_MAP[severity]}>#{Time.now.strftime("%b %e %H:%M:%S")} #{hostname.rstrip} [#{program_name.rstrip}][#{request_id.rstrip}]: "
|
202
|
+
per_chunk_max_length = 1024 - (message_marker.bytesize + 1)
|
203
|
+
|
204
|
+
message.split("\n").inject([]) do |target_array, message_line|
|
205
|
+
message_line_chunk_count = (message_line.bytesize.to_f / per_chunk_max_length.to_f).ceil.to_i
|
206
|
+
message_line_chunk_count.times.each do |chunk_index|
|
207
|
+
target_array << message_marker + message_line.byteslice((chunk_index + 0) * per_chunk_max_length, per_chunk_max_length)
|
208
|
+
end
|
209
|
+
target_array
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BufferedRemoteSyslogLogger::TcpLogger do
|
4
|
+
|
5
|
+
describe '#format_message' do
|
6
|
+
|
7
|
+
context 'WHEN the message was longer than 1024 bytes' do
|
8
|
+
it 'should be sliced up into multible chunks' do
|
9
|
+
string = SecureRandom.hex(650)
|
10
|
+
chunks = BufferedRemoteSyslogLogger::TcpLogger.new.send(:format_message, 4, string)
|
11
|
+
|
12
|
+
prepend_length = `hostname`.rstrip.size + 57
|
13
|
+
|
14
|
+
chunks.size.should eq 2
|
15
|
+
chunks.first.size.should eq 1023
|
16
|
+
chunks[0].should =~ /#{string.byteslice(0, 1024 - prepend_length - 1)}/
|
17
|
+
chunks[1].should =~ /#{string.byteslice(1024 - prepend_length - 1, 1024 - prepend_length - 1)}/
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'WHEN the text contains newline characters' do
|
22
|
+
it 'should generate seperate chunks for those' do
|
23
|
+
string = "foo\nbar"
|
24
|
+
|
25
|
+
chunks = BufferedRemoteSyslogLogger::TcpLogger.new.send(:format_message, 4, string)
|
26
|
+
|
27
|
+
chunks.size.should eq 2
|
28
|
+
chunks[0].should =~ /foo/
|
29
|
+
chunks[1].should =~ /bar/
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe '#log' do
|
36
|
+
it 'should send the message along' do
|
37
|
+
socket = TCPSocket.new('127.0.0.1', 514)
|
38
|
+
TCPSocket.stub(:new).and_return(socket)
|
39
|
+
socket.should_receive(:write).with("<14>#{Time.now.strftime("%b %e %H:%M:%S")} #{`hostname`.rstrip} [buffered_remote_syslog_logger][1]: foo\n")
|
40
|
+
socket.stub(:flush)
|
41
|
+
logger = BufferedRemoteSyslogLogger::TcpLogger.new
|
42
|
+
logger.info('foo')
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'WHEN there was a connection error' do
|
46
|
+
it 'should retry several times' do
|
47
|
+
sockets = [TCPSocket.new('127.0.0.1', 514), TCPSocket.new('127.0.0.1', 514), TCPSocket.new('127.0.0.1', 514)]
|
48
|
+
TCPSocket.stub(:new) { sockets.shift }
|
49
|
+
sockets[0].should_receive(:write).with("<14>#{Time.now.strftime("%b %e %H:%M:%S")} #{`hostname`.rstrip} [buffered_remote_syslog_logger][1]: foo\n").and_raise(Errno::ECONNREFUSED.new)
|
50
|
+
sockets[1].should_receive(:write).with("<14>#{Time.now.strftime("%b %e %H:%M:%S")} #{`hostname`.rstrip} [buffered_remote_syslog_logger][1]: foo\n").and_raise(Errno::ECONNREFUSED.new)
|
51
|
+
sockets[2].should_receive(:write).with("<14>#{Time.now.strftime("%b %e %H:%M:%S")} #{`hostname`.rstrip} [buffered_remote_syslog_logger][1]: foo\n").and_raise(Errno::ECONNREFUSED.new)
|
52
|
+
Socket.any_instance.stub(:flush)
|
53
|
+
logger = BufferedRemoteSyslogLogger::TcpLogger.new
|
54
|
+
logger.info('foo')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
describe '#<<' do
|
61
|
+
it 'should simply forward to add' do
|
62
|
+
logger = BufferedRemoteSyslogLogger::TcpLogger.new
|
63
|
+
logger.should_receive(:add).with(5, 'meh')
|
64
|
+
logger << 'meh'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.adapters.define 'gem' do
|
5
|
+
add_filter '/spec/'
|
6
|
+
end
|
7
|
+
SimpleCov.start 'gem'
|
8
|
+
|
9
|
+
|
10
|
+
# require code after simplecov
|
11
|
+
require 'buffered_remote_syslog_logger'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
|
15
|
+
config.expect_with :rspec do |c|
|
16
|
+
c.syntax = :should
|
17
|
+
end
|
18
|
+
config.mock_with :rspec do |c|
|
19
|
+
c.syntax = :should
|
20
|
+
end
|
21
|
+
|
22
|
+
I18n.enforce_available_locales = false
|
23
|
+
config.mock_with :rspec
|
24
|
+
end
|
25
|
+
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: buffered_remote_syslog_logger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- DailyDeal Development
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - <
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - <
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.0'
|
97
|
+
description: centralize logging without interleaving in a remote syslog
|
98
|
+
email:
|
99
|
+
- dev@dailydeal.de
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- Gemfile
|
106
|
+
- Gemfile.lock
|
107
|
+
- LICENSE
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- buffered_remote_syslog_logger.gemspec
|
112
|
+
- lib/buffered_remote_syslog_logger.rb
|
113
|
+
- lib/buffered_remote_syslog_logger/middleware.rb
|
114
|
+
- lib/buffered_remote_syslog_logger/tcp_logger.rb
|
115
|
+
- lib/buffered_remote_syslog_logger/version.rb
|
116
|
+
- spec/lib/buffered_remote_syslog_logger/tcp_logger_spec.rb
|
117
|
+
- spec/lib/buffered_remote_syslog_logger_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
homepage: http://github.com/DailyDeal/buffered_remote_syslog_logger.git
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 2.2.2
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: centralize logging without interleaving in a remote syslog
|
143
|
+
test_files:
|
144
|
+
- spec/lib/buffered_remote_syslog_logger/tcp_logger_spec.rb
|
145
|
+
- spec/lib/buffered_remote_syslog_logger_spec.rb
|
146
|
+
- spec/spec_helper.rb
|