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,67 @@
|
|
1
|
+
require 'logstash-logger/device/base'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
DEFAULT_TYPE = :udp
|
6
|
+
|
7
|
+
autoload :Base, 'logstash-logger/device/base'
|
8
|
+
autoload :Connectable, 'logstash-logger/device/connectable'
|
9
|
+
autoload :Socket, 'logstash-logger/device/socket'
|
10
|
+
autoload :UDP, 'logstash-logger/device/udp'
|
11
|
+
autoload :TCP, 'logstash-logger/device/tcp'
|
12
|
+
autoload :Unix, 'logstash-logger/device/unix'
|
13
|
+
autoload :Redis, 'logstash-logger/device/redis'
|
14
|
+
autoload :Kafka, 'logstash-logger/device/kafka'
|
15
|
+
autoload :Kinesis, 'logstash-logger/device/kinesis'
|
16
|
+
autoload :Firehose, 'logstash-logger/device/firehose'
|
17
|
+
autoload :File, 'logstash-logger/device/file'
|
18
|
+
autoload :IO, 'logstash-logger/device/io'
|
19
|
+
autoload :Stdout, 'logstash-logger/device/stdout'
|
20
|
+
autoload :Stderr, 'logstash-logger/device/stderr'
|
21
|
+
autoload :Balancer, 'logstash-logger/device/balancer'
|
22
|
+
autoload :MultiDelegator, 'logstash-logger/device/multi_delegator'
|
23
|
+
|
24
|
+
def self.new(opts)
|
25
|
+
opts = opts.dup
|
26
|
+
build_device(opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build_device(opts)
|
30
|
+
if parsed_uri_opts = parse_uri_config(opts)
|
31
|
+
opts.delete(:uri)
|
32
|
+
opts.merge!(parsed_uri_opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
type = opts.delete(:type) || DEFAULT_TYPE
|
36
|
+
|
37
|
+
device_klass_for(type).new(opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse_uri_config(opts)
|
41
|
+
if uri = opts[:uri]
|
42
|
+
require 'uri'
|
43
|
+
parsed = ::URI.parse(uri)
|
44
|
+
{type: parsed.scheme, host: parsed.host, port: parsed.port, path: parsed.path}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.device_klass_for(type)
|
49
|
+
case type.to_sym
|
50
|
+
when :udp then UDP
|
51
|
+
when :tcp then TCP
|
52
|
+
when :unix then Unix
|
53
|
+
when :file then File
|
54
|
+
when :redis then Redis
|
55
|
+
when :kafka then Kafka
|
56
|
+
when :kinesis then Kinesis
|
57
|
+
when :firehose then Firehose
|
58
|
+
when :io then IO
|
59
|
+
when :stdout then Stdout
|
60
|
+
when :stderr then Stderr
|
61
|
+
when :multi_delegator then MultiDelegator
|
62
|
+
when :balancer then Balancer
|
63
|
+
else fail ArgumentError, 'Invalid device type'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
begin
|
2
|
+
require 'aws-sdk-core'
|
3
|
+
rescue LoadError
|
4
|
+
require 'aws-sdk'
|
5
|
+
end
|
6
|
+
|
7
|
+
module LogStashLogger
|
8
|
+
module Device
|
9
|
+
class AwsStream < Connectable
|
10
|
+
|
11
|
+
DEFAULT_STREAM = 'logstash'
|
12
|
+
|
13
|
+
@stream_class = nil
|
14
|
+
@recoverable_error_codes = []
|
15
|
+
|
16
|
+
class << self
|
17
|
+
attr_accessor :stream_class, :recoverable_error_codes
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :aws_region, :stream
|
21
|
+
|
22
|
+
def initialize(opts)
|
23
|
+
super
|
24
|
+
@access_key_id = opts[:aws_access_key_id]
|
25
|
+
@secret_access_key = opts[:aws_secret_access_key]
|
26
|
+
@aws_region = opts[:aws_region]
|
27
|
+
@stream = opts[:stream] || DEFAULT_STREAM
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform_message(message)
|
31
|
+
fail NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
def put_records(records)
|
35
|
+
fail NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_successful_response(resp)
|
39
|
+
fail NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_response_records(resp)
|
43
|
+
fail NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
def connect
|
47
|
+
client_opts = {}
|
48
|
+
client_opts[:credentials] = Aws::Credentials.new(@access_key_id, @secret_access_key) unless @access_key_id == nil || @secret_access_key == nil
|
49
|
+
client_opts[:region] = @aws_region unless @aws_region == nil
|
50
|
+
@io = self.class.stream_class.new(client_opts)
|
51
|
+
end
|
52
|
+
|
53
|
+
def with_connection
|
54
|
+
connect unless connected?
|
55
|
+
yield
|
56
|
+
rescue => e
|
57
|
+
log_error(e)
|
58
|
+
log_warning("giving up")
|
59
|
+
close(flush: false)
|
60
|
+
end
|
61
|
+
|
62
|
+
def write_batch(messages, group = nil)
|
63
|
+
records = messages.map{ |m| transform_message(m) }
|
64
|
+
|
65
|
+
with_connection do
|
66
|
+
resp = put_records(records)
|
67
|
+
|
68
|
+
# Put any failed records back into the buffer
|
69
|
+
if !is_successful_response(resp)
|
70
|
+
get_response_records(resp).each_with_index do |record, index|
|
71
|
+
if self.class.recoverable_error_codes.include?(record.error_code)
|
72
|
+
log_warning("Failed to post record using #{self.class.stream_class.name} with error: #{record.error_code} #{record.error_message}")
|
73
|
+
log_warning("Retrying")
|
74
|
+
write(records[index][:data])
|
75
|
+
elsif !record.error_code.nil? && record.error_code != ''
|
76
|
+
log_error("Failed to post record using #{self.class.stream_class.name} with error: #{record.error_code} #{record.error_message}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def write_one(message)
|
84
|
+
write_batch([message])
|
85
|
+
end
|
86
|
+
|
87
|
+
def close!
|
88
|
+
@io = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module LogStashLogger
|
2
|
+
module Device
|
3
|
+
class Balancer < Base
|
4
|
+
attr_reader :devices
|
5
|
+
|
6
|
+
def initialize(opts)
|
7
|
+
@io = self
|
8
|
+
@devices = create_devices(opts[:outputs])
|
9
|
+
self.class.delegate_to_all(:close, :close!, :flush)
|
10
|
+
self.class.delegate_to_one(:write)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def create_devices(opts)
|
16
|
+
opts.map { |device_opts| Device.new(device_opts) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.delegate_to_all(*methods)
|
20
|
+
methods.each do |m|
|
21
|
+
define_method(m) do |*args|
|
22
|
+
devices.each { |device| device.send(m, *args) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.delegate_to_one(*methods)
|
28
|
+
methods.each do |m|
|
29
|
+
define_method(m) do |*args|
|
30
|
+
select_device.send(m, *args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def select_device
|
36
|
+
devices.sample
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module LogStashLogger
|
2
|
+
module Device
|
3
|
+
class Base
|
4
|
+
attr_reader :io
|
5
|
+
attr_accessor :sync
|
6
|
+
attr_accessor :error_logger
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@sync = opts[:sync]
|
10
|
+
@error_logger = opts.fetch(:error_logger, LogStashLogger.configuration.default_error_logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_io
|
14
|
+
@io
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(message)
|
18
|
+
write_one(message) unless message.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def write_one(message)
|
22
|
+
@io.write(message)
|
23
|
+
rescue => e
|
24
|
+
if unrecoverable_error?(e)
|
25
|
+
log_error(e)
|
26
|
+
log_warning("unrecoverable error, aborting write")
|
27
|
+
else
|
28
|
+
raise
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_batch(messages, group = nil)
|
33
|
+
messages.each do |message|
|
34
|
+
write_one(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def flush
|
39
|
+
@io && @io.flush
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset
|
43
|
+
close
|
44
|
+
end
|
45
|
+
|
46
|
+
def close(opts = {})
|
47
|
+
close!
|
48
|
+
rescue => e
|
49
|
+
log_error(e)
|
50
|
+
end
|
51
|
+
|
52
|
+
def close!
|
53
|
+
@io && @io.close
|
54
|
+
ensure
|
55
|
+
@io = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def unrecoverable_error?(e)
|
59
|
+
e.is_a?(JSON::GeneratorError)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def log_error(e)
|
65
|
+
error_logger.error "[#{self.class}] #{e.class} - #{e.message}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def log_warning(message)
|
69
|
+
error_logger.warn("[#{self.class}] #{message}")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'logstash-logger/buffer'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class Connectable < Base
|
6
|
+
include LogStashLogger::Buffer
|
7
|
+
|
8
|
+
attr_accessor :buffer_logger
|
9
|
+
|
10
|
+
def initialize(opts = {})
|
11
|
+
super
|
12
|
+
|
13
|
+
if opts[:batch_events]
|
14
|
+
warn "The :batch_events option is deprecated. Please use :buffer_max_items instead"
|
15
|
+
end
|
16
|
+
|
17
|
+
if opts[:batch_timeout]
|
18
|
+
warn "The :batch_timeout option is deprecated. Please use :buffer_max_interval instead"
|
19
|
+
end
|
20
|
+
|
21
|
+
@buffer_group = nil
|
22
|
+
@buffer_max_items = opts[:batch_events] || opts[:buffer_max_items]
|
23
|
+
@buffer_max_interval = opts[:batch_timeout] || opts[:buffer_max_interval]
|
24
|
+
@drop_messages_on_flush_error =
|
25
|
+
if opts.key?(:drop_messages_on_flush_error)
|
26
|
+
opts.delete(:drop_messages_on_flush_error)
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
@drop_messages_on_full_buffer =
|
32
|
+
if opts.key?(:drop_messages_on_full_buffer)
|
33
|
+
opts.delete(:drop_messages_on_full_buffer)
|
34
|
+
else
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
@buffer_flush_at_exit =
|
39
|
+
if opts.key?(:buffer_flush_at_exit)
|
40
|
+
opts.delete(:buffer_flush_at_exit)
|
41
|
+
else
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
@buffer_logger = opts[:buffer_logger]
|
46
|
+
|
47
|
+
buffer_initialize(
|
48
|
+
max_items: @buffer_max_items,
|
49
|
+
max_interval: @buffer_max_interval,
|
50
|
+
logger: buffer_logger,
|
51
|
+
autoflush: @sync,
|
52
|
+
drop_messages_on_flush_error: @drop_messages_on_flush_error,
|
53
|
+
drop_messages_on_full_buffer: @drop_messages_on_full_buffer,
|
54
|
+
flush_at_exit: @buffer_flush_at_exit
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def write(message)
|
59
|
+
buffer_receive(message, @buffer_group) unless message.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
def flush(*args)
|
63
|
+
if args.empty?
|
64
|
+
buffer_flush
|
65
|
+
else
|
66
|
+
messages, group = *args
|
67
|
+
write_batch(messages, group)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_full_buffer_receive(data)
|
72
|
+
log_warning("Buffer Full - #{data}")
|
73
|
+
end
|
74
|
+
|
75
|
+
def close(opts = {})
|
76
|
+
if opts.fetch(:flush, true)
|
77
|
+
buffer_flush(final: true)
|
78
|
+
end
|
79
|
+
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_io
|
84
|
+
with_connection do
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def connected?
|
90
|
+
!!@io
|
91
|
+
end
|
92
|
+
|
93
|
+
def write_one(message)
|
94
|
+
with_connection do
|
95
|
+
super
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def write_batch(messages, group = nil)
|
100
|
+
with_connection do
|
101
|
+
super
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Implemented by subclasses
|
106
|
+
def connect
|
107
|
+
fail NotImplementedError
|
108
|
+
end
|
109
|
+
|
110
|
+
def reset
|
111
|
+
reset_buffer
|
112
|
+
close(flush: false)
|
113
|
+
end
|
114
|
+
|
115
|
+
def reconnect
|
116
|
+
close(flush: false)
|
117
|
+
connect
|
118
|
+
end
|
119
|
+
|
120
|
+
# Ensure the block is executed with a valid connection
|
121
|
+
def with_connection(&block)
|
122
|
+
connect unless connected?
|
123
|
+
yield
|
124
|
+
rescue => e
|
125
|
+
log_error(e)
|
126
|
+
close(flush: false)
|
127
|
+
raise
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module LogStashLogger
|
4
|
+
module Device
|
5
|
+
class File < Base
|
6
|
+
def initialize(opts)
|
7
|
+
super
|
8
|
+
@path = opts[:path] || fail(ArgumentError, "Path is required")
|
9
|
+
open
|
10
|
+
end
|
11
|
+
|
12
|
+
def open
|
13
|
+
unless ::File.exist? ::File.dirname @path
|
14
|
+
::FileUtils.mkdir_p ::File.dirname @path
|
15
|
+
end
|
16
|
+
|
17
|
+
@io = ::File.open @path, ::File::WRONLY | ::File::APPEND | ::File::CREAT
|
18
|
+
@io.binmode
|
19
|
+
@io.sync = self.sync
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
begin
|
2
|
+
require 'aws-sdk-firehose'
|
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 Firehose < AwsStream
|
12
|
+
@stream_class = ::Aws::Firehose::Client
|
13
|
+
@recoverable_error_codes = [
|
14
|
+
"ServiceUnavailable",
|
15
|
+
"InternalFailure",
|
16
|
+
"ServiceUnavailableException"
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def transform_message(message)
|
20
|
+
{
|
21
|
+
data: message
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def put_records(records)
|
26
|
+
@io.put_record_batch({
|
27
|
+
records: records,
|
28
|
+
delivery_stream_name: @stream
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_successful_response(resp)
|
33
|
+
resp.failed_put_count == 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_response_records(resp)
|
37
|
+
resp.request_responses
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|