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