remote_syslog_sender_criteo 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2104968f2af1a9d3820df688db077437d21416d3dc765a0902b0123012f3ab65
4
+ data.tar.gz: bfb9a5545388613071aa3aed1b6764a58706de0bb7e65d709a17d8a1cd18d9de
5
+ SHA512:
6
+ metadata.gz: 610b4c3a537f0d3bb82cd104dc9804dbb2f8c0d883ef49ef09bcb0ee515fe71128c7983832db8d7d1610f7377e665380bb5a2ce0f20d89cc5645981ae4fa394a
7
+ data.tar.gz: 2ba10419c6cb0b531399975d6aac4dd9aea17ca48af0b0438e03d2c6dfe51e7aa43ef3a7e7117bdb4de3ccfda70c745b359b9e6448b2fb65d3c74a4a1b012cc8
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .bundle
3
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2017 joker1007
4
+ Original Copyright (c) 2011 Eric Lindvall
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Remote Syslog Sender
2
+
3
+ This gem is syslog sender that is extracted from [papertrail/remote_syslog_logger](https://github.com/papertrail/remote_syslog_logger)
4
+
5
+ This can send message to remote syslog server via UDP, TCP, TCP+TLS.
6
+ (Original does not support TCP, TCP+TLS protocol).
7
+
8
+ ## Installation
9
+
10
+ The easiest way to install `remote_syslog_sender` is with Bundler. Add
11
+ `remote_syslog_sender` to your `Gemfile`.
12
+
13
+ If you are not using a `Gemfile`, run:
14
+
15
+ $ [sudo] gem install remote_syslog_sender
16
+
17
+
18
+ ## Usage
19
+
20
+ ```ruby
21
+ sender = RemoteSyslogSender.new('syslog.domain.com', 514) # default protocol is UDP
22
+ sender.transmit("message body")
23
+ # or
24
+ sender.write("message body")
25
+
26
+
27
+ ## TCP
28
+ sender = RemoteSyslogSender.new('syslog.domain.com', 514, protocol: :tcp)
29
+ sender.transmit("message body")
30
+
31
+ ## TCP+TLS
32
+ sender = RemoteSyslogSender.new('syslog.domain.com', 514, protocol: :tcp, tls: true, ca_file: "custom_ca.pem")
33
+ sender.transmit("message body")
34
+ ```
35
+
36
+ To point the logs to your local system, use `localhost` and ensure that
37
+ the system's syslog daemon is bound to `127.0.0.1`.
38
+
39
+
40
+ ## Limitations
41
+
42
+ If the specified host cannot be resolved, `syslog.domain.com` in the
43
+ example under the usage section above, `remote_syslog_sender` will block
44
+ for approximately 20 seconds before displaying an error. This could
45
+ result in the application failing to start or even stopping responding.
46
+
47
+ Workarounds for this include:
48
+
49
+ * use an IP address instead of a hostname.
50
+ * put a hosts entry in `/etc/hosts` or equivalent, so that DNS is not
51
+ actually consulted
52
+ * instead of logging directly to the network, write to a file and
53
+ transmit new entries with a standalone daemon like
54
+ [remote_syslog](https://github.com/papertrail/remote_syslog),
55
+
56
+ ## Message length
57
+
58
+ All log lines are truncated to a maximum of 1024 characters. This restriction
59
+ comes from [RFC 3164 section 4.1][rfc-limit]:
60
+
61
+ > The total length of the packet MUST be 1024 bytes or less.
62
+
63
+ Additionally, the generally-accepted [MTU][] of the Internet is 1500 bytes, so
64
+ regardless of the RFC, UDP syslog packets longer than 1500 bytes would not
65
+ arrive. For details or to use TCP syslog for longer messages, see
66
+ [help.papertrailapp.com][troubleshoot].
67
+
68
+ [rfc-limit]: https://tools.ietf.org/html/rfc3164#section-4.1
69
+ [MTU]: (https://en.wikipedia.org/wiki/Maximum_transmission_unit)
70
+ [troubleshoot]: http://help.papertrailapp.com/kb/configuration/troubleshooting-remote-syslog-reachability/#message-length
71
+
72
+
73
+ ## Default program name
74
+
75
+ By default, the `program` value is set to the name and ID of the invoking
76
+ process. For example, `puma[12345]` or `rack[3456]`.
77
+
78
+ The `program` value is used to populate the syslog "tag" field, must be 32
79
+ or fewer characters. In a few cases, an artifact of how the app is launched
80
+ may lead to a default `program` value longer than 32 characters. For example,
81
+ the `thin` Web server may generate a default `program` value such
82
+ as:
83
+
84
+ thin server (0.0.0.0:3001)[11179]
85
+
86
+ If this occurs, the following exception will be raised when a
87
+ `RemoteSyslogSender` is instantiated:
88
+
89
+ Tag must not be longer than 32 characters (ArgumentError)
90
+
91
+ To remedy this, explicitly provide a `program` argument which is shorter than
92
+ 32 characters. See [Usage](#usage).
93
+
94
+
95
+ ## Contributing
96
+
97
+ Bug reports and pull requests are welcome on GitHub at https://github.com/reproio/remote_syslog_sender.
98
+
99
+
100
+ ## License
101
+
102
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,16 @@
1
+
2
+ require 'remote_syslog_sender/udp_sender'
3
+ require 'remote_syslog_sender/tcp_sender'
4
+
5
+ module RemoteSyslogSender
6
+ VERSION = '1.0.3'
7
+
8
+ def self.new(remote_hostname, remote_port, options = {})
9
+ protocol = options.delete(:protocol)
10
+ if protocol && protocol.to_sym == :tcp
11
+ TcpSender.new(remote_hostname, remote_port, options)
12
+ else
13
+ UdpSender.new(remote_hostname, remote_port, options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,73 @@
1
+ require 'socket'
2
+ require 'syslog_protocol'
3
+
4
+ module RemoteSyslogSender
5
+ class Sender
6
+ # To suppress initialize warning
7
+ class Packet < SyslogProtocol::Packet
8
+ def initialize(*)
9
+ super
10
+ @time = nil
11
+ end
12
+ end
13
+
14
+ attr_reader :socket
15
+ attr_accessor :packet
16
+
17
+ def initialize(remote_hostname, remote_port, options = {})
18
+ @remote_hostname = remote_hostname
19
+ @remote_port = remote_port
20
+ @whinyerrors = options[:whinyerrors]
21
+ @packet_size = options[:packet_size] || 1024
22
+
23
+ @packet = Packet.new
24
+
25
+ local_hostname = options[:hostname] || options[:local_hostname] || (Socket.gethostname rescue `hostname`.chomp)
26
+ local_hostname = 'localhost' if local_hostname.nil? || local_hostname.empty?
27
+ @packet.hostname = local_hostname
28
+
29
+ @packet.facility = options[:facility] || 'user'
30
+ @packet.severity = options[:severity] || 'notice'
31
+ @packet.tag = options[:tag] || options[:program] || "#{File.basename($0)}[#{$$}]"
32
+
33
+ @socket = nil
34
+ end
35
+
36
+ def transmit(message, packet_options = nil)
37
+ message.split(/\r?\n/).each do |line|
38
+ begin
39
+ next if line =~ /^\s*$/
40
+ packet = @packet.dup
41
+ if packet_options
42
+ packet.tag = packet_options[:program] if packet_options[:program]
43
+ packet.hostname = packet_options[:local_hostname] if packet_options[:local_hostname]
44
+ %i(hostname facility severity tag).each do |key|
45
+ packet.send("#{key}=", packet_options[key]) if packet_options[key]
46
+ end
47
+ end
48
+ packet.content = line
49
+ send_msg(packet.assemble(@packet_size))
50
+ rescue
51
+ if @whinyerrors
52
+ raise
53
+ else
54
+ $stderr.puts "#{self.class} error: #{$!.class}: #{$!}\nOriginal message: #{line}"
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ # Make this act a little bit like an `IO` object
61
+ alias_method :write, :transmit
62
+
63
+ def close
64
+ @socket.close
65
+ end
66
+
67
+ private
68
+
69
+ def send_msg(payload)
70
+ raise NotImplementedError, "please override"
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,155 @@
1
+ require 'socket'
2
+ require 'syslog_protocol'
3
+ require 'remote_syslog_sender/sender'
4
+
5
+ module RemoteSyslogSender
6
+ class TcpSender < Sender
7
+ class NonBlockingTimeout < StandardError; end
8
+
9
+ def initialize(remote_hostname, remote_port, options = {})
10
+ super
11
+ @tls = options[:tls]
12
+ @retry_limit = options[:retry_limit] || 3
13
+ @retry_interval = options[:retry_interval] || 0.5
14
+ @remote_hostname = remote_hostname
15
+ @remote_port = remote_port
16
+ @ssl_method = options[:ssl_method] || 'TLSv1_2'
17
+ @ca_file = options[:ca_file]
18
+ @verify_mode = options[:verify_mode]
19
+ @timeout = options[:timeout] || 600
20
+ @timeout_exception = !!options[:timeout_exception]
21
+ @exponential_backoff = !!options[:exponential_backoff]
22
+
23
+ @mutex = Mutex.new
24
+ @tcp_socket = nil
25
+
26
+ if [:SOL_SOCKET, :SO_KEEPALIVE, :IPPROTO_TCP, :TCP_KEEPIDLE].all? {|c| Socket.const_defined? c}
27
+ @keep_alive = options[:keep_alive]
28
+ end
29
+ if Socket.const_defined?(:TCP_KEEPIDLE)
30
+ @keep_alive_idle = options[:keep_alive_idle]
31
+ end
32
+ if Socket.const_defined?(:TCP_KEEPCNT)
33
+ @keep_alive_cnt = options[:keep_alive_cnt]
34
+ end
35
+ if Socket.const_defined?(:TCP_KEEPINTVL)
36
+ @keep_alive_intvl = options[:keep_alive_intvl]
37
+ end
38
+ connect
39
+ end
40
+
41
+ def close
42
+ @socket.close if @socket
43
+ @tcp_socket.close if @tcp_socket
44
+ end
45
+
46
+ private
47
+
48
+ def connect
49
+ connect_retry_count = 0
50
+ connect_retry_limit = 3
51
+ connect_retry_interval = 1
52
+ @mutex.synchronize do
53
+ begin
54
+ close
55
+
56
+ @tcp_socket = TCPSocket.new(@remote_hostname, @remote_port)
57
+
58
+ if @keep_alive
59
+ @tcp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
60
+ @tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, @keep_alive_idle) if @keep_alive_idle
61
+ @tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, @keep_alive_cnt) if @keep_alive_cnt
62
+ @tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, @keep_alive_intvl) if @keep_alive_intvl
63
+ end
64
+ if @tls
65
+ require 'openssl'
66
+ context = OpenSSL::SSL::SSLContext.new(@ssl_method)
67
+ context.ca_file = @ca_file if @ca_file
68
+ context.verify_mode = @verify_mode if @verify_mode
69
+
70
+ @socket = OpenSSL::SSL::SSLSocket.new(@tcp_socket, context)
71
+ @socket.connect
72
+ @socket.post_connection_check(@remote_hostname)
73
+ raise "verification error" if @socket.verify_result != OpenSSL::X509::V_OK
74
+ else
75
+ @socket = @tcp_socket
76
+ end
77
+ rescue
78
+ if connect_retry_count < connect_retry_limit
79
+ sleep connect_retry_interval
80
+ connect_retry_count += 1
81
+ retry
82
+ else
83
+ raise
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ def send_msg(payload)
90
+ if @timeout && @timeout >= 0
91
+ method = :write_nonblock
92
+ else
93
+ method = :write
94
+ end
95
+
96
+ retry_limit = @retry_limit.to_i
97
+ retry_interval = @retry_interval.to_f
98
+ retry_count = 0
99
+
100
+ payload << "\n"
101
+ payload.force_encoding(Encoding::ASCII_8BIT)
102
+ payload_size = payload.bytesize
103
+
104
+ until payload_size <= 0
105
+ start = get_time
106
+ begin
107
+ result = @mutex.synchronize { @socket.__send__(method, payload) }
108
+ payload_size -= result
109
+ payload.slice!(0, result) if payload_size > 0
110
+ rescue IO::WaitReadable
111
+ timeout_wait = @timeout - (get_time - start)
112
+ retry if IO.select([@socket], nil, nil, timeout_wait)
113
+
114
+ raise NonBlockingTimeout if @timeout_exception
115
+ break
116
+ rescue IO::WaitWritable
117
+ timeout_wait = @timeout - (get_time - start)
118
+ retry if IO.select(nil, [@socket], nil, timeout_wait)
119
+
120
+ raise NonBlockingTimeout if @timeout_exception
121
+ break
122
+ rescue
123
+ if retry_count < retry_limit
124
+ sleep retry_interval
125
+ retry_count += 1
126
+ retry_interval *= 2 if @exponential_backoff
127
+ connect
128
+ retry
129
+ else
130
+ raise
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ POSIX_CLOCK =
137
+ if defined?(Process::CLOCK_MONOTONIC_COARSE)
138
+ Process::CLOCK_MONOTONIC_COARSE
139
+ elsif defined?(Process::CLOCK_MONOTONIC)
140
+ Process::CLOCK_MONOTONIC
141
+ elsif defined?(Process::CLOCK_REALTIME_COARSE)
142
+ Process::CLOCK_REALTIME_COARSE
143
+ elsif defined?(Process::CLOCK_REALTIME)
144
+ Process::CLOCK_REALTIME
145
+ end
146
+
147
+ def get_time
148
+ if POSIX_CLOCK
149
+ Process.clock_gettime(POSIX_CLOCK)
150
+ else
151
+ Time.now.to_f
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,18 @@
1
+ require 'socket'
2
+ require 'syslog_protocol'
3
+ require 'remote_syslog_sender/sender'
4
+
5
+ module RemoteSyslogSender
6
+ class UdpSender < Sender
7
+ def initialize(remote_hostname, remote_port, options = {})
8
+ super
9
+ @socket = UDPSocket.new
10
+ end
11
+
12
+ private
13
+
14
+ def send_msg(payload)
15
+ @socket.send(payload, 0, @remote_hostname, @remote_port)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'remote_syslog_sender_criteo'
3
+ s.version = '1.2.1'
4
+ s.summary = "Message sender that sends directly to a remote syslog endpoint"
5
+ s.description = "Message sender that sends directly to a remote syslog endpoint (Support UDP, TCP, TCP+TLS)"
6
+
7
+ s.authors = ["Tomohiro Hashidate", "Eric Lindvall"]
8
+ s.email = 'kakyoin.hierophant@gmail.com'
9
+ s.homepage = 'https://github.com/reproio/remote_syslog_logger'
10
+
11
+ s.files = `git ls-files -z`.split("\x0")
12
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
13
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ s.require_paths = %w[lib]
15
+
16
+ s.add_runtime_dependency 'syslog_protocol_criteo'
17
+
18
+ s.add_development_dependency "bundler", "~> 1.6"
19
+ s.add_development_dependency "rake"
20
+ s.add_development_dependency "test-unit"
21
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ unless ENV['BUNDLE_GEMFILE']
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ Bundler.setup
7
+ Bundler.require
8
+ end
9
+
10
+ require 'remote_syslog_sender'
11
+
12
+ require 'test/unit'
@@ -0,0 +1,66 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class TestRemoteSyslogSender < Test::Unit::TestCase
4
+ def setup
5
+ @server_port = rand(50000) + 1024
6
+ @socket = UDPSocket.new
7
+ @socket.bind('127.0.0.1', @server_port)
8
+
9
+ @tcp_server = TCPServer.open('127.0.0.1', 0)
10
+ @tcp_server_port = @tcp_server.addr[1]
11
+
12
+ @tcp_server_wait_thread = Thread.start do
13
+ @tcp_server.accept
14
+ end
15
+ end
16
+
17
+ def teardown
18
+ @socket.close
19
+ @tcp_server.close
20
+ end
21
+
22
+ def test_sender
23
+ @sender = RemoteSyslogSender.new('127.0.0.1', @server_port)
24
+ @sender.write "This is a test"
25
+
26
+ message, _ = *@socket.recvfrom(1024)
27
+ assert_match(/This is a test/, message)
28
+ end
29
+
30
+ def test_sender_long_payload
31
+ @sender = RemoteSyslogSender.new('127.0.0.1', @server_port, packet_size: 10240)
32
+ @sender.write "abcdefgh" * 1000
33
+
34
+ message, _ = *@socket.recvfrom(10240)
35
+ assert_match(/#{"abcdefgh" * 1000}/, message)
36
+ end
37
+
38
+ def test_sender_tcp
39
+ @sender = RemoteSyslogSender.new('127.0.0.1', @tcp_server_port, protocol: :tcp)
40
+ @sender.write "This is a test"
41
+ sock = @tcp_server_wait_thread.value
42
+
43
+ message, _ = *sock.recvfrom(1024)
44
+ assert_match(/This is a test/, message)
45
+ end
46
+
47
+ def test_sender_tcp_nonblock
48
+ @sender = RemoteSyslogSender.new('127.0.0.1', @tcp_server_port, protocol: :tcp, timeout: 20)
49
+ @sender.write "This is a test"
50
+ sock = @tcp_server_wait_thread.value
51
+
52
+ message, _ = *sock.recvfrom(1024)
53
+ assert_match(/This is a test/, message)
54
+ end
55
+
56
+ def test_sender_multiline
57
+ @sender = RemoteSyslogSender.new('127.0.0.1', @server_port)
58
+ @sender.write "This is a test\nThis is the second line"
59
+
60
+ message, _ = *@socket.recvfrom(1024)
61
+ assert_match(/This is a test/, message)
62
+
63
+ message, _ = *@socket.recvfrom(1024)
64
+ assert_match(/This is the second line/, message)
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remote_syslog_sender_criteo
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Tomohiro Hashidate
8
+ - Eric Lindvall
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-05-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: syslog_protocol_criteo
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.6'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.6'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: test-unit
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Message sender that sends directly to a remote syslog endpoint (Support
71
+ UDP, TCP, TCP+TLS)
72
+ email: kakyoin.hierophant@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - lib/remote_syslog_sender.rb
83
+ - lib/remote_syslog_sender/sender.rb
84
+ - lib/remote_syslog_sender/tcp_sender.rb
85
+ - lib/remote_syslog_sender/udp_sender.rb
86
+ - remote_syslog_sender.gemspec
87
+ - test/helper.rb
88
+ - test/test_remote_syslog_logger.rb
89
+ homepage: https://github.com/reproio/remote_syslog_logger
90
+ licenses: []
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubygems_version: 3.0.3
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Message sender that sends directly to a remote syslog endpoint
111
+ test_files:
112
+ - test/helper.rb
113
+ - test/test_remote_syslog_logger.rb