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,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
|