logstash-logger-yajl 0.27.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 +21 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +26 -0
- data/Appraisals +23 -0
- data/CHANGELOG.md +203 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +880 -0
- data/Rakefile +23 -0
- data/gemfiles/rails_3.2.gemfile +9 -0
- data/gemfiles/rails_4.0.gemfile +9 -0
- data/gemfiles/rails_4.1.gemfile +9 -0
- data/gemfiles/rails_4.2.gemfile +9 -0
- data/gemfiles/rails_5.0.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +9 -0
- data/lib/logstash-event.rb +1 -0
- data/lib/logstash-logger.rb +11 -0
- data/lib/logstash-logger/buffer.rb +336 -0
- data/lib/logstash-logger/configuration.rb +29 -0
- data/lib/logstash-logger/device.rb +67 -0
- data/lib/logstash-logger/device/aws_stream.rb +94 -0
- data/lib/logstash-logger/device/balancer.rb +40 -0
- data/lib/logstash-logger/device/base.rb +73 -0
- data/lib/logstash-logger/device/connectable.rb +131 -0
- data/lib/logstash-logger/device/file.rb +23 -0
- data/lib/logstash-logger/device/firehose.rb +42 -0
- data/lib/logstash-logger/device/io.rb +11 -0
- data/lib/logstash-logger/device/kafka.rb +57 -0
- data/lib/logstash-logger/device/kinesis.rb +44 -0
- data/lib/logstash-logger/device/multi_delegator.rb +36 -0
- data/lib/logstash-logger/device/redis.rb +69 -0
- data/lib/logstash-logger/device/socket.rb +21 -0
- data/lib/logstash-logger/device/stderr.rb +13 -0
- data/lib/logstash-logger/device/stdout.rb +14 -0
- data/lib/logstash-logger/device/tcp.rb +86 -0
- data/lib/logstash-logger/device/udp.rb +12 -0
- data/lib/logstash-logger/device/unix.rb +18 -0
- data/lib/logstash-logger/formatter.rb +51 -0
- data/lib/logstash-logger/formatter/base.rb +73 -0
- data/lib/logstash-logger/formatter/cee.rb +11 -0
- data/lib/logstash-logger/formatter/cee_syslog.rb +22 -0
- data/lib/logstash-logger/formatter/json.rb +11 -0
- data/lib/logstash-logger/formatter/json_lines.rb +11 -0
- data/lib/logstash-logger/formatter/logstash_event.rb +6 -0
- data/lib/logstash-logger/logger.rb +106 -0
- data/lib/logstash-logger/multi_logger.rb +153 -0
- data/lib/logstash-logger/railtie.rb +51 -0
- data/lib/logstash-logger/silenced_logging.rb +83 -0
- data/lib/logstash-logger/tagged_logging.rb +40 -0
- data/lib/logstash-logger/version.rb +3 -0
- data/lib/logstash/event.rb +272 -0
- data/lib/logstash/namespace.rb +15 -0
- data/lib/logstash/util.rb +105 -0
- data/lib/logstash/util/fieldreference.rb +49 -0
- data/logstash-logger.gemspec +42 -0
- data/samples/example.crt +16 -0
- data/samples/example.key +15 -0
- data/samples/file.conf +11 -0
- data/samples/redis.conf +12 -0
- data/samples/ssl.conf +15 -0
- data/samples/syslog.conf +10 -0
- data/samples/tcp.conf +11 -0
- data/samples/udp.conf +11 -0
- data/samples/unix.conf +11 -0
- data/spec/configuration_spec.rb +27 -0
- data/spec/constructor_spec.rb +30 -0
- data/spec/device/balancer_spec.rb +31 -0
- data/spec/device/connectable_spec.rb +74 -0
- data/spec/device/file_spec.rb +15 -0
- data/spec/device/firehose_spec.rb +41 -0
- data/spec/device/io_spec.rb +13 -0
- data/spec/device/kafka_spec.rb +32 -0
- data/spec/device/kinesis_spec.rb +41 -0
- data/spec/device/multi_delegator_spec.rb +31 -0
- data/spec/device/redis_spec.rb +52 -0
- data/spec/device/socket_spec.rb +15 -0
- data/spec/device/stderr_spec.rb +16 -0
- data/spec/device/stdout_spec.rb +31 -0
- data/spec/device/tcp_spec.rb +120 -0
- data/spec/device/udp_spec.rb +9 -0
- data/spec/device/unix_spec.rb +23 -0
- data/spec/device_spec.rb +97 -0
- data/spec/formatter/base_spec.rb +125 -0
- data/spec/formatter/cee_spec.rb +15 -0
- data/spec/formatter/cee_syslog_spec.rb +43 -0
- data/spec/formatter/json_lines_spec.rb +14 -0
- data/spec/formatter/json_spec.rb +10 -0
- data/spec/formatter/logstash_event_spec.rb +10 -0
- data/spec/formatter_spec.rb +79 -0
- data/spec/logger_spec.rb +128 -0
- data/spec/logstash_event_spec.rb +139 -0
- data/spec/multi_logger_spec.rb +59 -0
- data/spec/rails_spec.rb +91 -0
- data/spec/silenced_logging_spec.rb +31 -0
- data/spec/spec_helper.rb +111 -0
- data/spec/syslog_spec.rb +32 -0
- data/spec/tagged_logging_spec.rb +32 -0
- metadata +385 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'poseidon'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class Kafka < Connectable
|
6
|
+
|
7
|
+
DEFAULT_HOST = 'localhost'
|
8
|
+
DEFAULT_PORT = 9092
|
9
|
+
DEFAULT_TOPIC = 'logstash'
|
10
|
+
DEFAULT_PRODUCER = 'logstash-logger'
|
11
|
+
DEFAULT_BACKOFF = 1
|
12
|
+
|
13
|
+
attr_accessor :hosts, :topic, :producer, :backoff
|
14
|
+
|
15
|
+
def initialize(opts)
|
16
|
+
super
|
17
|
+
host = opts[:host] || DEFAULT_HOST
|
18
|
+
port = opts[:port] || DEFAULT_PORT
|
19
|
+
@hosts = opts[:hosts] || host.split(',').map { |h| "#{h}:#{port}" }
|
20
|
+
@topic = opts[:path] || DEFAULT_TOPIC
|
21
|
+
@producer = opts[:producer] || DEFAULT_PRODUCER
|
22
|
+
@backoff = opts[:backoff] || DEFAULT_BACKOFF
|
23
|
+
@buffer_group = @topic
|
24
|
+
end
|
25
|
+
|
26
|
+
def connect
|
27
|
+
@io = ::Poseidon::Producer.new(@hosts, @producer)
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_connection
|
31
|
+
connect unless connected?
|
32
|
+
yield
|
33
|
+
rescue ::Poseidon::Errors::ChecksumError, Poseidon::Errors::UnableToFetchMetadata => e
|
34
|
+
log_error(e)
|
35
|
+
log_warning("reconnect/retry")
|
36
|
+
sleep backoff if backoff
|
37
|
+
reconnect
|
38
|
+
retry
|
39
|
+
rescue => e
|
40
|
+
log_error(e)
|
41
|
+
log_warning("giving up")
|
42
|
+
close(flush: false)
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_batch(messages, topic = nil)
|
46
|
+
topic ||= @topic
|
47
|
+
with_connection do
|
48
|
+
@io.send_messages messages.map { |message| Poseidon::MessageToSend.new(topic, message) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_one(message, topic = nil)
|
53
|
+
write_batch([message], topic)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
begin
|
2
|
+
require 'aws-sdk-kinesis'
|
3
|
+
rescue LoadError
|
4
|
+
require 'aws-sdk'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'logstash-logger/device/aws_stream'
|
8
|
+
|
9
|
+
module LogStashLogger
|
10
|
+
module Device
|
11
|
+
class Kinesis < AwsStream
|
12
|
+
@stream_class = ::Aws::Kinesis::Client
|
13
|
+
@recoverable_error_codes = [
|
14
|
+
"ServiceUnavailable",
|
15
|
+
"Throttling",
|
16
|
+
"RequestExpired",
|
17
|
+
"ProvisionedThroughputExceededException"
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def transform_message(message)
|
21
|
+
{
|
22
|
+
data: message,
|
23
|
+
partition_key: SecureRandom.uuid
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def put_records(records)
|
28
|
+
@io.put_records({
|
29
|
+
records: records,
|
30
|
+
stream_name: @stream
|
31
|
+
})
|
32
|
+
end
|
33
|
+
|
34
|
+
def is_successful_response(resp)
|
35
|
+
resp.failed_record_count == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_response_records(resp)
|
39
|
+
resp.records
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Container to allow writes to multiple devices
|
2
|
+
|
3
|
+
# Code originally from:
|
4
|
+
# http://stackoverflow.com/a/6410202
|
5
|
+
|
6
|
+
module LogStashLogger
|
7
|
+
module Device
|
8
|
+
class MultiDelegator < Base
|
9
|
+
attr_reader :devices
|
10
|
+
|
11
|
+
def initialize(opts)
|
12
|
+
@io = self
|
13
|
+
@devices = create_devices(opts)
|
14
|
+
self.class.delegate(:write, :close, :close!, :flush)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def create_devices(opts)
|
20
|
+
output_configurations = opts.delete(:outputs)
|
21
|
+
output_configurations.map do |device_opts|
|
22
|
+
device_opts = opts.merge(device_opts)
|
23
|
+
Device.new(device_opts)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.delegate(*methods)
|
28
|
+
methods.each do |m|
|
29
|
+
define_method(m) do |*args|
|
30
|
+
@devices.each { |device| device.send(m, *args) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class Redis < Connectable
|
6
|
+
DEFAULT_LIST = 'logstash'
|
7
|
+
|
8
|
+
attr_accessor :list
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
super
|
12
|
+
@list = opts.delete(:list) || DEFAULT_LIST
|
13
|
+
@buffer_group = @list
|
14
|
+
|
15
|
+
normalize_path(opts)
|
16
|
+
|
17
|
+
@redis_options = opts
|
18
|
+
end
|
19
|
+
|
20
|
+
def connect
|
21
|
+
@io = ::Redis.new(@redis_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def reconnect
|
25
|
+
@io.client.reconnect
|
26
|
+
rescue => e
|
27
|
+
log_error(e)
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_connection
|
31
|
+
connect unless connected?
|
32
|
+
yield
|
33
|
+
rescue ::Redis::InheritedError
|
34
|
+
reconnect
|
35
|
+
retry
|
36
|
+
rescue => e
|
37
|
+
log_error(e)
|
38
|
+
close(flush: false)
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_batch(messages, list = nil)
|
43
|
+
list ||= @list
|
44
|
+
with_connection do
|
45
|
+
@io.rpush(list, messages)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def write_one(message, list = nil)
|
50
|
+
write_batch(message, list)
|
51
|
+
end
|
52
|
+
|
53
|
+
def close!
|
54
|
+
@io && @io.quit
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def normalize_path(opts)
|
60
|
+
path = opts.fetch(:path, nil)
|
61
|
+
if path
|
62
|
+
opts[:db] = path.gsub("/", "").to_i unless path.empty?
|
63
|
+
opts.delete(:path)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class Socket < Connectable
|
6
|
+
DEFAULT_HOST = '0.0.0.0'
|
7
|
+
|
8
|
+
attr_reader :host, :port
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
super
|
12
|
+
@port = opts[:port] || fail(ArgumentError, "Port is required")
|
13
|
+
@host = opts[:host] || DEFAULT_HOST
|
14
|
+
end
|
15
|
+
|
16
|
+
def unrecoverable_error?(e)
|
17
|
+
e.is_a?(Errno::EMSGSIZE) || super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class TCP < Socket
|
6
|
+
attr_reader :ssl_certificate
|
7
|
+
|
8
|
+
def initialize(opts)
|
9
|
+
super
|
10
|
+
|
11
|
+
@ssl_certificate = opts[:ssl_certificate]
|
12
|
+
@ssl_context = opts[:ssl_context]
|
13
|
+
@use_ssl = !!(@ssl_certificate || opts[:ssl_context])
|
14
|
+
@use_ssl = opts[:ssl_enable] if opts.has_key? :ssl_enable
|
15
|
+
if opts.has_key?(:use_ssl)
|
16
|
+
@use_ssl = opts[:use_ssl]
|
17
|
+
warn "[LogStashLogger] The use_ssl option is deprecated. Use ssl_enable instead."
|
18
|
+
end
|
19
|
+
@verify_hostname = opts.fetch(:verify_hostname, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def ssl_context
|
23
|
+
return unless use_ssl?
|
24
|
+
@ssl_context || certificate_context
|
25
|
+
end
|
26
|
+
|
27
|
+
def use_ssl?
|
28
|
+
@use_ssl
|
29
|
+
end
|
30
|
+
|
31
|
+
def connect
|
32
|
+
if use_ssl?
|
33
|
+
io.connect
|
34
|
+
verify_hostname!
|
35
|
+
end
|
36
|
+
io
|
37
|
+
end
|
38
|
+
|
39
|
+
def io
|
40
|
+
@io ||= if use_ssl?
|
41
|
+
ssl_io
|
42
|
+
else
|
43
|
+
tcp_io
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def tcp_io
|
50
|
+
TCPSocket.new(@host, @port).tap do |socket|
|
51
|
+
socket.sync = sync unless sync.nil?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def ssl_io
|
56
|
+
ssl_context ?
|
57
|
+
OpenSSL::SSL::SSLSocket.new(tcp_io, ssl_context) :
|
58
|
+
OpenSSL::SSL::SSLSocket.new(tcp_io)
|
59
|
+
end
|
60
|
+
|
61
|
+
def certificate_context
|
62
|
+
return unless @ssl_certificate
|
63
|
+
@certificate_context ||= OpenSSL::SSL::SSLContext.new.tap do |ctx|
|
64
|
+
ctx.set_params(cert: @ssl_certificate)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def verify_hostname?
|
69
|
+
return false unless ssl_context
|
70
|
+
!! @verify_hostname
|
71
|
+
end
|
72
|
+
|
73
|
+
def verify_hostname!
|
74
|
+
@io.post_connection_check(hostname) if verify_hostname?
|
75
|
+
end
|
76
|
+
|
77
|
+
def hostname
|
78
|
+
if String === @verify_hostname
|
79
|
+
@verify_hostname
|
80
|
+
else
|
81
|
+
@host
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class Unix < Connectable
|
6
|
+
def initialize(opts={})
|
7
|
+
super
|
8
|
+
@path = opts[:path] || fail(ArgumentError, "Path is required")
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect
|
12
|
+
@io = ::UNIXSocket.new(@path).tap do |socket|
|
13
|
+
socket.sync = sync unless sync.nil?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'logstash-logger/formatter/base'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Formatter
|
5
|
+
DEFAULT_FORMATTER = :json_lines
|
6
|
+
|
7
|
+
autoload :LogStashEvent, 'logstash-logger/formatter/logstash_event'
|
8
|
+
autoload :Json, 'logstash-logger/formatter/json'
|
9
|
+
autoload :JsonLines, 'logstash-logger/formatter/json_lines'
|
10
|
+
autoload :Cee, 'logstash-logger/formatter/cee'
|
11
|
+
autoload :CeeSyslog, 'logstash-logger/formatter/cee_syslog'
|
12
|
+
|
13
|
+
def self.new(formatter_type, customize_event: nil)
|
14
|
+
build_formatter(formatter_type, customize_event)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.build_formatter(formatter_type, customize_event)
|
18
|
+
formatter_type ||= DEFAULT_FORMATTER
|
19
|
+
|
20
|
+
formatter = if custom_formatter_instance?(formatter_type)
|
21
|
+
formatter_type
|
22
|
+
elsif custom_formatter_class?(formatter_type)
|
23
|
+
formatter_type.new
|
24
|
+
else
|
25
|
+
formatter_klass(formatter_type).new(customize_event: customize_event)
|
26
|
+
end
|
27
|
+
|
28
|
+
formatter.send(:extend, ::LogStashLogger::TaggedLogging::Formatter)
|
29
|
+
formatter
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.formatter_klass(formatter_type)
|
33
|
+
case formatter_type.to_sym
|
34
|
+
when :json_lines then JsonLines
|
35
|
+
when :json then Json
|
36
|
+
when :logstash_event then LogStashEvent
|
37
|
+
when :cee then Cee
|
38
|
+
when :cee_syslog then CeeSyslog
|
39
|
+
else fail ArgumentError, 'Invalid formatter'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.custom_formatter_instance?(formatter_type)
|
44
|
+
formatter_type.respond_to?(:call)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.custom_formatter_class?(formatter_type)
|
48
|
+
formatter_type.is_a?(Class) && formatter_type.method_defined?(:call)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|